feat: Dynamic MeshMonitor trigger sync — auto-ignore MeshMonitor commands

Add MeshMonitorSync class that reads trigger patterns from a JSON file
and compiles them to regex. The router checks incoming messages against
these patterns and ignores messages that MeshMonitor will handle.

- New meshai/meshmonitor.py: Pattern compilation and file watching
- MeshMonitorConfig dataclass with enabled, triggers_file, inject_into_prompt
- Router integration: ignore matching messages, inject commands into prompt
- Main loop refresh: watch triggers file for changes without restart

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
root 2026-05-03 03:20:23 +00:00
commit f6540e893d
7 changed files with 251 additions and 0 deletions

View file

@ -37,6 +37,7 @@ class MeshAI:
self.dispatcher: Optional[CommandDispatcher] = None
self.llm: Optional[LLMBackend] = None
self.context: Optional[MeshContext] = None
self.meshmonitor_sync = None
self.router: Optional[MessageRouter] = None
self.responder: Optional[Responder] = None
self._running = False
@ -79,6 +80,10 @@ class MeshAI:
self.context.prune()
self._last_cleanup = time.time()
# Refresh MeshMonitor triggers if file changed
if self.meshmonitor_sync:
self.meshmonitor_sync.maybe_refresh()
async def stop(self) -> None:
"""Stop the bot."""
logger.info("Stopping MeshAI...")
@ -157,10 +162,21 @@ class MeshAI:
else:
self.context = None
# MeshMonitor trigger sync
self.meshmonitor_sync = None
mm_cfg = self.config.meshmonitor
if mm_cfg.enabled and mm_cfg.triggers_file:
from .meshmonitor import MeshMonitorSync
self.meshmonitor_sync = MeshMonitorSync(
triggers_file=mm_cfg.triggers_file,
)
self.meshmonitor_sync.load()
# Message router
self.router = MessageRouter(
self.config, self.connector, self.history, self.dispatcher, self.llm,
context=self.context,
meshmonitor_sync=self.meshmonitor_sync,
)
# Responder