mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-05-21 23:24:44 +02:00
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 <noreply@anthropic.com>
This commit is contained in:
parent
784b2e3fea
commit
5ad8da47bb
3 changed files with 7 additions and 228 deletions
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
# === BOT IDENTITY ===
|
# === BOT IDENTITY ===
|
||||||
bot:
|
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)
|
owner: "" # Owner's callsign (optional)
|
||||||
respond_to_mentions: true # Respond when name is mentioned
|
respond_to_mentions: true # Respond when name is mentioned
|
||||||
respond_to_dms: true # Respond to direct messages
|
respond_to_dms: true # Respond to direct messages
|
||||||
|
|
@ -32,13 +32,6 @@ response:
|
||||||
max_length: 150 # Max chars per message chunk
|
max_length: 150 # Max chars per message chunk
|
||||||
max_messages: 2 # Max message chunks per response
|
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 ===
|
# === CONVERSATION HISTORY ===
|
||||||
history:
|
history:
|
||||||
database: /data/conversations.db
|
database: /data/conversations.db
|
||||||
|
|
@ -66,25 +59,8 @@ llm:
|
||||||
Keep responses VERY brief - under 250 characters total.
|
Keep responses VERY brief - under 250 characters total.
|
||||||
Be concise but friendly. No markdown formatting.
|
Be concise but friendly. No markdown formatting.
|
||||||
|
|
||||||
# === WEB STATUS PAGE ===
|
# === WEATHER ===
|
||||||
web_status:
|
weather:
|
||||||
enabled: false # Enable web status page
|
primary: openmeteo # openmeteo | wttr | llm
|
||||||
port: 8080 # Status page port
|
fallback: llm # openmeteo | wttr | llm | none
|
||||||
show_uptime: true
|
default_location: "" # Default location for !weather (optional)
|
||||||
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
|
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,6 @@ response:
|
||||||
max_length: 150
|
max_length: 150
|
||||||
max_messages: 2
|
max_messages: 2
|
||||||
|
|
||||||
rate_limits:
|
|
||||||
messages_per_minute: 10
|
|
||||||
global_messages_per_minute: 30
|
|
||||||
cooldown_seconds: 5.0
|
|
||||||
burst_allowance: 3
|
|
||||||
|
|
||||||
history:
|
history:
|
||||||
database: /data/conversations.db
|
database: /data/conversations.db
|
||||||
max_messages_per_user: 50
|
max_messages_per_user: 50
|
||||||
|
|
@ -65,23 +59,6 @@ llm:
|
||||||
You are a helpful assistant on a Meshtastic mesh network.
|
You are a helpful assistant on a Meshtastic mesh network.
|
||||||
Keep responses VERY brief - under 250 characters total.
|
Keep responses VERY brief - under 250 characters total.
|
||||||
Be concise but friendly. No markdown formatting.
|
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
|
EOF
|
||||||
echo "Default config created. Configure via http://localhost:7682"
|
echo "Default config created. Configure via http://localhost:7682"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
176
meshai/config.py
176
meshai/config.py
|
|
@ -22,132 +22,6 @@ class BotConfig:
|
||||||
filter_bbs_protocols: bool = True
|
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
|
@dataclass
|
||||||
class ConnectionConfig:
|
class ConnectionConfig:
|
||||||
"""Meshtastic connection settings."""
|
"""Meshtastic connection settings."""
|
||||||
|
|
@ -201,16 +75,14 @@ class MemoryConfig:
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class LLMConfig:
|
class LLMConfig:
|
||||||
"""LLM backend settings with fallback support."""
|
"""LLM backend settings."""
|
||||||
|
|
||||||
# Primary backend (backwards compatible with old config)
|
|
||||||
backend: str = "openai" # openai, anthropic, google
|
backend: str = "openai" # openai, anthropic, google
|
||||||
api_key: str = ""
|
api_key: str = ""
|
||||||
base_url: str = "https://api.openai.com/v1"
|
base_url: str = "https://api.openai.com/v1"
|
||||||
model: str = "gpt-4o-mini"
|
model: str = "gpt-4o-mini"
|
||||||
timeout: int = 30
|
timeout: int = 30
|
||||||
|
|
||||||
# System prompt (kept for backwards compat, personality.system_prompt preferred)
|
|
||||||
system_prompt: str = (
|
system_prompt: str = (
|
||||||
"You are a helpful assistant on a Meshtastic mesh network. "
|
"You are a helpful assistant on a Meshtastic mesh network. "
|
||||||
"Keep responses VERY brief - under 250 characters total. "
|
"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
|
use_system_prompt: bool = True # Toggle to disable sending system prompt
|
||||||
web_search: bool = False # Enable web search (Open WebUI feature)
|
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
|
@dataclass
|
||||||
class OpenMeteoConfig:
|
class OpenMeteoConfig:
|
||||||
|
|
@ -251,14 +117,6 @@ class WeatherConfig:
|
||||||
wttr: WttrConfig = field(default_factory=WttrConfig)
|
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
|
@dataclass
|
||||||
class Config:
|
class Config:
|
||||||
"""Main configuration container."""
|
"""Main configuration container."""
|
||||||
|
|
@ -270,37 +128,10 @@ class Config:
|
||||||
history: HistoryConfig = field(default_factory=HistoryConfig)
|
history: HistoryConfig = field(default_factory=HistoryConfig)
|
||||||
memory: MemoryConfig = field(default_factory=MemoryConfig)
|
memory: MemoryConfig = field(default_factory=MemoryConfig)
|
||||||
llm: LLMConfig = field(default_factory=LLMConfig)
|
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)
|
weather: WeatherConfig = field(default_factory=WeatherConfig)
|
||||||
|
|
||||||
_config_path: Optional[Path] = field(default=None, repr=False)
|
_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:
|
def resolve_api_key(self) -> str:
|
||||||
"""Resolve API key from config or environment."""
|
"""Resolve API key from config or environment."""
|
||||||
if self.llm.api_key:
|
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:
|
with open(config_path, "w") as f:
|
||||||
f.write(header)
|
f.write(header)
|
||||||
yaml.dump(data, f, default_flow_style=False, sort_keys=False, allow_unicode=True)
|
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()
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue