HASHIRU / autonomous_config.py
mulambo's picture
Initial commit
fea1bd1
"""
HASHIRU 6.1 - Clean Configuration
Modern, type-safe, validated configuration following Python best practices
"""
import os
from pathlib import Path
from dataclasses import dataclass, field
from typing import List, Dict, Optional, Union
@dataclass
class OllamaConfig:
"""Ollama/LLM Configuration"""
base_url: str = "http://127.0.0.1:11434"
timeout: float = 180.0
# Models with fallbacks
reasoning_model: str = "deepseek-r1:8b"
reasoning_fallbacks: List[str] = field(default_factory=lambda: ["llama3.1:8b", "qwen2.5:14b-instruct"])
code_model: str = "deepseek-coder:6.7b"
code_fallbacks: List[str] = field(default_factory=lambda: ["deepseek-coder:33b", "llama3.1:8b"])
conversation_model: str = "llama3.1:8b"
conversation_fallbacks: List[str] = field(default_factory=lambda: ["mistral:7b-instruct"])
tools_model: str = "llama3-groq-tool-use:8b"
tools_fallbacks: List[str] = field(default_factory=lambda: ["llama3.1:8b"])
@classmethod
def from_env(cls) -> 'OllamaConfig':
"""Create config from environment variables"""
return cls(
base_url=os.getenv("OLLAMA_BASE_URL", cls.base_url),
timeout=float(os.getenv("OLLAMA_TIMEOUT", cls.timeout))
)
@dataclass
class SecurityConfig:
"""Security and file access policies"""
# Free zone - total freedom
free_project_path: Path = Path(r"C:\meu_projeto_livre")
# Always allowed paths
allowed_paths: List[str] = field(default_factory=lambda: [
".", # Current project
"tools", "utils", "scripts", "artifacts",
r"C:\meu_projeto_livre", # Free zone
r"C:\Users\Public", # Public folder
r"C:\temp", r"C:\tmp", # Temp folders
])
# Always blocked paths
blocked_paths: List[str] = field(default_factory=lambda: [
r"C:\Windows\System32",
r"C:\Program Files",
".git", "__pycache__", "venv", ".venv"
])
# Dangerous file extensions
blocked_extensions: List[str] = field(default_factory=lambda: [
".sys", ".dll" # Only truly dangerous ones
])
def is_write_allowed(self, target_path: Union[str, Path]) -> bool:
"""Check if writing to path is allowed"""
try:
resolved = Path(target_path).resolve()
path_str = str(resolved)
# Check blocked extensions
if resolved.suffix.lower() in self.blocked_extensions:
return False
# Check if in allowed paths
for allowed in self.allowed_paths:
if path_str.startswith(str(Path(allowed).resolve())):
return True
# Check if in blocked paths
for blocked in self.blocked_paths:
if path_str.startswith(blocked):
return False
# Check for user home directory (generally safe)
if path_str.startswith(str(Path.home())):
return True
return False
except Exception:
return False
@dataclass
class WebConfig:
"""Web and internet access configuration"""
enabled: bool = True
max_search_results: int = 10
default_timeout: float = 30.0
user_agent: str = "HASHIRU-6.1-Agent"
# Search engines (for future implementation)
search_engines: List[str] = field(default_factory=lambda: [
"duckduckgo", "google", "bing"
])
@dataclass
class SystemConfig:
"""System-level configuration"""
project_root: Path = field(default_factory=lambda: Path(__file__).parent)
# Directory structure
tools_dir: Path = field(default_factory=lambda: Path("tools"))
utils_dir: Path = field(default_factory=lambda: Path("utils"))
artifacts_dir: Path = field(default_factory=lambda: Path("artifacts"))
backups_dir: Path = field(default_factory=lambda: Path("backups"))
# Runtime settings
encoding: str = "utf-8"
chainlit_port: int = 8080
max_commands_per_execution: int = 20
def ensure_directories(self) -> None:
"""Create necessary directories"""
for dir_path in [self.artifacts_dir, self.backups_dir]:
dir_path.mkdir(exist_ok=True)
@classmethod
def from_env(cls) -> 'SystemConfig':
"""Create system config from environment"""
return cls(
chainlit_port=int(os.getenv("CHAINLIT_PORT", cls.chainlit_port))
)
@dataclass
class EngineConfig:
"""Self-modification engine configuration"""
enabled: bool = True
auto_backup: bool = True
max_backups_per_file: int = 10
# File patterns that can be modified
modifiable_patterns: List[str] = field(default_factory=lambda: [
"*.py", "*.json", "*.txt", "*.md"
])
@dataclass
class Config:
"""Main configuration class - Clean and typed"""
# Sub-configurations
ollama: OllamaConfig = field(default_factory=OllamaConfig)
security: SecurityConfig = field(default_factory=SecurityConfig)
web: WebConfig = field(default_factory=WebConfig)
system: SystemConfig = field(default_factory=SystemConfig)
engine: EngineConfig = field(default_factory=EngineConfig)
# Simple flags
autonomous_mode: bool = True
debug_mode: bool = False
# Messages
startup_banner: str = "🚀 HASHIRU 6.1 - Agente Autônomo Inteligente"
processing_message: str = "🧠 Processando com IA..."
executing_message: str = "⚡ Executando automaticamente..."
@classmethod
def load(cls) -> 'Config':
"""Load configuration with environment overrides"""
config = cls()
# Load from environment
config.ollama = OllamaConfig.from_env()
config.system = SystemConfig.from_env()
# Set debug mode from environment
config.debug_mode = os.getenv("DEBUG", "false").lower() == "true"
# Validate and setup
config.validate()
config.setup()
return config
def validate(self) -> None:
"""Validate configuration - fail fast if invalid"""
# Ensure required paths exist or can be created
try:
self.security.free_project_path.mkdir(parents=True, exist_ok=True)
except Exception as e:
raise ValueError(f"Cannot create free project path: {e}")
# Validate models are strings
if not isinstance(self.ollama.reasoning_model, str):
raise ValueError("Models must be strings")
# Validate ports
if not (1024 <= self.system.chainlit_port <= 65535):
raise ValueError("Invalid port number")
def setup(self) -> None:
"""Setup configuration - create directories, etc."""
self.system.ensure_directories()
# Create free project structure
free_path = self.security.free_project_path
for subdir in ["downloads", "research", "experiments", "backups"]:
(free_path / subdir).mkdir(exist_ok=True)
def get_model(self, model_type: str) -> str:
"""Get primary model for type"""
model_map = {
"reasoning": self.ollama.reasoning_model,
"code": self.ollama.code_model,
"code_specialist": self.ollama.code_model,
"code_master": self.ollama.code_model,
"conversation": self.ollama.conversation_model,
"tools": self.ollama.tools_model,
"general": self.ollama.conversation_model,
}
return model_map.get(model_type, self.ollama.conversation_model)
def get_fallback_models(self, model_type: str) -> List[str]:
"""Get fallback models for type"""
fallback_map = {
"reasoning": self.ollama.reasoning_fallbacks,
"code": self.ollama.code_fallbacks,
"code_specialist": self.ollama.code_fallbacks,
"code_master": self.ollama.code_fallbacks,
"conversation": self.ollama.conversation_fallbacks,
"tools": self.ollama.tools_fallbacks,
"general": self.ollama.conversation_fallbacks,
}
return fallback_map.get(model_type, self.ollama.conversation_fallbacks)
# Global configuration instance
config = Config.load()
# Legacy compatibility functions (for existing code)
def get_ai_model(model_type: str) -> str:
"""Legacy: Get AI model"""
return config.get_model(model_type)
def get_fallback_models(model_type: str) -> List[str]:
"""Legacy: Get fallback models"""
return config.get_fallback_models(model_type)
def is_write_path_allowed(target_path: str) -> bool:
"""Legacy: Check if write is allowed"""
return config.security.is_write_allowed(target_path)
def is_command_auto_allowed(command: str) -> bool:
"""Legacy: Check if command is auto-allowed"""
return config.autonomous_mode
def is_dangerous_command_allowed(command: str) -> bool:
"""Legacy: Check if dangerous command is allowed"""
return config.autonomous_mode
# Legacy constants (for existing imports)
OLLAMA_URL = config.ollama.base_url
AUTONOMOUS_MODE = config.autonomous_mode
SELF_MODIFICATION_ENABLED = config.engine.enabled
STARTUP_BANNER = config.startup_banner
PROCESSING_MESSAGE = config.processing_message
EXECUTING_MESSAGE = config.executing_message
# Export for easy imports
__all__ = [
"Config", "config",
"get_ai_model", "get_fallback_models",
"is_write_path_allowed", "is_command_auto_allowed", "is_dangerous_command_allowed",
"OLLAMA_URL", "AUTONOMOUS_MODE", "SELF_MODIFICATION_ENABLED",
"STARTUP_BANNER", "PROCESSING_MESSAGE", "EXECUTING_MESSAGE"
]
# Initialize on import
if config.debug_mode:
print("🔧 HASHIRU Config loaded in DEBUG mode")
print(f"📁 Free path: {config.security.free_project_path}")
print(f"🤖 Reasoning model: {config.ollama.reasoning_model}")