Commit graph

95 commits

Author SHA1 Message Date
root
f6540e893d 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>
2026-05-03 03:20:23 +00:00
Ubuntu
1172b9b67f Add API timeout to all backends + mesh-aware system prompt
All three LLM backends (Google, OpenAI, Anthropic) now wrap API calls
in asyncio.wait_for() using config.timeout (default 30s). Previously
Gemini could hang indefinitely with grounding+AFC enabled.

Router catches TimeoutError with user-friendly "request timed out" message.
Empty context buffer now injects "[No recent mesh traffic observed yet.]"
so the LLM knows the capability exists even when buffer is empty.
Default system prompt updated to mention mesh awareness.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 07:27:39 +00:00
Ubuntu
a01c9b2d05 Silently drop unknown bang commands instead of responding
Unknown !commands (like !mail, !login, !bbs from advBBS users) were
getting "Unknown command, try !help" responses. Now returns None so
the bot stays silent on commands it doesn't recognize.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 02:02:01 +00:00
Ubuntu
63a2caad37 Add passive mesh context awareness — observe channel traffic, inject into LLM prompts
New context.py module: ring buffer (50K hard cap, ~25MB ceiling) passively
records all channel broadcasts. Observations are formatted with relative
timestamps and injected into the system prompt when generating LLM responses.
Only public channel traffic is observed; DMs to the bot are excluded (already
in per-user history). Bot's own node ID is auto-added to ignore list.

Config: context.enabled, observe_channels, ignore_nodes, max_age, max_context_items
TUI: new Context settings submenu (menu item 7)
Hourly prune removes expired observations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:02:42 +00:00
Ubuntu
1e033316fb Remove dead channel/mention code — DM-only bot cleanup
MeshAI is now DM-only. Removed all unreachable channel response
paths, @mention detection, ChannelsConfig, and channel TUI menu.
Fixed restart mechanism with integrated watcher and SIGKILL fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 08:43:25 +00:00
Ubuntu
32147ccaec Add Commands section to TUI configurator with toggle for each built-in command
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 07:33:36 +00:00
Ubuntu
8001de46c7 Add !clear command and simplify !reset confirmation message
Both !clear and !reset now respond with "Conversation memory cleared."

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 07:24:02 +00:00
Ubuntu
6a67fe1940 Disable rolling summary — send full conversation history to Gemini
Mesh messages are short enough that summarization is unnecessary
with Gemini Flash's 1M token context window.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 07:11:24 +00:00
Ubuntu
6b1320f9e0 Support unlimited message history when max_messages_per_user is 0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 07:03:15 +00:00
Ubuntu
69b749930c Revert date injection from system prompt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 06:46:42 +00:00
Ubuntu
825d93e52d Inject current date into system prompt so LLM knows today's date
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 06:28:24 +00:00
Ubuntu
6e2d956be6 Migrate Google backend from deprecated google-generativeai to google-genai SDK with grounding support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 04:44:44 +00:00
Ubuntu
94d27a634e Remove dead code from living files
Delete unused CommandResult class from commands/base.py and unused
format_dm_response method from responder.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:27:49 +00:00
Ubuntu
1f66faff0c Clean configurator: remove rate_limits, web_status, announcements menus
Removed dead menu items that referenced deleted config sections.
Renumbered menu options. Added BBS filter toggle to bot settings.
Added missing _handle_exit method.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:27:05 +00:00
Ubuntu
5ad8da47bb 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>
2026-02-24 00:25:34 +00:00
Ubuntu
784b2e3fea Remove FallbackBackend and generate_with_search from all backends
FallbackBackend was never configured in practice. generate_with_search
was an unused abstract method on all backends.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:24:24 +00:00
Ubuntu
10bc94b273 Remove dead modules: safety, rate_limiter, personality, webhook, web_status, announcements, log_setup
These modules were wired up but never actually functional in the
running bot. Strips all imports and usage from main.py and router.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:23:46 +00:00
Ubuntu
9a628724ce Remove AI planning docs and example scripts
These were LLM-generated planning artifacts from the memory
implementation phase. Not user-facing documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:22:31 +00:00
Ubuntu
8c2c4d2aef Add GHCR publishing workflow and update docker-compose for registry pull
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:39:23 +00:00
Ubuntu
5294b027e7 Add MIT license file
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:31:59 +00:00
Ubuntu
05a8f8659d Document advBBS compatibility in README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:29:59 +00:00
Ubuntu
247074afd1 Add advBBS protocol message filter to router
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:28:20 +00:00
Ubuntu
2a857bcb70 Deprecate Config.get_system_prompt() and fix callback type annotation
- 7a: Config.get_system_prompt() now logs a deprecation warning.
  PersonalityManager.get_system_prompt() is the canonical source (wired
  in commit 4). LLMConfig.system_prompt kept for backwards compat as
  fallback when personality is not configured.
- 7b: Fix AnnouncementScheduler callback type from asyncio.coroutine
  (a decorator, not a type) to Awaitable[None] from typing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:19:09 +00:00
Ubuntu
ab7e52b9fb Fix healthcheck to verify PID and add DM-only conversational mode
- 6a: Change healthcheck in Dockerfile and docker-compose.yml to verify
  the PID file exists and the process is alive (kill -0) instead of
  testing SQLite connectivity, which only proves the DB file exists
- 6b: In DMs, skip !commands so MeshMonitor or other bots handle them.
  MeshAI only responds conversationally in DMs (no bang commands)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:18:27 +00:00
Ubuntu
32cd2b3427 Add HTML escaping to status page and prompt injection guard to router
- 5a: Import html.escape and apply to all values rendered into the
  HTML template in _serve_status_page() — uptime, counts, status text,
  node counts, errors. Prevents XSS via crafted node names or errors.
- 5b: Add basic prompt injection detection to _clean_query() with
  configurable safety.prompt_injection_guard (default: on). Detects
  patterns like "ignore all previous", "you are now", "system prompt:",
  etc. Truncates query before the injection phrase and logs a warning.
  Not foolproof but better than nothing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:17:46 +00:00
Ubuntu
a71f92a77a Wire up all unused modules into main application lifecycle
- 2a: SafetyFilter + UserFilter — check user access before processing,
  filter LLM responses through SafetyFilter before sending
- 2b: RateLimiter — check rate limits before processing, record
  messages after successful response delivery
- 2c: PersonalityManager — pass to MessageRouter, used for system
  prompt generation instead of raw config.llm.system_prompt
- 2d: WebhookClient — start/stop in lifecycle, fire events on
  message_received, response_sent, error, startup, shutdown
- 2e: WebStatusServer — start/stop in lifecycle, record messages,
  responses, and errors in StatusData
- 2f: AnnouncementScheduler — start/stop in lifecycle, uses
  connector.send_message as callback
- 2g: FallbackBackend — wrap primary backend when config.llm.fallback
  is configured, otherwise use primary directly
- 2h: CommandDispatcher — pass prefix, disabled_commands, and
  custom_commands from config to create_dispatcher()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:16:25 +00:00
Ubuntu
2945031071 Unify memory implementations: delete AnthropicMemory and GoogleMemory
RollingSummaryMemory now accepts a generic async summarize callable
instead of hardcoding AsyncOpenAI. Each backend provides its own
_summarize_messages() method that uses the appropriate API client.

- Removed AnthropicMemory class from anthropic_backend.py
- Removed GoogleMemory class from google_backend.py
- Changed RollingSummaryMemory.__init__ signature to accept
  summarize_fn: Callable[[list[dict]], Awaitable[str]]
- All three backends (OpenAI, Anthropic, Google) now instantiate
  the same RollingSummaryMemory class with backend-specific callables
- Extracted shared summarize prompt to module-level _SUMMARIZE_PROMPT

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:14:50 +00:00
Ubuntu
dca03500ec Add thread safety to MeshConnector node caches and StatusData
- 4a: Add threading.Lock to MeshConnector protecting _node_names and
  _node_positions dicts that are read/written from Meshtastic's pubsub
  thread callbacks (_on_receive, _on_node_update, _cache_node_info)
  and read from async code (get_node_position, get_node_name)
- 4b: Add threading.Lock to StatusData protecting counters and activity
  list that are written from the async event loop and read from the
  HTTP server thread in to_dict()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:13:12 +00:00
Ubuntu
c1f2c48494 Fix bugs: MeshMessage position field, summary loading, Google system prompt, import placement, cleanup timer
- 1a: Declare _position as proper dataclass field with field(default=None, init=False)
  so hasattr() check isn't needed and the attribute always exists
- 1b: Load persisted conversation summaries from DB into memory cache on startup
  via new _load_summaries() method called after backend creation
- 1c: Use Gemini's system_instruction parameter on GenerativeModel instead of
  only prepending to first message, so system prompt persists across all turns
- 1d: Move 'import os' from line 198 to top of main.py with other imports
- 1e: Replace unreliable modulo-based cleanup timer with _last_cleanup timestamp
  comparison that won't miss hours due to async sleep jitter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:11:46 +00:00
bc3e85a6fb Add 2-day forecast to weather command
Shows current conditions plus tomorrow and next day forecast
with hi/lo temps, conditions, and rain probability if >20%
2025-12-15 15:00:52 -07:00
173af91d45 Increase max_tokens to 500 for web search/RAG responses 2025-12-15 14:34:21 -07:00
ed97bf8d8b Fix web search: use features.web_search for Open WebUI 2025-12-15 14:28:36 -07:00
8a896cfc5a Fix web search: use tool_ids parameter for Open WebUI 2025-12-15 14:22:03 -07:00
e7c44a5f1c Add web search toggle for Open WebUI
- Add web_search config option to LLMConfig
- Pass web_search: true in extra_body when enabled
- Add toggle in configurator LLM submenu (option 7)
2025-12-15 14:11:27 -07:00
0d29ad49c2 Fix restart loop issue - use PID file for clean bot restart
- Use PID file to track bot process instead of pkill pattern matching
- Add 3-second debounce after restart to prevent signal storms
- Properly distinguish bot process from config tool process
- Clean up PID file on bot exit
2025-12-15 14:01:14 -07:00
152f46282f Add toggle to enable/disable system prompt 2025-12-15 13:56:10 -07:00
459028e79e Allow empty system prompt in configurator 2025-12-15 13:53:14 -07:00
8647dd3d91 Add weather settings back to configurator menu 2025-12-15 13:43:18 -07:00
95b194967c Simplify configurator to essential config options
Reduced TUI menu to 10 core options:
1. Bot Settings
2. Connection
3. LLM Backend
4. Response Settings
5. Channels
6. History & Memory
7. Rate Limits
8. Web Status Page
9. Announcements
10. Setup Wizard

Added fq51BBS-style save/restart options:
- 11. Save (stay in menu)
- 12. Save & Restart Bot (apply changes now)
- 13. Save & Exit (save, restart, exit)
- 14. Exit without Saving

Removed from UI (still in code for future use):
- Safety & Filtering
- User Management
- Commands/Custom Commands
- Personality/Personas
- Logging
- Webhooks

Simplified default config and example config to match.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 13:38:33 -07:00
1747edd150 Update TUI configurator with all new config sections
Major expansion of the configurator TUI to support all new config options:

Main Menu:
- Reorganized into 3 tables: Core Settings (1-6), Advanced Settings (7-12), Features (13-16)
- Added options 7-16 for all new config sections

New Submenus Added:
- Rate Limits (7): messages_per_minute, global rate, cooldown, burst allowance
- Safety & Filtering (8): profanity filter, blocked phrases, require_mention, emergency keywords
- User Management (9): blocklist, allowlist, admin nodes, VIP nodes with interactive editors
- Commands (10): enable/disable, prefix, disabled commands, custom commands editor
- Personality (11): system prompt override, context injection, personas editor
- Logging (12): log level, file path, rotation settings, log verbosity toggles
- Web Status Page (14): enable, port, display options, authentication
- Announcements (15): enable, interval, channel, messages editor, random order
- Webhooks (16): enable, URL, events selection

Updated Submenus:
- History (6): Added memory settings (enabled, window_size, summarize_threshold)

All config options are now accessible through the TUI - no need to edit YAML files directly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 13:18:43 -07:00
165da72d8d Add comprehensive config options matching fq51bbs
New features:
- Rate limiting (per-user and global)
- Enhanced logging with file rotation
- LLM fallback backend support
- Safety filtering (profanity, blocked phrases, emergency keywords)
- User management (blocklist, allowlist, admin/VIP nodes)
- Custom commands with static responses
- Personality/prompt templates with persona switching
- Web status page with JSON API
- Periodic announcements/broadcasts
- Webhook integrations

New modules:
- rate_limiter.py - Per-user and global rate limiting
- safety.py - Response filtering and user access control
- personality.py - Prompt templates and persona management
- web_status.py - Simple web status dashboard
- announcements.py - Periodic broadcast scheduler
- webhook.py - Webhook notification client
- log_setup.py - Enhanced logging configuration
- backends/fallback.py - LLM fallback wrapper

Config expanded from ~50 to ~200 lines with full documentation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 13:10:02 -07:00
04248bc692 Change web config port from 7681 to 7682
Avoids conflict with fq51bbs which uses 7681

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 12:06:47 -07:00
60acef9d78 Remove redundant docker-compose files
Serial vs TCP is now configured via web interface, not separate compose files.
Just uncomment devices section in docker-compose.yml if using USB serial.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 12:05:30 -07:00
389e59c18e Add web-based config interface via ttyd
- Install ttyd in Docker image for browser-based TUI access
- Create docker-entrypoint.sh to run ttyd + bot with auto-restart
- Expose port 7681 for web config access
- Update docker-compose.yml with proper configuration

Access config at http://localhost:7681 after starting container

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 12:02:14 -07:00
fd3f995ebb Initial commit: MeshAI - LLM-powered Meshtastic assistant
Features:
- Multi-backend LLM support (OpenAI, Anthropic, Google)
- Rolling summary memory for token optimization (~70-80% reduction)
- Per-user conversation history with SQLite persistence
- Bang commands (!help, !ping, !reset, !status, !weather)
- Meshtastic integration via serial or TCP
- Message chunking for mesh network constraints (150 char limit)
- Rate limiting to prevent network congestion
- Rich TUI configurator
- Docker support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 11:53:46 -07:00