Skip to main content
Glama

Voice Mode

by mbailey
pronounce_commands.py7.94 kB
"""CLI commands for managing pronunciation rules.""" import click import yaml import json from pathlib import Path from typing import Optional from voice_mode.pronounce import get_manager @click.group(name='pronounce') def pronounce_group(): """Manage pronunciation rules for TTS and STT.""" pass @pronounce_group.command(name='list') @click.option('--direction', '-d', type=click.Choice(['tts', 'stt', 'all']), default='all', help='Filter by direction (tts/stt/all)') @click.option('--enabled-only', '-e', is_flag=True, help='Show only enabled rules') @click.option('--show-private', '-p', is_flag=True, help='Include private rules') @click.option('--format', '-f', type=click.Choice(['table', 'yaml', 'json']), default='table', help='Output format') def list_rules(direction: str, enabled_only: bool, show_private: bool, format: str): """List pronunciation rules.""" manager = get_manager() # Get rules if direction == 'all': rules = manager.list_rules(include_private=show_private) else: rules = manager.list_rules(direction=direction, include_private=show_private) # Filter if needed if enabled_only: rules = [r for r in rules if r['enabled']] # Format output if format == 'table': if not rules: click.echo("No rules found.") return # Count private rules that were hidden all_rules = manager.list_rules(include_private=True) private_count = len(all_rules) - len(rules) # Simple table format without tabulate click.echo("\nPronunciation Rules:") click.echo("=" * 80) for rule in rules: status = '✓' if rule['enabled'] else '✗' click.echo(f"\n{status} [{rule['direction'].upper()}] {rule['name']} (order: {rule['order']})") click.echo(f" Pattern: {rule['pattern']}") click.echo(f" Replace: {rule['replacement']}") if rule['description']: click.echo(f" Desc: {rule['description']}") if private_count > 0 and not show_private: click.echo(f"\n({private_count} private rules hidden. Use --show-private to display)") elif format == 'yaml': import yaml click.echo(yaml.dump(rules, default_flow_style=False)) elif format == 'json': import json click.echo(json.dumps(rules, indent=2)) @pronounce_group.command(name='test') @click.argument('text') @click.option('--direction', '-d', type=click.Choice(['tts', 'stt']), default='tts', help='Test direction (tts/stt)') def test_rule(text: str, direction: str): """Test pronunciation rules on text.""" manager = get_manager() result = manager.test_rule(text, direction) if text != result: click.echo(f"Original: {text}") click.echo(f"Modified: {result}") # Show which rules were applied if logging is enabled import os if os.environ.get('VOICEMODE_PRONUNCIATION_LOG_SUBSTITUTIONS', '').lower() == 'true': click.echo("\n(Check logs for applied rules)") else: click.echo(f"No changes: {text}") @pronounce_group.command(name='add') @click.option('--direction', '-d', type=click.Choice(['tts', 'stt']), required=True, help='Rule direction (tts/stt)') @click.option('--pattern', '-p', required=True, help='Regex pattern to match') @click.option('--replacement', '-r', required=True, help='Replacement text') @click.option('--name', '-n', help='Rule name (auto-generated if not provided)') @click.option('--description', help='Rule description') @click.option('--order', type=int, default=100, help='Processing order (lower = earlier)') @click.option('--disabled', is_flag=True, help='Create rule as disabled') def add_rule(direction: str, pattern: str, replacement: str, name: Optional[str], description: str, order: int, disabled: bool): """Add a new pronunciation rule.""" manager = get_manager() success = manager.add_rule( direction=direction, pattern=pattern, replacement=replacement, name=name, description=description or "", enabled=not disabled, order=order, private=False # CLI-created rules are not private ) if success: click.echo(f"✓ Rule added successfully") else: click.echo("✗ Failed to add rule (check pattern validity)", err=True) @pronounce_group.command(name='remove') @click.option('--direction', '-d', type=click.Choice(['tts', 'stt']), required=True, help='Rule direction (tts/stt)') @click.argument('name') def remove_rule(direction: str, name: str): """Remove a pronunciation rule by name.""" manager = get_manager() success = manager.remove_rule(direction, name) if success: click.echo(f"✓ Rule '{name}' removed") else: click.echo(f"✗ Rule '{name}' not found", err=True) @pronounce_group.command(name='enable') @click.option('--direction', '-d', type=click.Choice(['tts', 'stt']), required=True, help='Rule direction (tts/stt)') @click.argument('name') def enable_rule(direction: str, name: str): """Enable a pronunciation rule.""" manager = get_manager() success = manager.enable_rule(direction, name) if success: click.echo(f"✓ Rule '{name}' enabled") else: click.echo(f"✗ Failed to enable rule '{name}' (not found or private)", err=True) @pronounce_group.command(name='disable') @click.option('--direction', '-d', type=click.Choice(['tts', 'stt']), required=True, help='Rule direction (tts/stt)') @click.argument('name') def disable_rule(direction: str, name: str): """Disable a pronunciation rule.""" manager = get_manager() success = manager.disable_rule(direction, name) if success: click.echo(f"✓ Rule '{name}' disabled") else: click.echo(f"✗ Failed to disable rule '{name}' (not found or private)", err=True) @pronounce_group.command(name='reload') def reload_rules(): """Reload pronunciation rules from configuration files.""" manager = get_manager() manager.reload_rules() click.echo("✓ Pronunciation rules reloaded") @pronounce_group.command(name='edit') @click.option('--system', is_flag=True, help='Edit system default rules (requires sudo)') def edit_config(system: bool): """Open pronunciation config in editor.""" import os import subprocess if system: # Edit system defaults config_path = Path(__file__).parent.parent / 'data' / 'default_pronunciation.yaml' if not config_path.exists(): click.echo(f"System config not found: {config_path}", err=True) return # Might need sudo editor = os.environ.get('EDITOR', 'nano') subprocess.run(['sudo', editor, str(config_path)]) else: # Edit user config config_path = Path.home() / '.voicemode' / 'config' / 'pronunciation.yaml' if not config_path.exists(): # Create default config config_path.parent.mkdir(parents=True, exist_ok=True) default_config = { 'version': 1, 'tts_rules': [], 'stt_rules': [] } with open(config_path, 'w') as f: yaml.dump(default_config, f, default_flow_style=False) editor = os.environ.get('EDITOR', 'nano') subprocess.run([editor, str(config_path)]) # Reload after editing manager = get_manager() manager.reload_rules() click.echo("✓ Configuration edited and reloaded") # Register the command group def register_commands(cli): """Register pronunciation commands with the main CLI.""" cli.add_command(pronounce_group)

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mbailey/voicemode'

If you have feedback or need assistance with the MCP directory API, please join our Discord server