From 5ad8da47bb794892a63b49e3db6c633d5a911dfe Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 24 Feb 2026 00:25:34 +0000 Subject: [PATCH] Strip config to working features only Remove ~15 unused dataclasses (RateLimitsConfig, LoggingConfig, SafetyConfig, UsersConfig, CommandsConfig, PersonalityConfig, WebStatusConfig, AnnouncementsConfig, WebhookConfig, IntegrationsConfig, etc). Strip config.example.yaml and docker-entrypoint.sh defaults. Co-Authored-By: Claude Opus 4.6 --- config.example.yaml | 36 ++------- docker-entrypoint.sh | 23 ------ meshai/config.py | 176 +------------------------------------------ 3 files changed, 7 insertions(+), 228 deletions(-) diff --git a/config.example.yaml b/config.example.yaml index ca5afd7..d632654 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -6,7 +6,7 @@ # === BOT IDENTITY === bot: - name: ai # Bot's trigger name (users say "ai help") + name: ai # Bot's trigger name (users say "@ai help") owner: "" # Owner's callsign (optional) respond_to_mentions: true # Respond when name is mentioned respond_to_dms: true # Respond to direct messages @@ -32,13 +32,6 @@ response: max_length: 150 # Max chars per message chunk max_messages: 2 # Max message chunks per response -# === RATE LIMITING === -rate_limits: - messages_per_minute: 10 # Per-user message limit - global_messages_per_minute: 30 # Total across all users - cooldown_seconds: 5.0 # Min time between responses to same user - burst_allowance: 3 # Allow short bursts before limiting - # === CONVERSATION HISTORY === history: database: /data/conversations.db @@ -66,25 +59,8 @@ llm: Keep responses VERY brief - under 250 characters total. Be concise but friendly. No markdown formatting. -# === WEB STATUS PAGE === -web_status: - enabled: false # Enable web status page - port: 8080 # Status page port - show_uptime: true - show_message_count: true - show_connected_nodes: true - show_recent_activity: false # Privacy concern - disabled by default - require_auth: false # Require password - auth_password: "" # Password if require_auth=true - -# === ANNOUNCEMENTS === -announcements: - enabled: false # Enable periodic announcements - interval_hours: 24 # Time between announcements - channel: 0 # Channel to broadcast on - messages: [] # Messages to rotate through - # Example: - # messages: - # - "MeshAI online. Mention 'ai' for help!" - # - "Type !help for available commands." - random_order: true # Randomize message order +# === WEATHER === +weather: + primary: openmeteo # openmeteo | wttr | llm + fallback: llm # openmeteo | wttr | llm | none + default_location: "" # Default location for !weather (optional) diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 8586bf1..6234cdb 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -36,12 +36,6 @@ response: max_length: 150 max_messages: 2 -rate_limits: - messages_per_minute: 10 - global_messages_per_minute: 30 - cooldown_seconds: 5.0 - burst_allowance: 3 - history: database: /data/conversations.db max_messages_per_user: 50 @@ -65,23 +59,6 @@ llm: You are a helpful assistant on a Meshtastic mesh network. Keep responses VERY brief - under 250 characters total. Be concise but friendly. No markdown formatting. - -web_status: - enabled: false - port: 8080 - show_uptime: true - show_message_count: true - show_connected_nodes: true - show_recent_activity: false - require_auth: false - auth_password: "" - -announcements: - enabled: false - interval_hours: 24 - channel: 0 - messages: [] - random_order: true EOF echo "Default config created. Configure via http://localhost:7682" fi diff --git a/meshai/config.py b/meshai/config.py index d7241d8..7ce007a 100644 --- a/meshai/config.py +++ b/meshai/config.py @@ -22,132 +22,6 @@ class BotConfig: filter_bbs_protocols: bool = True -@dataclass -class RateLimitsConfig: - """Rate limiting settings.""" - - messages_per_minute: int = 10 # Per-user message limit - global_messages_per_minute: int = 30 # Total across all users - cooldown_seconds: float = 5.0 # Min time between responses to same user - burst_allowance: int = 3 # Allow short bursts before limiting - - -@dataclass -class LoggingConfig: - """Logging settings.""" - - level: str = "INFO" # DEBUG | INFO | WARNING | ERROR - file: str = "" # Empty = console only - max_size_mb: int = 10 - backup_count: int = 3 - log_messages: bool = True # Log incoming messages - log_responses: bool = True # Log outgoing responses - log_api_calls: bool = False # Log raw LLM API requests (verbose) - - -@dataclass -class LLMBackendConfig: - """Single LLM backend configuration.""" - - backend: str = "openai" # openai, anthropic, google - api_key: str = "" - base_url: str = "https://api.openai.com/v1" - model: str = "gpt-4o-mini" - timeout: int = 30 - - -@dataclass -class SafetyConfig: - """Response filtering and safety settings.""" - - max_response_length: int = 250 # Hard cap on response length - filter_profanity: bool = False # Basic profanity filter - blocked_phrases: list[str] = field(default_factory=list) # Phrases to filter out - require_mention: bool = True # Only respond when mentioned by name - ignore_self: bool = True # Don't respond to own messages - emergency_keywords: list[str] = field( - default_factory=lambda: ["emergency", "help", "sos"] - ) # Always respond to these - prompt_injection_guard: bool = True # Basic prompt injection detection - - -@dataclass -class UsersConfig: - """User management settings.""" - - blocklist: list[str] = field(default_factory=list) # Never respond to these node IDs - allowlist_only: bool = False # If true, only respond to allowlist - allowlist: list[str] = field(default_factory=list) # Exclusive users - admin_nodes: list[str] = field(default_factory=list) # Nodes with admin commands - vip_nodes: list[str] = field(default_factory=list) # Skip rate limits - - -@dataclass -class CustomCommandConfig: - """Custom static command definition.""" - - response: str = "" - - -@dataclass -class CommandsConfig: - """Command customization settings.""" - - enabled: bool = True - prefix: str = "!" # Command prefix - custom_commands: dict = field(default_factory=dict) # name -> response mapping - disabled_commands: list[str] = field(default_factory=list) # Built-in commands to disable - - -@dataclass -class PersonalityConfig: - """Personality and prompt settings.""" - - system_prompt: str = ( - "You are a helpful assistant on a Meshtastic mesh network. " - "Keep responses VERY brief - under 250 characters total. " - "Be concise but friendly. No markdown formatting." - ) - context_injection: str = "" # Template with {time}, {sender_name}, {channel} - personas: dict = field(default_factory=dict) # trigger -> prompt mapping - - -@dataclass -class WebStatusConfig: - """Web status page settings.""" - - enabled: bool = False - port: int = 8080 - show_uptime: bool = True - show_message_count: bool = True - show_connected_nodes: bool = True - show_recent_activity: bool = False # Privacy concern - require_auth: bool = False - auth_password: str = "" - - -@dataclass -class AnnouncementsConfig: - """Periodic announcement settings.""" - - enabled: bool = False - interval_hours: int = 24 - channel: int = 0 - messages: list[str] = field(default_factory=list) - random_order: bool = True - - -@dataclass -class WebhookConfig: - """Webhook integration settings.""" - - enabled: bool = False - url: str = "" - events: list[str] = field( - default_factory=lambda: ["message_received", "response_sent", "error"] - ) - - @dataclass class ConnectionConfig: """Meshtastic connection settings.""" @@ -201,16 +75,14 @@ class MemoryConfig: @dataclass class LLMConfig: - """LLM backend settings with fallback support.""" + """LLM backend settings.""" - # Primary backend (backwards compatible with old config) backend: str = "openai" # openai, anthropic, google api_key: str = "" base_url: str = "https://api.openai.com/v1" model: str = "gpt-4o-mini" timeout: int = 30 - # System prompt (kept for backwards compat, personality.system_prompt preferred) system_prompt: str = ( "You are a helpful assistant on a Meshtastic mesh network. " "Keep responses VERY brief - under 250 characters total. " @@ -219,12 +91,6 @@ class LLMConfig: use_system_prompt: bool = True # Toggle to disable sending system prompt web_search: bool = False # Enable web search (Open WebUI feature) - # Fallback settings - fallback: Optional[LLMBackendConfig] = None - retry_attempts: int = 2 - fallback_on_error: bool = True - fallback_on_timeout: bool = True - @dataclass class OpenMeteoConfig: @@ -251,14 +117,6 @@ class WeatherConfig: wttr: WttrConfig = field(default_factory=WttrConfig) -@dataclass -class IntegrationsConfig: - """External integrations settings.""" - - weather: WeatherConfig = field(default_factory=WeatherConfig) - webhook: WebhookConfig = field(default_factory=WebhookConfig) - - @dataclass class Config: """Main configuration container.""" @@ -270,37 +128,10 @@ class Config: history: HistoryConfig = field(default_factory=HistoryConfig) memory: MemoryConfig = field(default_factory=MemoryConfig) llm: LLMConfig = field(default_factory=LLMConfig) - - # New config sections - rate_limits: RateLimitsConfig = field(default_factory=RateLimitsConfig) - logging: LoggingConfig = field(default_factory=LoggingConfig) - safety: SafetyConfig = field(default_factory=SafetyConfig) - users: UsersConfig = field(default_factory=UsersConfig) - commands: CommandsConfig = field(default_factory=CommandsConfig) - personality: PersonalityConfig = field(default_factory=PersonalityConfig) - web_status: WebStatusConfig = field(default_factory=WebStatusConfig) - announcements: AnnouncementsConfig = field(default_factory=AnnouncementsConfig) - integrations: IntegrationsConfig = field(default_factory=IntegrationsConfig) - - # Keep weather at top level for backwards compatibility weather: WeatherConfig = field(default_factory=WeatherConfig) _config_path: Optional[Path] = field(default=None, repr=False) - def get_system_prompt(self) -> str: - """Get effective system prompt, preferring personality config. - - Deprecated: Use PersonalityManager.get_system_prompt() instead. - Kept for backwards compatibility. - """ - _config_logger.warning( - "Config.get_system_prompt() is deprecated. " - "Use PersonalityManager.get_system_prompt() instead." - ) - if self.personality.system_prompt: - return self.personality.system_prompt - return self.llm.system_prompt - def resolve_api_key(self) -> str: """Resolve API key from config or environment.""" if self.llm.api_key: @@ -408,8 +239,3 @@ def save_config(config: Config, config_path: Optional[Path] = None) -> None: with open(config_path, "w") as f: f.write(header) yaml.dump(data, f, default_flow_style=False, sort_keys=False, allow_unicode=True) - - -def get_default_config() -> Config: - """Get a Config object with all default values.""" - return Config()