configuration_api.md 12 KB

Configuration Management API Documentation

Overview

The Configuration Management system provides centralized, type-safe configuration handling for all Trixy components across different deployment modes (server, client, standalone).

Location: ./trixy_core/config/

Core Components

ConfigManager

Main configuration management class with hot-reloading and validation.

Configuration Classes

  • ServerConfig: Server-specific configuration
  • ClientConfig: Client/satellite configuration
  • StandaloneConfig: Standalone mode configuration

ConfigValidator

Validates configuration values and dependencies.

API Reference

ConfigManager Class

Initialization

from trixy_core.config import ConfigManager, DeploymentMode

config_manager = ConfigManager(
    mode=DeploymentMode.SERVER,
    config_file="config/server_config.json",
    debug_mode=False
)

Core Methods

load_config()

Loads and validates configuration from file.

config = config_manager.load_config()
print(f"Command port: {config.network.command_port}")
get_config()

Returns current loaded configuration.

current_config = config_manager.get_config()
save_config(config=None)

Saves configuration to file with backup.

# Modify and save
config = config_manager.get_config()
config.network.command_port = 2105
config_manager.save_config(config)
reload_config()

Reloads configuration from file.

config_manager.reload_config()
override_config(overrides: Dict)

Apply runtime configuration overrides.

config_manager.override_config({
    "network": {"command_port": 2105},
    "max_satellites": 100,
    "debug": {"enable_verbose_logging": True}
})
enable_hot_reload(interval: float = 1.0)

Enables automatic configuration reloading.

# Check for config changes every 2 seconds
config_manager.enable_hot_reload(interval=2.0)

# Register callback for config changes
def on_config_changed(old_config, new_config):
    print("Configuration updated!")

config_manager.enable_hot_reload(callback=on_config_changed)
disable_hot_reload()

Disables automatic configuration reloading.

config_manager.disable_hot_reload()
validate_config(config=None)

Validates configuration against schema.

is_valid, errors = config_manager.validate_config()
if not is_valid:
    for error in errors:
        print(f"Config error: {error}")
backup_config()

Creates manual backup of current configuration.

backup_path = config_manager.backup_config()
print(f"Config backed up to: {backup_path}")
restore_backup(backup_file: str)

Restores configuration from backup.

config_manager.restore_backup("config/backups/server_config_20241201_120000.json")

Configuration Classes

ServerConfig

@dataclass
class ServerConfig:
    # Network configuration
    network: NetworkConfig
    
    # Satellite management
    max_satellites: int = 50
    registration_timeout: int = 60
    
    # Plugin settings
    plugins: PluginConfig
    
    # Audio processing
    audio: AudioConfig
    
    # ML models
    models: ModelConfig
    
    # Logging
    logging: LoggingConfig
    
    # Security
    security: SecurityConfig

ClientConfig

@dataclass
class ClientConfig:
    # Network configuration
    network: ClientNetworkConfig
    
    # Server connection
    server: ServerConnectionConfig
    
    # Audio capture
    audio: ClientAudioConfig
    
    # ML models (wakeword, voice recognition)
    models: ClientModelConfig
    
    # Hardware settings
    hardware: HardwareConfig
    
    # Logging
    logging: LoggingConfig

StandaloneConfig

@dataclass
class StandaloneConfig:
    # Combines server and client features
    network: NetworkConfig
    audio: AudioConfig
    models: ModelConfig
    plugins: PluginConfig
    logging: LoggingConfig
    
    # Standalone-specific
    sync: SyncConfig  # Server synchronization settings

Configuration Sections

NetworkConfig

@dataclass
class NetworkConfig:
    command_port: int = 2101
    audio_input_port: int = 2102
    audio_output_port: int = 2103
    music_output_port: int = 2104
    bind_address: str = "0.0.0.0"
    max_connections: int = 100
    connection_timeout: int = 30
    keepalive_interval: int = 60

AudioConfig

@dataclass
class AudioConfig:
    sample_rate: int = 16000
    channels: int = 1
    bit_depth: int = 16
    chunk_size: int = 1024
    input_device: Optional[str] = None
    output_device: Optional[str] = None
    noise_reduction: bool = True
    auto_gain_control: bool = True

ModelConfig

@dataclass
class ModelConfig:
    wakeword_model: str = "models/wakeword/default.pth"
    voice_recognition_model: str = "models/voice_recognition/default.pth"
    model_password: str = ""
    use_gpu: bool = False
    model_cache_size: int = 2
    inference_threads: int = 1

Environment Variables

The configuration system supports environment variable overrides with the TRIXY_ prefix:

# Network settings
export TRIXY_NETWORK_COMMAND_PORT=2201
export TRIXY_NETWORK_BIND_ADDRESS="127.0.0.1"

# Model settings
export TRIXY_MODELS_USE_GPU=true
export TRIXY_MODELS_MODEL_PASSWORD="secret123"

# Debug settings
export TRIXY_DEBUG_ENABLE_VERBOSE_LOGGING=true

Configuration File Management

Default Configuration Files

server_config.json

{
  "network": {
    "command_port": 2101,
    "audio_input_port": 2102,
    "audio_output_port": 2103,
    "music_output_port": 2104,
    "bind_address": "0.0.0.0",
    "max_connections": 50
  },
  "max_satellites": 50,
  "registration_timeout": 60,
  "plugins": {
    "directory": "plugins",
    "auto_load": true,
    "hot_reload": true
  },
  "audio": {
    "sample_rate": 16000,
    "channels": 1,
    "bit_depth": 16
  },
  "models": {
    "wakeword_model": "models/wakeword/default.pth",
    "voice_recognition_model": "models/voice_recognition/default.pth"
  }
}

client_config.json

{
  "network": {
    "local_ports": {
      "audio_input": 3102,
      "audio_output": 3103,
      "music_output": 3104
    }
  },
  "server": {
    "host": "localhost",
    "port": 2101,
    "reconnect_interval": 5,
    "max_reconnect_attempts": -1
  },
  "audio": {
    "sample_rate": 16000,
    "channels": 1,
    "input_device": null,
    "noise_reduction": true
  },
  "models": {
    "wakeword_model": "models/wakeword/client.pth",
    "voice_recognition_model": "models/voice_recognition/client.pth",
    "use_gpu": false
  }
}

Advanced Usage

Configuration Override Priority

  1. Runtime overrides (highest priority)
  2. Environment variables
  3. Command line arguments
  4. Configuration files (lowest priority)

Hot-Reload with Callbacks

class ConfigurableComponent:
    def __init__(self, config_manager):
        self.config_manager = config_manager
        self.config_manager.enable_hot_reload(callback=self.on_config_changed)
    
    def on_config_changed(self, old_config, new_config):
        # Handle configuration changes
        if old_config.network.command_port != new_config.network.command_port:
            self.restart_network_listener(new_config.network.command_port)

Configuration Validation

from trixy_core.config import ConfigValidator

validator = ConfigValidator()

# Add custom validation rules
@validator.add_rule("network.command_port")
def validate_port(value):
    if not (1024 <= value <= 65535):
        return False, "Port must be between 1024 and 65535"
    return True, None

# Validate configuration
is_valid, errors = validator.validate(config)

Configuration Migration

def migrate_config_v1_to_v2(config_dict):
    """Migrate configuration from version 1 to 2"""
    if config_dict.get("version", 1) == 1:
        # Rename old settings
        if "server_port" in config_dict:
            config_dict["network"] = {"command_port": config_dict.pop("server_port")}
        
        config_dict["version"] = 2
    
    return config_dict

config_manager.add_migration(migrate_config_v1_to_v2)

Integration Examples

Plugin Configuration Access

from trixy_core.plugins import TrixyPlugin

class MyPlugin(TrixyPlugin):
    def initialize(self):
        # Access global config
        config = self.application.get_config_manager().get_config()
        
        # Use configuration values
        if config.debug.enable_plugin_debugging:
            self.enable_debug_mode()
        
        # Watch for config changes
        self.application.get_config_manager().enable_hot_reload(
            callback=self.on_config_changed
        )
    
    def on_config_changed(self, old_config, new_config):
        # React to configuration changes
        if old_config.audio.sample_rate != new_config.audio.sample_rate:
            self.restart_audio_processing()

Component Configuration

class NetworkManager:
    def __init__(self, application):
        self.application = application
        self.config_manager = application.get_config_manager()
        self.current_config = self.config_manager.get_config()
        
        # Enable hot-reload for network settings
        self.config_manager.enable_hot_reload(
            callback=self.on_network_config_changed
        )
    
    def on_network_config_changed(self, old_config, new_config):
        # Check if network settings changed
        if old_config.network != new_config.network:
            self.restart_network_services(new_config.network)

Error Handling

Configuration Errors

from trixy_core.config import (
    ConfigurationError,
    ConfigurationValidationError,
    ConfigurationLoadError,
    ConfigurationSaveError
)

try:
    config = config_manager.load_config()
except ConfigurationLoadError as e:
    print(f"Failed to load config: {e}")
    # Use default configuration
    config = config_manager.get_default_config()
except ConfigurationValidationError as e:
    print(f"Invalid configuration: {e}")
    # Show validation errors to user
    for error in e.validation_errors:
        print(f"  - {error}")

File System Errors

try:
    config_manager.save_config()
except ConfigurationSaveError as e:
    print(f"Failed to save config: {e}")
    # Try saving to alternate location
    backup_path = config_manager.backup_config()
    print(f"Configuration saved to backup: {backup_path}")

Best Practices

1. Configuration Structure

# Good: Logical grouping
{
  "network": {"command_port": 2101, "bind_address": "0.0.0.0"},
  "audio": {"sample_rate": 16000, "channels": 1},
  "models": {"wakeword_model": "path/to/model.pth"}
}

# Avoid: Flat structure
{
  "command_port": 2101,
  "bind_address": "0.0.0.0",
  "sample_rate": 16000
}

2. Environment Variable Usage

# Use environment variables for sensitive data
{
  "api_keys": {
    "openai_key": "${TRIXY_OPENAI_API_KEY}",
    "google_key": "${TRIXY_GOOGLE_API_KEY}"
  }
}

3. Configuration Validation

class MyComponent:
    def __init__(self, config_manager):
        self.config = config_manager.get_config()
        
        # Validate required configuration
        if not self.config.network.command_port:
            raise ConfigurationError("Command port not configured")
        
        if not (1024 <= self.config.network.command_port <= 65535):
            raise ConfigurationError("Invalid command port range")

4. Hot-Reload Handling

def on_config_changed(self, old_config, new_config):
    # Only react to relevant changes
    if old_config.audio != new_config.audio:
        self.restart_audio_system()
    
    # Avoid unnecessary restarts
    if old_config.logging != new_config.logging:
        self.update_log_level(new_config.logging.level)
        # Don't restart entire component

Performance Considerations

  • File Watching: Hot-reload uses efficient file system watching
  • Validation: Validation is cached and only run when config changes
  • Memory Usage: Configurations are loaded once and cached
  • Thread Safety: All operations are thread-safe

Security Considerations

  • Sensitive Data: Use environment variables for passwords/keys
  • File Permissions: Configuration files should have restricted permissions
  • Backup Security: Backups inherit security settings from original files
  • Validation: Always validate configuration before use