"""
Configuration management for Galaxy Brain MCP
"""
import os
import json
from pathlib import Path
from typing import Any, Dict, Optional
from dataclasses import dataclass, field
@dataclass
class ThinkingConfig:
"""Configuration for the thinking service"""
max_thoughts: int = 50
max_branches: int = 10
max_revisions_per_thought: int = 5
default_thought_timeout: int = 30 # seconds
allow_infinite_expansion: bool = True
@dataclass
class DoingConfig:
"""Configuration for the doing service"""
max_operations: int = 50
max_content_size_mb: int = 10
default_timeout: int = 30 # seconds
max_timeout: int = 300 # seconds
stop_on_error: bool = True
track_timing: bool = True
allowed_services: tuple = ('file', 'python', 'shell', 'http')
@dataclass
class BridgeConfig:
"""Configuration for the thought-to-action bridge"""
auto_execute: bool = False # Require explicit execute call
validate_before_execute: bool = True
max_plan_operations: int = 25
require_confirmation: bool = True
@dataclass
class GalaxyBrainConfig:
"""Main configuration container"""
thinking: ThinkingConfig = field(default_factory=ThinkingConfig)
doing: DoingConfig = field(default_factory=DoingConfig)
bridge: BridgeConfig = field(default_factory=BridgeConfig)
# Logging
log_level: str = "INFO"
log_file: Optional[str] = None
# Server
server_name: str = "galaxy-brain"
server_version: str = "1.0.0"
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "GalaxyBrainConfig":
"""Create config from dictionary"""
thinking_data = data.get('thinking', {})
doing_data = data.get('doing', {})
bridge_data = data.get('bridge', {})
return cls(
thinking=ThinkingConfig(**thinking_data),
doing=DoingConfig(**doing_data),
bridge=BridgeConfig(**bridge_data),
log_level=data.get('log_level', 'INFO'),
log_file=data.get('log_file'),
server_name=data.get('server_name', 'galaxy-brain'),
server_version=data.get('server_version', '1.0.0')
)
@classmethod
def from_file(cls, path: Path) -> "GalaxyBrainConfig":
"""Load config from JSON file"""
if not path.exists():
return cls()
with open(path, 'r') as f:
data = json.load(f)
return cls.from_dict(data)
@classmethod
def from_env(cls) -> "GalaxyBrainConfig":
"""Load config from environment variables"""
config = cls()
# Override from environment
if os.environ.get('GALAXY_BRAIN_LOG_LEVEL'):
config.log_level = os.environ['GALAXY_BRAIN_LOG_LEVEL']
if os.environ.get('GALAXY_BRAIN_MAX_THOUGHTS'):
config.thinking.max_thoughts = int(os.environ['GALAXY_BRAIN_MAX_THOUGHTS'])
if os.environ.get('GALAXY_BRAIN_MAX_OPERATIONS'):
config.doing.max_operations = int(os.environ['GALAXY_BRAIN_MAX_OPERATIONS'])
return config
# Global config instance
_config: Optional[GalaxyBrainConfig] = None
def get_config() -> GalaxyBrainConfig:
"""Get the global configuration instance"""
global _config
if _config is None:
# Try to load from file first, then env
config_paths = [
Path.cwd() / 'galaxy-brain.json',
Path.home() / '.galaxy-brain' / 'config.json',
Path('/etc/galaxy-brain/config.json')
]
for path in config_paths:
if path.exists():
_config = GalaxyBrainConfig.from_file(path)
break
else:
_config = GalaxyBrainConfig.from_env()
return _config
def set_config(config: GalaxyBrainConfig) -> None:
"""Set the global configuration instance"""
global _config
_config = config