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

@ -64,6 +64,7 @@ class MessageRouter:
dispatcher: CommandDispatcher,
llm_backend: LLMBackend,
context: MeshContext = None,
meshmonitor_sync=None,
):
self.config = config
self.connector = connector
@ -71,6 +72,7 @@ class MessageRouter:
self.dispatcher = dispatcher
self.llm = llm_backend
self.context = context
self.meshmonitor_sync = meshmonitor_sync
def should_respond(self, message: MeshMessage) -> bool:
@ -102,6 +104,15 @@ class MessageRouter:
logger.debug(f"Ignoring advBBS message from {message.sender_id}: {message.text[:40]}...")
return False
# Ignore messages that match MeshMonitor auto-responder triggers
if self.meshmonitor_sync and message.text:
if self.meshmonitor_sync.matches(message.text.strip()):
logger.debug(
f"Ignoring DM from {message.sender_id}: "
f"matches MeshMonitor trigger"
)
return False
return True
async def route(self, message: MeshMessage) -> RouteResult:
@ -165,6 +176,23 @@ class MessageRouter:
"\n\n[No recent mesh traffic observed yet.]"
)
# Inject MeshMonitor commands into prompt
if (
self.meshmonitor_sync
and getattr(self.config.meshmonitor, "inject_into_prompt", False)
and self.meshmonitor_sync.trigger_list
):
trigger_lines = ", ".join(
t for t in self.meshmonitor_sync.trigger_list
if t not in ("commands", "command")
)
system_prompt += (
"\n\nMESHMONITOR COMMANDS (handled by MeshMonitor, not you): "
+ trigger_lines
+ "\nIf someone asks what commands are available, mention these too."
)
try:
response = await self.llm.generate(
messages=history,