Commit graph

172 commits

Author SHA1 Message Date
62f04a3e09 fix: Align parameter names between data_store and source_manager
- create_dispatcher uses data_store=
- MessageRouter uses source_manager=
- Added get_all_traceroutes() and get_all_channels() compat methods

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 03:50:58 +00:00
800e4d9e7e fix: Add get_all_traceroutes and get_all_channels compat methods
Completes backwards compatibility layer for mesh_health.py.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 03:45:48 +00:00
c756727cad feat: Node source overlap for gateway coverage metrics
Replaces broken per-packet gateway sampling with node-level source counting.
Each Meshview/MeshMonitor source represents a gateway view of the mesh.
If a node is seen by N sources, its packets are reaching N gateways.

- Removed _sample_gateway_coverage() (required non-existent API)
- Rewrote _enrich_deliverability() to use node.sources count
- Per-node: avg_gateways, max_gateways, source_reach, deliverability_score
- Mesh-wide: avg 4.16 gateways/node with 7 sources
- Fixed edge.timestamp -> edge.last_seen in get_all_edges()

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 03:31:48 +00:00
f30cd0a8bf fix: Add backwards compatibility methods for mesh_health.py
- Add hasattr check for fetch_recent_packets in gateway sampling
- Add get_all_nodes(), get_all_telemetry(), get_all_packets(), get_all_edges() methods
- These methods return data in dict format expected by mesh_health.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 03:09:30 +00:00
af2f66d71d Merge subscriptions from main into feature branch (with full data pipeline) 2026-05-05 02:57:41 +00:00
Ubuntu
b20dea60e2 feat(subscriptions): Add Phase 4 subscription system for scheduled reports
- Create subscriptions.py with SubscriptionManager class for SQLite storage
- Add subscribe.py commands: !sub, !unsub, !mysubs with aliases
- Update dispatcher.py to register subscription commands
- Modify main.py with scheduler tick (60s) and _check_scheduled_subs()
- Add build_node_compact() and build_region_compact() to mesh_reporter.py
- Support daily, weekly, and alerts subscription types
- Support mesh, region, and node scope filtering
- 5-minute matching window for schedule tolerance
- Dedup via last_sent tracking

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-05 02:26:12 +00:00
e06d71036f fix: !neighbors shows infra links without requiring SNR, edge SNR enrichment from traceroutes
- Removed SNR-required filter from !neighbors command
- Show all infra neighbors, add signal quality when available
- Enrich edges with SNR from traceroute snrTowards/snrBack data
- Fallback: use node-level SNR for edges without traceroute data
- Sort by SNR when available, alphabetically otherwise

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-05 01:18:37 +00:00
8c3b6a1f09 fix: Fundamental ID matching — packets, telemetry, and utilization now work
Root cause: health engine keyed nodes by database row IDs instead of
Meshtastic node numbers. Packets and telemetry could never match.

Fixed:
- Store _node_num on all normalized nodes (mesh_sources.py)
- Key health engine node dict by _node_num (mesh_health.py)
- Fix packet field names: from_node not from/fromId
- Fix telemetry parsing: handle telemetryType/value structure
- Increase packet/telemetry fetch limits for 24h coverage
- Fix utilization formula to compute actual airtime percentage
2026-05-04 21:47:18 +00:00
3959444a09 feat: Complete data pipeline — utilization, behavior, power, solar, traceroutes all wired 2026-05-04 21:22:30 +00:00
df197cc395 fix: Scope detection, follow-up context, utilization calculation, duplicate disambiguation
- router.py: Fixed region scope detection to match longest region name first
- router.py: Added region abbreviations (SCID, SWID, etc.) for quick matching
- router.py: Added city name mapping (Boise -> South Western ID, etc.)
- router.py: Fixed node longname matching (case-insensitive substring)
- router.py: Added follow-up message context tracking (_user_mesh_context)
- router.py: Added more mesh keywords (noisy, traffic, packets, etc.)
- mesh_reporter.py: Added disambiguation for duplicate shortnames in region detail
- mesh_health.py: Added util_data_available flag to track packet data presence
- mesh_health.py: Passes has_packet_data through score computation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 20:56:54 +00:00
ece8bfd4d9 fix: Normalize role enums, GPS fields, and timestamps across sources
Add _normalize_node() function to mesh_sources.py that standardizes:

- Role field: Map integer enums to string names using correct Meshtastic
  protobuf values (0=CLIENT, 1=CLIENT_MUTE, 2=ROUTER, 3=ROUTER_CLIENT,
  11=ROUTER_LATE, etc.). Now detects 18 infrastructure nodes.

- GPS fields: Check latitude/longitude, then last_lat/last_long (Meshview
  scaled integers), then lat/lon. Filter out invalid 0,0 coordinates.
  Now 238 nodes with GPS (was 201).

- Timestamps: Normalize to last_heard as epoch seconds. Handle
  microseconds (last_seen_us), milliseconds, and seconds formats.
  Now 527 nodes with timestamps (was 0).

- Hardware model: Prefer string hw_model over integer hwModel.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 20:22:07 +00:00
44c74ccfd4 feat: Phase 3 - LLM mesh health integration, recommendations, and health commands
New files:
- mesh_reporter.py: MeshReporter class for prompt injection
  - build_tier1_summary(): ~500-800 token mesh health summary
  - build_region_detail(): Detailed region breakdown
  - build_node_detail(): Single node info with recommendations
  - build_recommendations(): Optimization suggestions
  - build_lora_compact(): Short format for LoRa messages
  - list_regions_compact(): Region list with scores

- commands/health.py: !health and !region commands
  - !health: Quick mesh summary (no LLM)
  - !region [name]: Region info or list all regions

Modified files:
- router.py: Mesh question detection and prompt injection
  - _is_mesh_question(): Keyword/phrase matching
  - _detect_mesh_scope(): Node/region/mesh scope detection
  - Inject Tier 1/2 data for mesh questions
  - Add mesh awareness instructions to LLM

- main.py: Create MeshReporter, pass to dispatcher/router

- commands/dispatcher.py: Register health/region commands

- mesh_health.py: Fix role type (int -> str)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 19:19:42 +00:00
89315a8008 Fix configurator: region_labels -> regions
Update main menu to use new regions attribute instead of old region_labels.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 18:56:13 +00:00
959c128c6f Add node/edge deduplication to MeshSourceManager
- Add _extract_node_num() helper to normalize node IDs across formats
- Add _normalize_edge_key() helper for undirected edge deduplication
- Update get_all_nodes() to deduplicate by nodeNum with _sources field
- Update get_all_edges() to deduplicate by sorted (from, to) tuple
- Update get_all_telemetry() to deduplicate by (nodeNum, timestamp)
- Add get_dedup_stats() method for raw vs dedup counts
- Add get_stats_by_source() method for per-source statistics
- Change _source field to _sources (list) for multi-source tracking

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 18:02:47 +00:00
06c2b9e4e2 feat: Expand region defaults to ID/UT
10 regions covering Idaho and Utah:
- Northern ID (Coeur d alene)
- Central ID (Salmon)
- South Western ID (Boise)
- South Central ID (Twin Falls)
- South Eastern ID (Idaho Falls)
- Northern UT (Ogden)
- Central UT (Salt Lake City)
- Eastern UT (Vernal)
- Western UT (Tooele)
- Southern UT (St. George)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 17:43:59 +00:00
584616c8a5 feat: Infer node region from neighbors
Nodes without GPS can be assigned to a region based on their
neighbors. Uses edge data to build neighbor graph, then assigns
unlocated nodes to the most common region among their neighbors.
Iterates until no more assignments possible.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 17:38:57 +00:00
c3f1347b4b refactor: Replace auto-clustering with fixed region anchors
- Regions are now user-defined anchor points (name + lat/lon)
- Nodes assigned to nearest region, no distance limits
- Removed auto-naming and region_labels/infra_overrides
- Added Idaho region defaults in TUI
- Simpler, deterministic, user-controlled

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 17:35:28 +00:00
fe2b77097b fix: Handle Meshview GPS and timestamp formats
- last_lat/last_long are scaled integers (divide by 1e7)
- last_seen_us is in microseconds (divide by 1e6)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 17:21:51 +00:00
fd9ba21f4a fix: Handle Meshview API wrapper format
Meshview API returns {"nodes": [...]} and {"edges": [...]} wrapper
dicts, not raw lists. Added _extract_list() helper to unwrap.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 17:13:57 +00:00
5c8aeb3974 feat: Add User-Agent header to API requests
Adds MeshAI/x.x User-Agent for good API citizenship and easier
traffic identification by Meshview/MeshMonitor operators.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 17:06:14 +00:00
a7c409e406 feat: Add Phase 2 - Geographic Hierarchy and Health Scoring
Implements mesh intelligence with geo clustering, four-pillar health scoring,
and auto-naming regions from GPS data.

New: geo.py, mesh_health.py
Modified: config.py, main.py, router.py, configurator.py, config.example.yaml

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 16:43:12 +00:00
b945558ba3 feat: Phase 1 — multi-source data aggregation from Meshview and MeshMonitor APIs
- Add MeshviewSource class for fetching nodes, edges, stats from Meshview API
- Add MeshMonitorDataSource class for fetching nodes, channels, telemetry,
  traceroutes, network stats, topology, packets, solar from MeshMonitor API
- Add MeshSourceManager for managing multiple sources with aggregation
- Add MeshSourceConfig dataclass and mesh_sources list to config
- Integrate source_manager into main.py with periodic refresh
- Add source_manager parameter to MessageRouter (for future Phase 3)
- Add Mesh Sources TUI menu with add/edit/remove/test functionality
- Update config.example.yaml with mesh_sources section

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 16:26:58 +00:00
root
584d1b199d docs: Update advBBS link to zvx-echo6/advbbs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 14:29:43 +00:00
root
0e36869a5f feat: Hybrid RAG knowledge base, sentence-aware chunking, MeshMonitor HTTP sync
Knowledge Base:
- Hybrid FTS5 + vector search using sqlite-vec and bge-small-en-v1.5
- Reciprocal Rank Fusion for result merging
- Domain-aware query construction handles typos
- Configurable weights for keyword vs semantic matching

Message Chunking:
- Sentence-aware splitting respects message boundaries
- Continuation prompts for long responses
- Natural follow-up detection (yes, ok, continue, more, etc.)
- Per-user continuation state management

MeshMonitor Integration:
- HTTP API trigger sync (replaces file-based triggers.json)
- Dynamic refresh interval
- Trigger injection into LLM prompt

Other:
- Updated system prompt for better response length control
- Simplified responder to handle message lists
- Updated README with new features and architecture diagram
- Cleaned up config.example.yaml

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-04 07:44:12 +00:00
root
e65a558c6f docs: Add MeshMonitor integration section and credit to README
- Add MeshMonitor Integration section with features and configuration
- Add credit line in Features list
- Link to github.com/Yeraze/meshmonitor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-03 07:10:21 +00:00
root
5f66b69c9c feat: Dynamic identity system prompt from bot config
- Build system prompt dynamically using bot.name and bot.owner from config
- Reorder prompt: identity -> static prompt -> MeshMonitor (conditional) -> mesh context
- MeshMonitor description only injected when meshmonitor.enabled is true
- Update default system_prompt to static parts only (commands, architecture, rules)
- Fix meshmonitor.py to handle trigger arrays (not just strings)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-03 05:45:58 +00:00
root
494f4510ac feat(tui): Add MeshMonitor Sync settings menu with View Triggers
- Add MeshMonitor Sync as main menu option 9
- Toggle enabled/disabled, triggers file path, inject_into_prompt
- View Triggers shows loaded patterns from triggers.json

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-03 03:30:53 +00:00
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