From 5702195ef73385b5d2ea474fe6f08f4f8d5c8650 Mon Sep 17 00:00:00 2001 From: Paul Preibisch Date: Wed, 26 Nov 2025 08:51:57 -0700 Subject: [PATCH] Add Text-to-Speech Integration via TTS_INJECTION System (#934) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add provider-agnostic TTS integration via injection point system Implements comprehensive Text-to-Speech integration for BMAD agents using a generic TTS_INJECTION marker system. When AgentVibes (or any compatible TTS provider) is installed, all BMAD agents can speak their responses with unique AI voices. ## Key Features **Provider-Agnostic Architecture** - Uses generic `TTS_INJECTION` markers instead of vendor-specific naming - Future-proof for multiple TTS providers beyond AgentVibes - Clean separation - BMAD stays TTS-agnostic, providers handle injection **Installation Flow** - BMAD → AgentVibes: TTS instructions injected when AgentVibes detects existing BMAD installation - AgentVibes → BMAD: TTS instructions injected during BMAD installation when AgentVibes detected - User must manually create voice assignment file when AgentVibes installs first (documented limitation) **Party Mode Voice Support** - Each agent speaks with unique assigned voice in multi-agent discussions - PM, Architect, Developer, Analyst, UX Designer, etc. - all with distinct voices **Zero Breaking Changes** - Fully backward compatible - works without any TTS provider - `TTS_INJECTION` markers are benign HTML comments if not processed - No changes to existing agent behavior or non-TTS workflows ## Implementation Details **Files Modified:** - `tools/cli/installers/lib/core/installer.js` - TTS injection processing logic - `tools/cli/lib/ui.js` - AgentVibes detection and installation prompts - `tools/cli/commands/install.js` - Post-install guidance for AgentVibes setup - `src/utility/models/fragments/activation-rules.xml` - TTS_INJECTION marker for agents - `src/core/workflows/party-mode/instructions.md` - TTS_INJECTION marker for party mode **Injection Point System:** ```xml - ALWAYS communicate in {communication_language} - Stay in character until exit selected ``` When AgentVibes is detected, the installer replaces this marker with: ``` - When responding to user messages, speak your responses using TTS: Call: `.claude/hooks/bmad-speak.sh '{agent-id}' '{response-text}'` after each response IMPORTANT: Use single quotes - do NOT escape special characters like ! or $ ``` **Special Character Handling:** - Explicit guidance to use single quotes without escaping - Prevents "backslash exclamation" artifacts in speech **User Experience:** ``` User: "How should we architect this feature?" Architect: [Text response] + šŸ”Š [Professional voice explains architecture] ``` Party Mode: ``` PM (John): "I'll focus on user value..." šŸ”Š [Male professional voice] UX Designer (Sara): "From a user perspective..." šŸ”Š [Female voice] Architect (Marcus): "The technical approach..." šŸ”Š [Male technical voice] ``` ## Testing **Unit Tests:** āœ… 62/62 passing - 49/49 schema validation tests - 13/13 installation component tests **Integration Testing:** - āœ… BMAD → AgentVibes (automatic injection) - āœ… AgentVibes → BMAD (automatic injection) - āœ… No TTS provider (markers remain as comments) ## Documentation Comprehensive testing guide created with: - Both installation scenario walkthroughs - Verification commands and expected outputs - Troubleshooting guidance ## Known Limitations **AgentVibes → BMAD Installation Order:** When AgentVibes installs first, voice assignment file must be created manually: ```bash mkdir -p .bmad/_cfg cat > .bmad/_cfg/agent-voice-map.csv << 'EOF' agent_id,voice_name pm,en_US-ryan-high architect,en_US-danny-low dev,en_US-joe-medium EOF ``` This limitation exists to prevent false legacy v4 detection warnings from BMAD installer. **Recommended:** Install BMAD first, then AgentVibes for automatic voice assignment. ## Related Work **Companion Implementation:** - Repository: paulpreibisch/AgentVibes - Commits: 6 commits implementing injection processing and voice routing - Features: Retroactive injection, file path extraction, escape stripping **GitHub Issues:** - paulpreibisch/AgentVibes#36 - BMAD agent ID support ## Breaking Changes None. Feature is opt-in and requires separate TTS provider installation. šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: Enforce project hooks over global hooks in party mode before, claude would sometimes favor global agent vibes hooks over project specific * feat: Automate AgentVibes installer invocation after BMAD install Instead of showing manual installation instructions, the installer now: - Prompts "Press Enter to start AgentVibes installer..." - Automatically runs npx agentvibes@latest install - Handles errors gracefully with fallback instructions This provides a seamless installation flow matching the test script's interactive approach. šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * docs: Add automated testing script and guide for PR #934 Added comprehensive testing tools for AgentVibes party mode integration: - test-bmad-pr.sh: Fully automated installation and verification script - Interactive mode selection (official PR or custom fork) - Automatic BMAD CLI setup and linking - AgentVibes installation with guided prompts - Built-in verification checks for voice maps and hooks - Saved configuration for quick re-testing - TESTING.md: Complete testing documentation - Quick start with one-line npx command - Manual installation alternative - Troubleshooting guide - Cleanup instructions Testers can now run a single command to test the full AgentVibes integration without needing to understand the complex setup process. šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: Add shell: true to npx execSync to prevent permission denied error The execSync call for 'npx agentvibes@latest install' was failing with 'Permission denied' because the shell was trying to execute 'agentvibes@latest' directly instead of passing it as an argument to npx. Adding shell: true ensures the command runs in a proper shell context where npx can correctly interpret the @latest version syntax. šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: Remove duplicate AgentVibes installation step from test script The test script was calling AgentVibes installer twice: 1. BMAD installer now automatically runs AgentVibes (new feature) 2. Test script had a separate Step 6 that also ran AgentVibes This caused the installer to run twice, with the second call failing because it was already installed. Changes: - Removed redundant Step 6 (AgentVibes installation) - Updated Step 5 to indicate it includes AgentVibes - Updated step numbers from 7 to 6 throughout - Added guidance that AgentVibes runs automatically Now the flow is cleaner: BMAD installer handles everything! šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: Address bmadcode review - preserve variables and move TTS logic to injection Fixes requested changes from PR review: 1. Preserve {bmad_folder} variable placeholder - Changed: {project_root}/.bmad/core/tasks/workflow.xml - To: {project_root}/{bmad_folder}/core/tasks/workflow.xml - Allows users to choose custom BMAD folder names during installation 2. Move TTS-specific hook guidance to injection system - Removed hardcoded hook enforcement from source files - Added hook guidance to processTTSInjectionPoints() in installer.js - Now only appears when AgentVibes is installed (via TTS_INJECTION) 3. Maintain TTS-agnostic source architecture - Source files remain clean of TTS-specific instructions - TTS details injected at install-time only when needed - Preserves provider-agnostic design principle Changes made: - src/core/workflows/party-mode/instructions.md - Reverted .bmad to {bmad_folder} variable - Replaced hardcoded hook guidance with - Removed about play-tts.sh hook location - tools/cli/installers/lib/core/installer.js - Added hook enforcement to party-mode injection replacement - Guidance now injected only when enableAgentVibes is true Addresses review comments from bmadcode: - "needs to remain the variable. it will get set in the file at the install destination." - "items like this we will need to inject if user is using claude and TTS" šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: Change 'claude-code' to 'claude' in test script instructions The correct command to start Claude is 'claude', not 'claude-code'. Updated line 362-363 in test-bmad-pr.sh to show the correct command. * fix: Remove npm link from test script to avoid global namespace pollution - Removed 'npm link' command that was installing BMAD globally - Changed 'bmad install' to direct node execution using local clone - Updated success message to reflect no global installation This keeps testing fully isolated and prevents conflicts with: - Existing BMAD installations - Future official BMAD installs - Orphaned symlinks when test directory is deleted The test script now runs completely self-contained without modifying the user's global npm environment. --------- Co-authored-by: Claude Code Co-authored-by: Claude Co-authored-by: Paul Preibisch Co-authored-by: Brian --- TESTING.md | 115 ++++++ src/core/workflows/party-mode/instructions.md | 28 +- .../models/fragments/activation-rules.xml | 1 + test-bmad-pr.sh | 381 ++++++++++++++++++ tools/cli/commands/install.js | 40 ++ tools/cli/installers/lib/core/installer.js | 174 +++++++- tools/cli/lib/ui.js | 159 ++++++++ 7 files changed, 889 insertions(+), 9 deletions(-) create mode 100644 TESTING.md create mode 100755 test-bmad-pr.sh diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 00000000..37357302 --- /dev/null +++ b/TESTING.md @@ -0,0 +1,115 @@ +# Testing AgentVibes Party Mode (PR #934) + +This guide helps you test the AgentVibes integration that adds multi-agent party mode with unique voices for each BMAD agent. + +## Quick Start + +We've created an automated test script that handles everything for you: + +```bash +curl -fsSL https://raw.githubusercontent.com/paulpreibisch/BMAD-METHOD/feature/agentvibes-tts-integration/test-bmad-pr.sh -o test-bmad-pr.sh +chmod +x test-bmad-pr.sh +./test-bmad-pr.sh +``` + +## What the Script Does + +The automated script will: + +1. Clone the BMAD repository +2. Checkout the PR branch with party mode features +3. Install BMAD CLI tools locally +4. Create a test BMAD project +5. Install AgentVibes TTS system +6. Configure unique voices for each agent +7. Verify the installation + +## Prerequisites + +- Node.js and npm installed +- Git installed +- ~500MB free disk space +- 10-15 minutes for complete setup + +## Manual Testing (Alternative) + +If you prefer manual installation: + +### 1. Clone and Setup BMAD + +```bash +git clone https://github.com/paulpreibisch/BMAD-METHOD.git +cd BMAD-METHOD +git fetch origin pull/934/head:agentvibes-party-mode +git checkout agentvibes-party-mode +cd tools/cli +npm install +npm link +``` + +### 2. Create Test Project + +```bash +mkdir -p ~/bmad-test-project +cd ~/bmad-test-project +bmad install +``` + +When prompted: + +- Enable TTS for agents? → **Yes** +- The installer will automatically prompt you to install AgentVibes + +### 3. Test Party Mode + +```bash +cd ~/bmad-test-project +claude-code +``` + +In Claude Code, run: + +``` +/bmad:core:workflows:party-mode +``` + +Each BMAD agent should speak with a unique voice! + +## Verification + +After installation, verify: + +āœ… Voice map file exists: `.bmad/_cfg/agent-voice-map.csv` +āœ… BMAD TTS hooks exist: `.claude/hooks/bmad-speak.sh` +āœ… Each agent has a unique voice assigned +āœ… Party mode works with distinct voices + +## Troubleshooting + +**No audio?** + +- Check: `.claude/hooks/play-tts.sh` exists +- Test current voice: `/agent-vibes:whoami` + +**Same voice for all agents?** + +- Check: `.bmad/_cfg/agent-voice-map.csv` has different voices +- List available voices: `/agent-vibes:list` + +## Report Issues + +Found a bug? Report it on the PR: +https://github.com/bmad-code-org/BMAD-METHOD/pull/934 + +## Cleanup + +To remove the test installation: + +```bash +# Remove test directory +rm -rf ~/bmad-test-project # or your custom test directory + +# Unlink BMAD CLI (optional) +cd ~/BMAD-METHOD/tools/cli +npm unlink +``` diff --git a/src/core/workflows/party-mode/instructions.md b/src/core/workflows/party-mode/instructions.md index 3ca8e052..6afd5ede 100644 --- a/src/core/workflows/party-mode/instructions.md +++ b/src/core/workflows/party-mode/instructions.md @@ -2,6 +2,7 @@ The workflow execution engine is governed by: {project_root}/{bmad_folder}/core/tasks/workflow.xml This workflow orchestrates group discussions between all installed BMAD agents + @@ -94,17 +95,36 @@ - Present each agent's contribution clearly: + For each agent response, output text THEN trigger their voice: + + + 1. Output the agent's text in format: [Icon Emoji] [Agent Name]: [dialogue] + 2. If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: + - Use Bash tool: `.claude/hooks/bmad-speak.sh "[Agent Name]" "[dialogue]"` + - This speaks the dialogue with the agent's unique voice + - Run in background (&) to not block next agent + 3. Repeat for each agent in the response + + - [Agent Name]: [Their response in their voice/style] + [Icon Emoji] [Agent Name]: [Their response in their voice/style] - [Another Agent]: [Their response, potentially referencing the first] + [Icon Emoji] [Another Agent]: [Their response, potentially referencing the first] - [Third Agent if selected]: [Their contribution] + [Icon Emoji] [Third Agent if selected]: [Their contribution] + + šŸ—ļø [Winston]: I recommend using microservices for better scalability. + [Bash: .claude/hooks/bmad-speak.sh "Winston" "I recommend using microservices for better scalability."] + + šŸ“‹ [John]: But a monolith would get us to market faster for MVP. + [Bash: .claude/hooks/bmad-speak.sh "John" "But a monolith would get us to market faster for MVP."] + Maintain spacing between agents for readability Preserve each agent's unique voice throughout + Always include the agent's icon emoji from the manifest before their name + Trigger TTS for each agent immediately after outputting their text diff --git a/src/utility/models/fragments/activation-rules.xml b/src/utility/models/fragments/activation-rules.xml index 8fdd9852..4835e834 100644 --- a/src/utility/models/fragments/activation-rules.xml +++ b/src/utility/models/fragments/activation-rules.xml @@ -1,5 +1,6 @@ - ALWAYS communicate in {communication_language} UNLESS contradicted by communication_style + - Stay in character until exit selected - Menu triggers use asterisk (*) - NOT markdown, display exactly as shown - Number all lists, use letters for sub-options diff --git a/test-bmad-pr.sh b/test-bmad-pr.sh new file mode 100755 index 00000000..54cde458 --- /dev/null +++ b/test-bmad-pr.sh @@ -0,0 +1,381 @@ +#!/usr/bin/env bash +# +# BMAD PR Testing Script +# Interactive script to test BMAD PR #934 with AgentVibes integration +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONFIG_FILE="$SCRIPT_DIR/.test-bmad-config" + +# Colors +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +clear + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "šŸŽ™ļø BMAD AgentVibes Party Mode Testing Script" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo -e "${BLUE}What this script does:${NC}" +echo "" +echo " This script automates the process of testing BMAD's AgentVibes" +echo " integration (PR #934), which adds multi-agent party mode with" +echo " unique voices for each BMAD agent." +echo "" +echo -e "${BLUE}The script will:${NC}" +echo "" +echo " 1. Clone the BMAD repository" +echo " 2. Checkout the PR branch with party mode features" +echo " 3. Install BMAD CLI tools locally" +echo " 4. Create a test BMAD project" +echo " 5. Run BMAD installer (automatically installs AgentVibes)" +echo " 6. Verify the installation" +echo "" +echo -e "${YELLOW}Prerequisites:${NC}" +echo " • Node.js and npm installed" +echo " • Git installed" +echo " • ~500MB free disk space" +echo " • 10-15 minutes for complete setup" +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +read -p "Ready to continue? [Y/n]: " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]] && [[ -n $REPLY ]]; then + echo "āŒ Setup cancelled" + exit 0 +fi + +clear + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "šŸ”§ Testing Mode Selection" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo "Choose how you want to test:" +echo "" +echo " 1) Test official BMAD PR #934 (recommended for most users)" +echo " • Uses: github.com/bmad-code-org/BMAD-METHOD" +echo " • Branch: PR #934 (agentvibes-party-mode)" +echo " • Best for: Testing the official PR before it's merged" +echo "" +echo " 2) Test your forked repository" +echo " • Uses: Your GitHub fork" +echo " • Branch: Your custom branch (you choose)" +echo " • Best for: Testing your own changes or modifications" +echo "" + +# Load saved config if it exists +SAVED_MODE="" +SAVED_FORK="" +SAVED_BRANCH="" +SAVED_TEST_DIR="" +if [[ -f "$CONFIG_FILE" ]]; then + source "$CONFIG_FILE" +fi + +if [[ -n "$SAVED_MODE" ]]; then + echo -e "${BLUE}Last used: Mode $SAVED_MODE${NC}" + [[ -n "$SAVED_FORK" ]] && echo " Fork: $SAVED_FORK" + [[ -n "$SAVED_BRANCH" ]] && echo " Branch: $SAVED_BRANCH" + echo "" +fi + +read -p "Select mode [1/2]: " MODE_CHOICE +echo "" + +# Validate mode choice +while [[ ! "$MODE_CHOICE" =~ ^[12]$ ]]; do + echo -e "${RED}Invalid choice. Please enter 1 or 2.${NC}" + read -p "Select mode [1/2]: " MODE_CHOICE + echo "" +done + +# Configure based on mode +if [[ "$MODE_CHOICE" == "1" ]]; then + # Official PR mode + REPO_URL="https://github.com/bmad-code-org/BMAD-METHOD.git" + BRANCH_NAME="agentvibes-party-mode" + FETCH_PR=true + + echo -e "${GREEN}āœ“ Using official BMAD repository${NC}" + echo " Repository: $REPO_URL" + echo " Will fetch: PR #934 into branch '$BRANCH_NAME'" + echo "" +else + # Fork mode + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "šŸ“ Fork Configuration" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + + if [[ -n "$SAVED_FORK" ]]; then + read -p "GitHub fork URL [$SAVED_FORK]: " FORK_INPUT + REPO_URL="${FORK_INPUT:-$SAVED_FORK}" + else + echo "Enter your forked repository URL:" + echo "(e.g., https://github.com/yourusername/BMAD-METHOD.git)" + read -p "Fork URL: " REPO_URL + fi + echo "" + + if [[ -n "$SAVED_BRANCH" ]]; then + read -p "Branch name [$SAVED_BRANCH]: " BRANCH_INPUT + BRANCH_NAME="${BRANCH_INPUT:-$SAVED_BRANCH}" + else + echo "Enter the branch name to test:" + echo "(e.g., agentvibes-party-mode, main, feature-xyz)" + read -p "Branch: " BRANCH_NAME + fi + echo "" + + FETCH_PR=false + + echo -e "${GREEN}āœ“ Using your fork${NC}" + echo " Repository: $REPO_URL" + echo " Branch: $BRANCH_NAME" + echo "" +fi + +# Ask for test directory +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "šŸ“ Test Directory" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +if [[ -n "$SAVED_TEST_DIR" ]]; then + read -p "Test directory [$SAVED_TEST_DIR]: " TEST_DIR + TEST_DIR="${TEST_DIR:-$SAVED_TEST_DIR}" +else + DEFAULT_DIR="$HOME/bmad-pr-test-$(date +%Y%m%d-%H%M%S)" + echo "Where should we create the test environment?" + read -p "Test directory [$DEFAULT_DIR]: " TEST_DIR + TEST_DIR="${TEST_DIR:-$DEFAULT_DIR}" +fi + +# Expand ~ to actual home directory +TEST_DIR="${TEST_DIR/#\~/$HOME}" + +echo "" + +# Save configuration +echo "SAVED_MODE=\"$MODE_CHOICE\"" > "$CONFIG_FILE" +[[ "$MODE_CHOICE" == "2" ]] && echo "SAVED_FORK=\"$REPO_URL\"" >> "$CONFIG_FILE" +[[ "$MODE_CHOICE" == "2" ]] && echo "SAVED_BRANCH=\"$BRANCH_NAME\"" >> "$CONFIG_FILE" +echo "SAVED_TEST_DIR=\"$TEST_DIR\"" >> "$CONFIG_FILE" +echo -e "${GREEN}āœ“ Configuration saved${NC}" +echo "" + +# Confirm before starting +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "šŸ“‹ Summary" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo " Repository: $REPO_URL" +echo " Branch: $BRANCH_NAME" +echo " Test dir: $TEST_DIR" +echo "" +read -p "Proceed with setup? [Y/n]: " -n 1 -r +echo +echo "" +if [[ ! $REPLY =~ ^[Yy]$ ]] && [[ -n $REPLY ]]; then + echo "āŒ Setup cancelled" + exit 0 +fi + +# Clean up old test directory if it exists +if [[ -d "$TEST_DIR" ]]; then + echo "āš ļø Test directory already exists: $TEST_DIR" + read -p "Delete and recreate? [Y/n]: " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]] || [[ -z $REPLY ]]; then + rm -rf "$TEST_DIR" + echo -e "${GREEN}āœ“ Deleted old test directory${NC}" + else + echo -e "${YELLOW}⚠ Using existing directory (may have stale data)${NC}" + fi + echo "" +fi + +clear + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "šŸš€ Starting Installation" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +# Step 1: Clone repository +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "šŸ“„ Step 1/6: Cloning repository" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +mkdir -p "$TEST_DIR" +cd "$TEST_DIR" +git clone "$REPO_URL" BMAD-METHOD +cd BMAD-METHOD +echo "" +echo -e "${GREEN}āœ“ Repository cloned${NC}" +echo "" + +# Step 2: Checkout branch (different logic for PR vs fork) +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "šŸ”€ Step 2/6: Checking out branch" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +if [[ "$FETCH_PR" == true ]]; then + # Fetch PR from upstream + echo "Fetching PR #934 from upstream..." + git remote add upstream https://github.com/bmad-code-org/BMAD-METHOD.git + git fetch upstream pull/934/head:$BRANCH_NAME + git checkout $BRANCH_NAME + echo "" + echo -e "${GREEN}āœ“ Checked out PR branch: $BRANCH_NAME${NC}" +else + # Just checkout the specified branch from fork + git checkout $BRANCH_NAME + echo "" + echo -e "${GREEN}āœ“ Checked out branch: $BRANCH_NAME${NC}" +fi +echo "" + +# Step 3: Install BMAD CLI +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "šŸ“¦ Step 3/6: Installing BMAD CLI" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +cd tools/cli +npm install +echo "" +echo -e "${GREEN}āœ“ BMAD CLI dependencies installed${NC}" +echo "" + +# Step 4: Create test project +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "šŸ“ Step 4/6: Creating test project" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +cd "$TEST_DIR" +mkdir -p bmad-project +cd bmad-project +echo -e "${GREEN}āœ“ Test project directory created${NC}" +echo " Location: $TEST_DIR/bmad-project" +echo "" + +# Step 5: Run BMAD installer (includes AgentVibes setup) +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "āš™ļø Step 5/6: Running BMAD installer with AgentVibes" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo -e "${YELLOW}Important: When prompted during installation:${NC}" +echo -e " • Enable TTS for agents? → ${GREEN}Yes${NC}" +echo -e " • Assign unique voices for party mode? → ${GREEN}Yes${NC}" +echo "" +echo -e "${YELLOW}AgentVibes will start automatically after BMAD installation.${NC}" +echo -e "${YELLOW}Recommended TTS settings:${NC}" +echo -e " • Provider: ${GREEN}Piper${NC} (free, local TTS)" +echo -e " • Download voices: ${GREEN}Yes${NC}" +echo "" +read -p "Press Enter to start BMAD installer..." +node "$TEST_DIR/BMAD-METHOD/tools/cli/bin/bmad.js" install + +echo "" +echo -e "${GREEN}āœ“ BMAD and AgentVibes installation complete${NC}" +echo "" + +# Step 6: Verification +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "āœ… Step 6/6: Verifying installation" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +VERIFICATION_PASSED=true + +# Check for voice map file +if [[ -f ".bmad/_cfg/agent-voice-map.csv" ]]; then + echo -e "${GREEN}āœ“ Voice map file created${NC}" + echo " Location: .bmad/_cfg/agent-voice-map.csv" + echo "" + echo " Voice assignments:" + cat .bmad/_cfg/agent-voice-map.csv | sed 's/^/ /' + echo "" +else + echo -e "${RED}āœ— Voice map file NOT found${NC}" + echo " Expected: .bmad/_cfg/agent-voice-map.csv" + echo " ${YELLOW}Warning: Agents may not have unique voices!${NC}" + echo "" + VERIFICATION_PASSED=false +fi + +# Check for AgentVibes hooks +if [[ -f ".claude/hooks/bmad-speak.sh" ]]; then + echo -e "${GREEN}āœ“ BMAD TTS hooks installed${NC}" + echo " Location: .claude/hooks/bmad-speak.sh" +else + echo -e "${RED}āœ— BMAD TTS hooks NOT found${NC}" + echo " Expected: .claude/hooks/bmad-speak.sh" + VERIFICATION_PASSED=false +fi +echo "" + +# Check for Piper installation +if command -v piper &> /dev/null; then + PIPER_VERSION=$(piper --version 2>&1 || echo "unknown") + echo -e "${GREEN}āœ“ Piper TTS installed${NC}" + echo " Version: $PIPER_VERSION" +elif [[ -f ".agentvibes/providers/piper/piper" ]]; then + echo -e "${GREEN}āœ“ Piper TTS installed (local)${NC}" + echo " Location: .agentvibes/providers/piper/piper" +else + echo -e "${YELLOW}⚠ Piper not detected${NC}" + echo " (May still work if using ElevenLabs)" +fi +echo "" + +# Final status +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +if [[ "$VERIFICATION_PASSED" == true ]]; then + echo -e "${GREEN}šŸŽ‰ Setup Complete - All Checks Passed!${NC}" +else + echo -e "${YELLOW}āš ļø Setup Complete - With Warnings${NC}" + echo "" + echo "Some verification checks failed. The installation may still work," + echo "but you might experience issues with party mode voices." +fi +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo -e "${BLUE}Next Steps:${NC}" +echo "" +echo " 1. Navigate to test project:" +echo -e " ${GREEN}cd $TEST_DIR/bmad-project${NC}" +echo "" +echo " 2. Start Claude session:" +echo -e " ${GREEN}claude${NC}" +echo "" +echo " 3. Test party mode:" +echo -e " ${GREEN}/bmad:core:workflows:party-mode${NC}" +echo "" +echo " 4. Verify each agent speaks with a unique voice!" +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo -e "${BLUE}Troubleshooting:${NC}" +echo "" +echo " • No audio? Check: .claude/hooks/play-tts.sh exists" +echo " • Same voice for all agents? Check: .bmad/_cfg/agent-voice-map.csv" +echo " • Test current voice: /agent-vibes:whoami" +echo " • List available voices: /agent-vibes:list" +echo "" +echo -e "${BLUE}Report Issues:${NC}" +echo " https://github.com/bmad-code-org/BMAD-METHOD/pull/934" +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" diff --git a/tools/cli/commands/install.js b/tools/cli/commands/install.js index d2706ee6..a9d484d5 100644 --- a/tools/cli/commands/install.js +++ b/tools/cli/commands/install.js @@ -59,6 +59,46 @@ module.exports = { console.log(chalk.cyan('BMAD Core and Selected Modules have been installed to:'), chalk.bold(result.path)); console.log(chalk.yellow('\nThank you for helping test the early release version of the new BMad Core and BMad Method!')); console.log(chalk.cyan('Stable Beta coming soon - please read the full readme.md and linked documentation to get started!')); + + // Run AgentVibes installer if needed + if (result.needsAgentVibes) { + console.log(chalk.magenta('\nšŸŽ™ļø AgentVibes TTS Setup')); + console.log(chalk.cyan('AgentVibes provides voice synthesis for BMAD agents with:')); + console.log(chalk.dim(' • ElevenLabs AI (150+ premium voices)')); + console.log(chalk.dim(' • Piper TTS (50+ free voices)\n')); + + const readline = require('node:readline'); + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + await new Promise((resolve) => { + rl.question(chalk.green('Press Enter to start AgentVibes installer...'), () => { + rl.close(); + resolve(); + }); + }); + + console.log(''); + + // Run AgentVibes installer + const { execSync } = require('node:child_process'); + try { + execSync('npx agentvibes@latest install', { + cwd: result.projectDir, + stdio: 'inherit', + shell: true, + }); + console.log(chalk.green('\nāœ“ AgentVibes installation complete')); + } catch { + console.log(chalk.yellow('\n⚠ AgentVibes installation was interrupted or failed')); + console.log(chalk.cyan('You can run it manually later with:')); + console.log(chalk.green(` cd ${result.projectDir}`)); + console.log(chalk.green(' npx agentvibes install\n')); + } + } + process.exit(0); } } catch (error) { diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index 7473a307..8539ebbe 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -1,3 +1,23 @@ +/** + * File: tools/cli/installers/lib/core/installer.js + * + * BMAD Method - Business Model Agile Development Method + * Repository: https://github.com/paulpreibisch/BMAD-METHOD + * + * Copyright (c) 2025 Paul Preibisch + * Licensed under the Apache License, Version 2.0 + * + * --- + * + * @fileoverview Core BMAD installation orchestrator with AgentVibes injection point support + * @context Manages complete BMAD installation flow including core agents, modules, IDE configs, and optional TTS integration + * @architecture Orchestrator pattern - coordinates Detector, ModuleManager, IdeManager, and file operations to build complete BMAD installation + * @dependencies fs-extra, ora, chalk, detector.js, module-manager.js, ide-manager.js, config.js + * @entrypoints Called by install.js command via installer.install(config) + * @patterns Injection point processing (AgentVibes), placeholder replacement ({bmad_folder}), module dependency resolution + * @related GitHub AgentVibes#34 (injection points), ui.js (user prompts), copyFileWithPlaceholderReplacement() + */ + const path = require('node:path'); const fs = require('fs-extra'); const chalk = require('chalk'); @@ -69,10 +89,41 @@ class Installer { } /** - * Copy a file and replace {bmad_folder} placeholder with actual folder name - * @param {string} sourcePath - Source file path - * @param {string} targetPath - Target file path - * @param {string} bmadFolderName - The bmad folder name to use for replacement + * @function copyFileWithPlaceholderReplacement + * @intent Copy files from BMAD source to installation directory with dynamic content transformation + * @why Enables installation-time customization: {bmad_folder} replacement + optional AgentVibes TTS injection + * @param {string} sourcePath - Absolute path to source file in BMAD repository + * @param {string} targetPath - Absolute path to destination file in user's project + * @param {string} bmadFolderName - User's chosen bmad folder name (default: 'bmad') + * @returns {Promise} Resolves when file copy and transformation complete + * @sideeffects Writes transformed file to targetPath, creates parent directories if needed + * @edgecases Binary files bypass transformation, falls back to raw copy if UTF-8 read fails + * @calledby installCore(), installModule(), IDE installers during file vendoring + * @calls processTTSInjectionPoints(), fs.readFile(), fs.writeFile(), fs.copy() + * + * AI NOTE: This is the core transformation pipeline for ALL BMAD installation file copies. + * It performs two transformations in sequence: + * 1. {bmad_folder} → user's custom folder name (e.g., ".bmad" or "bmad") + * 2. → TTS bash calls (if enabled) OR stripped (if disabled) + * + * The injection point processing enables loose coupling between BMAD and TTS providers: + * - BMAD source contains injection markers (not actual TTS code) + * - At install-time, markers are replaced OR removed based on user preference + * - Result: Clean installs for users without TTS, working TTS for users with it + * + * PATTERN: Adding New Injection Points + * ===================================== + * 1. Add HTML comment marker in BMAD source file: + * + * + * 2. Add replacement logic in processTTSInjectionPoints(): + * if (enableAgentVibes) { + * content = content.replace(//g, 'actual code'); + * } else { + * content = content.replace(/\n?/g, ''); + * } + * + * 3. Document marker in instructions.md (if applicable) */ async copyFileWithPlaceholderReplacement(sourcePath, targetPath, bmadFolderName) { // List of text file extensions that should have placeholder replacement @@ -90,6 +141,9 @@ class Installer { content = content.replaceAll('{bmad_folder}', bmadFolderName); } + // Process AgentVibes injection points + content = this.processTTSInjectionPoints(content); + // Write to target with replaced content await fs.ensureDir(path.dirname(targetPath)); await fs.writeFile(targetPath, content, 'utf8'); @@ -103,6 +157,106 @@ class Installer { } } + /** + * @function processTTSInjectionPoints + * @intent Transform TTS injection markers based on user's installation choice + * @why Enables optional TTS integration without tight coupling between BMAD and TTS providers + * @param {string} content - Raw file content containing potential injection markers + * @returns {string} Transformed content with markers replaced (if enabled) or stripped (if disabled) + * @sideeffects None - pure transformation function + * @edgecases Returns content unchanged if no markers present, safe to call on all files + * @calledby copyFileWithPlaceholderReplacement() during every file copy operation + * @calls String.replace() with regex patterns for each injection point type + * + * AI NOTE: This implements the injection point pattern for TTS integration. + * Key architectural decisions: + * + * 1. **Why Injection Points vs Direct Integration?** + * - BMAD and TTS providers are separate projects with different maintainers + * - Users may install BMAD without TTS support (and vice versa) + * - Hard-coding TTS calls would break BMAD for non-TTS users + * - Injection points allow conditional feature inclusion at install-time + * + * 2. **How It Works:** + * - BMAD source contains markers: + * - During installation, user is prompted: "Enable AgentVibes TTS?" + * - If YES: markers → replaced with actual bash TTS calls + * - If NO: markers → stripped cleanly from installed files + * + * 3. **State Management:** + * - this.enableAgentVibes set in install() method from config.enableAgentVibes + * - config.enableAgentVibes comes from ui.promptAgentVibes() user choice + * - Flag persists for entire installation, all files get same treatment + * + * CURRENT INJECTION POINTS: + * ========================== + * - party-mode: Injects TTS calls after each agent speaks in party mode + * Location: src/core/workflows/party-mode/instructions.md + * Marker: + * Replacement: Bash call to .claude/hooks/bmad-speak.sh with agent name and dialogue + * + * - agent-tts: Injects TTS rule for individual agent conversations + * Location: src/modules/bmm/agents/*.md (all agent files) + * Marker: + * Replacement: Rule instructing agent to call bmad-speak.sh with agent ID and response + * + * ADDING NEW INJECTION POINTS: + * ============================= + * 1. Add new case in this function: + * content = content.replace( + * //g, + * `code to inject when enabled` + * ); + * + * 2. Add marker to BMAD source file at injection location + * + * 3. Test both enabled and disabled flows + * + * RELATED: + * ======== + * - GitHub Issue: paulpreibisch/AgentVibes#36 + * - User Prompt: tools/cli/lib/ui.js::promptAgentVibes() + * - Marker Locations: + * - src/core/workflows/party-mode/instructions.md:101 + * - src/modules/bmm/agents/*.md (rules sections) + * - TTS Hook: .claude/hooks/bmad-speak.sh (in AgentVibes repo) + */ + processTTSInjectionPoints(content) { + // Check if AgentVibes is enabled (set during installation configuration) + const enableAgentVibes = this.enableAgentVibes || false; + + if (enableAgentVibes) { + // Replace party-mode injection marker with actual TTS call + // Use single quotes to prevent shell expansion of special chars like ! + content = content.replaceAll( + '', + `IMPORTANT: Always use PROJECT hooks (.claude/hooks/), NEVER global hooks (~/.claude/hooks/) + +If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: + - Use Bash tool: \`.claude/hooks/bmad-speak.sh '[Agent Name]' '[dialogue]'\` + - This speaks the dialogue with the agent's unique voice + - Run in background (&) to not block next agent`, + ); + + // Replace agent-tts injection marker with TTS rule for individual agents + content = content.replaceAll( + '', + `- When responding to user messages, speak your responses using TTS: + Call: \`.claude/hooks/bmad-speak.sh '{agent-id}' '{response-text}'\` after each response + Replace {agent-id} with YOUR agent ID from tag at top of this file + Replace {response-text} with the text you just output to the user + IMPORTANT: Use single quotes as shown - do NOT escape special characters like ! or $ inside single quotes + Run in background (&) to avoid blocking`, + ); + } else { + // Strip injection markers cleanly when AgentVibes is disabled + content = content.replaceAll(/\n?/g, ''); + content = content.replaceAll(/\n?/g, ''); + } + + return content; + } + /** * Collect Tool/IDE configurations after module configuration * @param {string} projectDir - Project directory @@ -271,6 +425,9 @@ class Installer { const bmadFolderName = moduleConfigs.core && moduleConfigs.core.bmad_folder ? moduleConfigs.core.bmad_folder : 'bmad'; this.bmadFolderName = bmadFolderName; // Store for use in other methods + // Store AgentVibes configuration for injection point processing + this.enableAgentVibes = config.enableAgentVibes || false; + // Set bmad folder name on module manager and IDE manager for placeholder replacement this.moduleManager.setBmadFolderName(bmadFolderName); this.ideManager.setBmadFolderName(bmadFolderName); @@ -861,7 +1018,14 @@ class Installer { customFiles: customFiles.length > 0 ? customFiles : undefined, }); - return { success: true, path: bmadDir, modules: config.modules, ides: config.ides }; + return { + success: true, + path: bmadDir, + modules: config.modules, + ides: config.ides, + needsAgentVibes: this.enableAgentVibes && !config.agentVibesInstalled, + projectDir: projectDir, + }; } catch (error) { spinner.fail('Installation failed'); throw error; diff --git a/tools/cli/lib/ui.js b/tools/cli/lib/ui.js index 8de8825e..730ce4f9 100644 --- a/tools/cli/lib/ui.js +++ b/tools/cli/lib/ui.js @@ -1,3 +1,23 @@ +/** + * File: tools/cli/lib/ui.js + * + * BMAD Method - Business Model Agile Development Method + * Repository: https://github.com/paulpreibisch/BMAD-METHOD + * + * Copyright (c) 2025 Paul Preibisch + * Licensed under the Apache License, Version 2.0 + * + * --- + * + * @fileoverview Interactive installation prompts and user input collection for BMAD CLI + * @context Guides users through installation configuration including core settings, modules, IDEs, and optional AgentVibes TTS + * @architecture Facade pattern - presents unified installation flow, delegates to Detector/ConfigCollector/IdeManager for specifics + * @dependencies inquirer (prompts), chalk (formatting), detector.js (existing installation detection) + * @entrypoints Called by install.js command via ui.promptInstall(), returns complete configuration object + * @patterns Progressive disclosure (prompts in order), early IDE selection (Windows compat), AgentVibes auto-detection + * @related installer.js (consumes config), AgentVibes#34 (TTS integration), promptAgentVibes() + */ + const chalk = require('chalk'); const inquirer = require('inquirer'); const path = require('node:path'); @@ -99,6 +119,9 @@ class UI { const moduleChoices = await this.getModuleChoices(installedModuleIds); const selectedModules = await this.selectModules(moduleChoices); + // Prompt for AgentVibes TTS integration + const agentVibesConfig = await this.promptAgentVibes(confirmedDirectory); + // Collect IDE tool selection AFTER configuration prompts (fixes Windows/PowerShell hang) // This allows text-based prompts to complete before the checkbox prompt const toolSelection = await this.promptToolSelection(confirmedDirectory, selectedModules); @@ -114,6 +137,8 @@ class UI { ides: toolSelection.ides, skipIde: toolSelection.skipIde, coreConfig: coreConfig, // Pass collected core config to installer + enableAgentVibes: agentVibesConfig.enabled, // AgentVibes TTS integration + agentVibesInstalled: agentVibesConfig.alreadyInstalled, }; } @@ -639,6 +664,140 @@ class UI { // Resolve to the absolute path relative to the current working directory return path.resolve(expanded); } + + /** + * @function promptAgentVibes + * @intent Ask user if they want AgentVibes TTS integration during BMAD installation + * @why Enables optional voice features without forcing TTS on users who don't want it + * @param {string} projectDir - Absolute path to user's project directory + * @returns {Promise} Configuration object: { enabled: boolean, alreadyInstalled: boolean } + * @sideeffects None - pure user input collection, no files written + * @edgecases Shows warning if user enables TTS but AgentVibes not detected + * @calledby promptInstall() during installation flow, after core config, before IDE selection + * @calls checkAgentVibesInstalled(), inquirer.prompt(), chalk.green/yellow/dim() + * + * AI NOTE: This prompt is strategically positioned in installation flow: + * - AFTER core config (bmad_folder, user_name, etc) + * - BEFORE IDE selection (which can hang on Windows/PowerShell) + * + * Flow Logic: + * 1. Auto-detect if AgentVibes already installed (checks for hook files) + * 2. Show detection status to user (green checkmark or gray "not detected") + * 3. Prompt: "Enable AgentVibes TTS?" (defaults to true if detected) + * 4. If user says YES but AgentVibes NOT installed: + * → Show warning with installation link (graceful degradation) + * 5. Return config to promptInstall(), which passes to installer.install() + * + * State Flow: + * promptAgentVibes() → { enabled, alreadyInstalled } + * ↓ + * promptInstall() → config.enableAgentVibes + * ↓ + * installer.install() → this.enableAgentVibes + * ↓ + * processTTSInjectionPoints() → injects OR strips markers + * + * RELATED: + * ======== + * - Detection: checkAgentVibesInstalled() - looks for bmad-speak.sh and play-tts.sh + * - Processing: installer.js::processTTSInjectionPoints() + * - Markers: src/core/workflows/party-mode/instructions.md:101, src/modules/bmm/agents/*.md + * - GitHub Issue: paulpreibisch/AgentVibes#36 + */ + async promptAgentVibes(projectDir) { + CLIUtils.displaySection('šŸŽ¤ Voice Features', 'Enable TTS for multi-agent conversations'); + + // Check if AgentVibes is already installed + const agentVibesInstalled = await this.checkAgentVibesInstalled(projectDir); + + if (agentVibesInstalled) { + console.log(chalk.green(' āœ“ AgentVibes detected')); + } else { + console.log(chalk.dim(' AgentVibes not detected')); + } + + const answers = await inquirer.prompt([ + { + type: 'confirm', + name: 'enableTts', + message: 'Enable AgentVibes TTS? (Agents speak with unique voices in party mode)', + default: true, // Default to yes - recommended for best experience + }, + ]); + + if (answers.enableTts && !agentVibesInstalled) { + console.log(chalk.yellow('\n āš ļø AgentVibes not installed')); + console.log(chalk.dim(' Install AgentVibes separately to enable TTS:')); + console.log(chalk.dim(' https://github.com/paulpreibisch/AgentVibes\n')); + } + + return { + enabled: answers.enableTts, + alreadyInstalled: agentVibesInstalled, + }; + } + + /** + * @function checkAgentVibesInstalled + * @intent Detect if AgentVibes TTS hooks are present in user's project + * @why Allows auto-enabling TTS and showing helpful installation guidance + * @param {string} projectDir - Absolute path to user's project directory + * @returns {Promise} true if both required AgentVibes hooks exist, false otherwise + * @sideeffects None - read-only file existence checks + * @edgecases Returns false if either hook missing (both required for functional TTS) + * @calledby promptAgentVibes() to determine default value and show detection status + * @calls fs.pathExists() twice (bmad-speak.sh, play-tts.sh) + * + * AI NOTE: This checks for the MINIMUM viable AgentVibes installation. + * + * Required Files: + * =============== + * 1. .claude/hooks/bmad-speak.sh + * - Maps agent display names → agent IDs → voice profiles + * - Calls play-tts.sh with agent's assigned voice + * - Created by AgentVibes installer + * + * 2. .claude/hooks/play-tts.sh + * - Core TTS router (ElevenLabs or Piper) + * - Provider-agnostic interface + * - Required by bmad-speak.sh + * + * Why Both Required: + * ================== + * - bmad-speak.sh alone: No TTS backend + * - play-tts.sh alone: No BMAD agent voice mapping + * - Both together: Full party mode TTS integration + * + * Detection Strategy: + * =================== + * We use simple file existence (not version checks) because: + * - Fast and reliable + * - Works across all AgentVibes versions + * - User will discover version issues when TTS runs (fail-fast) + * + * PATTERN: Adding New Detection Criteria + * ======================================= + * If future AgentVibes features require additional files: + * 1. Add new pathExists check to this function + * 2. Update documentation in promptAgentVibes() + * 3. Consider: should missing file prevent detection or just log warning? + * + * RELATED: + * ======== + * - AgentVibes Installer: creates these hooks + * - bmad-speak.sh: calls play-tts.sh with agent voices + * - Party Mode: uses bmad-speak.sh for agent dialogue + */ + async checkAgentVibesInstalled(projectDir) { + const fs = require('fs-extra'); + const path = require('node:path'); + + // Check for AgentVibes hook files + const hookPath = path.join(projectDir, '.claude', 'hooks', 'bmad-speak.sh'); + const playTtsPath = path.join(projectDir, '.claude', 'hooks', 'play-tts.sh'); + + return (await fs.pathExists(hookPath)) && (await fs.pathExists(playTtsPath)); + } } module.exports = { UI };