mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-05-21 23:24:44 +02:00
feat(config): split monolithic config + extract secrets
- Update .gitignore for v0.3 multi-file layout - Add config/.env.example template for secrets - Add config/local.yaml.example for operator values - Wire main.py to use new config_loader - Support both legacy and new layouts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2c11432bd8
commit
965a844b0d
4 changed files with 113 additions and 7 deletions
20
.gitignore
vendored
20
.gitignore
vendored
|
|
@ -1,3 +1,13 @@
|
|||
# Operator-identifying config and secrets (v0.3 split)
|
||||
/data/config/local.yaml
|
||||
/data/config/secrets/
|
||||
/data/secrets/
|
||||
.env
|
||||
.env.local
|
||||
.env.*
|
||||
!.env.example
|
||||
local.yaml
|
||||
!local.yaml.example
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
|
@ -49,3 +59,13 @@ data/
|
|||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
# Operator-identifying config and secrets (v0.3 split)
|
||||
/data/config/local.yaml
|
||||
/data/config/secrets/
|
||||
/data/secrets/
|
||||
.env
|
||||
.env.local
|
||||
.env.*
|
||||
!.env.example
|
||||
local.yaml
|
||||
!local.yaml.example
|
||||
|
|
|
|||
19
config/.env.example
Normal file
19
config/.env.example
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# MeshAI Secrets Template
|
||||
# Copy to /data/secrets/.env and fill in your values
|
||||
# This file is gitignored - never commit real secrets
|
||||
|
||||
# LLM API Keys (only one needed based on your backend choice)
|
||||
OPENAI_API_KEY=
|
||||
ANTHROPIC_API_KEY=
|
||||
GOOGLE_API_KEY=
|
||||
|
||||
# Mesh Source Credentials
|
||||
MESHMONITOR_API_TOKEN=
|
||||
MQTT_PASSWORD=
|
||||
|
||||
# Environmental Feed Keys
|
||||
TOMTOM_API_KEY=
|
||||
FIRMS_MAP_KEY=
|
||||
|
||||
# Notification Credentials
|
||||
SMTP_PASSWORD=
|
||||
57
config/local.yaml.example
Normal file
57
config/local.yaml.example
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# MeshAI Local Configuration Template
|
||||
# Copy to /data/config/local.yaml and customize for your deployment
|
||||
# This file is gitignored - contains operator-identifying values
|
||||
|
||||
# Operator Identity
|
||||
identity:
|
||||
name: "" # Bot display name
|
||||
owner: "" # Owner callsign/name
|
||||
primary_node_id: "" # Your main mesh node ID
|
||||
contact_email: "" # For NWS user_agent, SMTP from
|
||||
|
||||
# Region Coordinates
|
||||
# Map your region names to their lat/lon center points
|
||||
regions:
|
||||
"Example Region":
|
||||
lat: 0.0
|
||||
lon: 0.0
|
||||
# Add more regions as needed:
|
||||
# "Another Region":
|
||||
# lat: 42.5
|
||||
# lon: -114.5
|
||||
|
||||
# Mesh Data Source URLs
|
||||
mesh_sources:
|
||||
meshmonitor_url: "" # Your MeshMonitor instance
|
||||
sources:
|
||||
# Per-source URL overrides (matches names in mesh_sources.yaml)
|
||||
"My-Meshview":
|
||||
url: ""
|
||||
# "My-MeshMonitor":
|
||||
# url: ""
|
||||
|
||||
# Infrastructure Hosts
|
||||
infrastructure:
|
||||
tcp_host: "" # Meshtastic TCP host (meshtasticd)
|
||||
qdrant_host: "" # Qdrant vector DB (optional)
|
||||
tei_host: "" # TEI embedding service (optional)
|
||||
sparse_host: "" # Sparse embedding service (optional)
|
||||
|
||||
# Environmental Feed Center Point
|
||||
env_center:
|
||||
latitude: 0.0 # Center of your coverage area
|
||||
longitude: 0.0
|
||||
|
||||
# Notification Targets
|
||||
notification_targets:
|
||||
smtp_from: "" # Email from address
|
||||
smtp_recipients: [] # Default email recipients
|
||||
webhook_urls: [] # Webhook endpoints
|
||||
alert_node_ids: [] # Node IDs for mesh DM alerts
|
||||
|
||||
# Critical Infrastructure Nodes (short names)
|
||||
critical_nodes: []
|
||||
# Example:
|
||||
# critical_nodes:
|
||||
# - "MHR"
|
||||
# - "HPR"
|
||||
|
|
@ -16,7 +16,8 @@ from .cli import run_configurator
|
|||
from .commands import CommandDispatcher
|
||||
from .commands.dispatcher import create_dispatcher
|
||||
from .commands.status import set_start_time
|
||||
from .config import Config, load_config
|
||||
from .config import Config
|
||||
from .config_loader import load_config, get_config_dir_from_path
|
||||
from .connector import MeshConnector, MeshMessage
|
||||
from .context import MeshContext
|
||||
from .history import ConversationHistory
|
||||
|
|
@ -712,12 +713,21 @@ def main() -> None:
|
|||
run_configurator(args.config_file)
|
||||
return
|
||||
|
||||
# Load config
|
||||
config = load_config(args.config_file)
|
||||
# Load config - support both old (/data/config.yaml) and new (/data/config/) layouts
|
||||
config_path = args.config_file
|
||||
config_dir = get_config_dir_from_path(config_path)
|
||||
|
||||
# Check if config exists
|
||||
if not args.config_file.exists():
|
||||
logger.warning(f"Config file not found: {args.config_file}")
|
||||
# Check for new multi-file layout first
|
||||
if (config_dir / "config.yaml").exists():
|
||||
logger.info(f"Loading config from multi-file layout: {config_dir}")
|
||||
config = load_config(config_dir)
|
||||
elif config_path.exists():
|
||||
# Fall back to legacy single-file loading
|
||||
logger.info(f"Loading legacy config: {config_path}")
|
||||
from .config import load_config as legacy_load
|
||||
config = legacy_load(config_path)
|
||||
else:
|
||||
logger.warning(f"Config not found at {config_path} or {config_dir}")
|
||||
logger.info("Run 'meshai --config' to create one, or copy config.example.yaml")
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue