# MESH-API Changelog All notable changes to MESH-API, newest first. For the project overview and setup, see [README.md](README.md). For the built-in extension reference, see [EXTENSIONS.md](EXTENSIONS.md). --- ## Release Summaries (v0.6.0 → present) - **v0.7.4.1 Beta** — 📤 **Send composer revamp + Previously Seen nodes + MeshCore presence fix.** The dashboard's **Send a Message** box was rebuilt with **Broadcast / Direct** mode tabs and, in broadcast mode, **per-network checkboxes** so you can target one or more radios at once: 📡 **Meshtastic**, 🟣 **MeshCore**, and 🌉 **Bridged**. The **Bridged** dropdown now shows **both** routed channels for each entry (e.g. `0 → 📡 LongFast + 🟣 Public`) instead of a single channel name, so it's clear which Meshtastic *and* MeshCore channels a bridged send will reach. The Available Nodes list gained a **Previously Seen** section (with an adjustable staleness threshold) for nodes that have gone quiet, with favorites pinned back into the main list. 🐛 Fixes **MeshCore node presence**: MeshCore contacts no longer fall out of the live list just because their last *advert* is old — presence is now **activity-based** (message activity / `last_msg`), since MeshCore nodes advertise only occasionally rather than beaconing continuously like Meshtastic. The footer link now points to **mesh-api.dev**. - **v0.7.4 Beta** — 🧙 **Setup Wizard now covers MeshCore.** The first-start (and re-runnable) **Setup Wizard** was brought up to date with the v0.7.x multi-radio architecture. It now has a dedicated **🟣 MeshCore Radio** step (enable MeshCore, choose **serial / TCP / BLE**, set the port/host/address, toggle **adverts** and **channel bridging**), a checkbox on the Meshtastic step to run a **MeshCore-only / standalone node** (`meshtastic_enabled`), and a **Default Send Network** selector (`auto` / Meshtastic / MeshCore / both) on the node-identity step. The wizard pre-populates every field from the existing `config.json`, so a fresh install can be fully configured for either or both radios without hand-editing JSON. - **v0.7.3.7 Beta** — 🟣 **All extensions now route to MeshCore (bug fix).** Messages and AI replies sent to the mesh from **any** extension — Telegram, Discord, Home Assistant, the alert feeds, MQTT, Matrix, n8n, and the rest — now reach **every connected radio (Meshtastic *and* MeshCore)**, not just Meshtastic. Previously the shared `send_to_mesh()` helper (and a couple of extensions that sent directly) only used the Meshtastic interface, so e.g. a Telegram message arrived on Meshtastic but never on MeshCore (GitHub [#59](https://github.com/mr-tbot/mesh-api/issues/59)). Extension outbound now flows through the core network-agnostic `web_send` path, fanning out per the `default_send_network` setting (`auto` = whichever radios are connected). No config or extension changes required. - **v0.7.3.6 Beta** — 💓 **AI endpoint heartbeat (token-free connection status).** Each **named AI endpoint** now shows a live **heartbeat** status dot in the **🔌 Manage AI Endpoints** panel (🟢 online · 🟡 reachable/auth · 🔴 offline), so you can tell at a glance whether an endpoint is still reachable. A lightweight background thread periodically pings each endpoint's OpenAI-compatible `/models` route — a cheap GET that **costs zero AI tokens** — and the UI auto-refreshes while the panel is open, with a **Check now** button per endpoint for an on-demand probe. New endpoint: `GET /api/ai_endpoints/health`. Heartbeat interval is configurable via `ai_endpoint_heartbeat_sec` (default 60s). - **v0.7.3.2 Beta** — 🗺️ **Map filter + MeshCore nodes now appear + [MT]/[MC] labels.** The Node Map gets a **Show:** filter to display **All / ⭐ Favorites only / 🔵 Meshtastic only / 🟣 MeshCore only** nodes (choice persists), with a live count. Fixes a bug where **MeshCore nodes reporting GPS never showed on the map** — the map only read the page-load snapshot, so positions discovered afterward (common for MeshCore adverts) were ignored; the map now merges live `/nodes` GPS for **both** networks on every refresh. Map tooltips now tag every node with its network (`[MT]` for Meshtastic, `[MC]` for MeshCore). - **v0.7.3.1 Beta** — 🔌 **Named AI endpoints + live extension toggle fix.** You can now define multiple **named AI endpoints** (each with its own **name**, **type**, and **config** — URL, API key, model, timeout) from a new **🔌 Manage AI Endpoints** panel in the **🤖 Channel Agents** modal, then assign a different endpoint to each channel. This lets you point two channels at two separate OpenAI-compatible agents without renaming a shared provider. New endpoints: `GET`/`POST /api/ai_endpoints`. Also fixes a bug where the extension **Enable/Disable** button did nothing for an already-**loaded** extension — toggling now **live-loads/unloads** the extension (no restart needed). - **v0.7.3 Beta** — 🌉 **Cross-network channel bridge UI.** When both a Meshtastic and a MeshCore radio are connected, you can now **mirror chat between channels on the two networks** from a new **🌉 Bridge** toolbar button — no more hand-editing `config.json`. The visual editor maps **Meshtastic channel ⇄ MeshCore channel** links (the per-device channel indexes can differ), with a per-link **direction** (both / MT→MC / MC→MT), an overall **bridge on/off** toggle, and customizable **tags** (e.g. `[MT]` / `[MC]`) added to bridged messages. Changes **apply live** (no restart) and persist to the `meshcore` block of `config.json`. The Bridge button appears only when MeshCore is in play, and the editor shows live radio-connection status. New endpoints: `GET`/`POST /api/channel_bridge`. (Slash commands and AI replies are never bridged.) - **v0.7.2.5 Beta** — 🕸️ **Mouse-reactive mesh background.** The dashboard's plain black background is replaced with a dense, animated **"mesh" grid** — a field of points connected by lines that drift continuously and **warp toward your mouse** in real time, evoking a living mesh network behind the UI. The UI boxes are now translucent so the grid shows through behind the panels (inputs and controls stay fully opaque). Fully controllable from **UI Settings → Appearance**: toggle it **on/off**, adjust the **speed**, **line thickness**, **color**, and the **box opacity** (how transparent the panels are). Renders on a single GPU-friendly canvas behind the panels. - **v0.7.2.4 Beta** — ☁️ **MQTT node indicators + smaller traffic graph.** Nodes heard over **MQTT** (rather than direct RF) now show a teal **☁ MQTT** badge in the Available Nodes list and a distinct teal map marker (with an "☁ Heard via MQTT" note in the popup and a ☁ on the map label), so you can tell at a glance which nodes are coming in via MQTT. The Traffic Monitor graph is now **half the height** for a more compact dashboard. - **v0.7.2.3 Beta** — 📊 **Traffic monitor upgrades.** The Traffic Monitor is now **full-width** (double-wide) and sits **above the Node Map / Send row** by default (still draggable, hideable, and reorderable like every other box). It now counts **all received packets** — position, telemetry, nodeinfo, routing, text, etc. — not just chat messages, via a dedicated all-packet radio hook. Added a **user-selectable time window** (1 min / 5 min / 15 min / 30 min / 1 hour / 6 hours), persisted per browser, with the graph re-bucketed so it stays readable at any length. `GET /api/traffic` gained `seconds` (up to 6 h) and `buckets` parameters. - **v0.7.2.2 Beta** — 📊 **Traffic monitor + 🚨 emergency alerts + Hermes is now an extension.** - **Real-time traffic monitor** — a new movable **📊 Traffic Monitor** box at the top of the dashboard draws live mesh radio activity as green→red bars (RX received / TX sent, last 60 s). Like every panel it can be dragged, hidden, or reordered. Backed by a new `GET /api/traffic` endpoint. - **Emergency alert box** — when a node triggers `/emergency` (or `/911`), a large **flashing red box** appears in the masthead (between the logo and the toolbar, below the connection status). Click it to open a modal with the alert text and node information (name, ID, GPS/map link, reply). Alerts **must be cleared by the user** and persist until then. - **Hermes moved out of core** — the Nous Research **Hermes** AI provider is now a bundled **extension** (`extensions/hermes`) instead of core code, keeping the core lean. It registers itself as the `hermes` AI provider automatically, so `ai_provider: "hermes"` and Channel-Agent `provider: hermes` keep working; configure it from the **🧩 Extensions** manager. Legacy `hermes_*` keys in the main config are imported automatically on first load. - **v0.7.2.1 Beta** — 🧩 **All v0.7.x settings are now in the WebUI config form**, plus a channel-panel fix. The friendly **⚙️ Config** editor gained sections for **Multi-Radio** (`meshtastic_enabled`, `default_send_network`), the **MeshCore** radio, the **MCP Server**, **Firmware & Updates**, and the **Hermes** and **Home Assistant** AI providers — previously these v0.7.x blocks were only reachable via the Raw JSON tab. 🐛 Also hardened the **Channel Messages** panel so a single malformed message can no longer blank the entire panel (each channel/message now renders in isolation; channels sort numerically). - **v0.7.2 Beta** — 🤖 **Channel Agents are now manageable from the WebUI.** A new **🤖 Agents** toolbar button opens a Channel Agents manager where you can assign any channel to a specific **AI provider** (OpenAI, Hermes, Ollama, Claude, …) or a loaded **extension** (e.g. OpenClaw), with an optional per-channel **PIN** gate. Assignments **apply live** (no restart) and persist to [config.json](config.json). Channels with an assigned agent now show a badge (🤖 provider / 🧩 extension) in the Channel Messages panel, and the legacy `home_assistant_channel_index` mapping is surfaced automatically. The `/api/channel_agents` endpoint gained a `POST` to save assignments. - **v0.7.1 Beta** — 🐛 **Bug fix:** the WebUI Extensions Manager **Enable / Disable** buttons now update immediately. The toggle wrote the new state to the extension's `config.json` but the in-memory status returned by `/extensions/status` stayed stale, so the button label and status dot never changed (the change only appeared after a restart). The loader's in-memory state is now kept in sync, so toggling reflects instantly; use **Reload** (or restart) to apply it to the running extensions. - **v0.7.0 Beta** — 🚀 **Multi-radio overhaul + MCP tool server + firmware updates.** - **MeshCore is a first-class radio.** Run Meshtastic-only, MeshCore-only (fully standalone — no Meshtastic device required), or both with MESH-API as the man-in-the-middle. MeshCore connects over serial / TCP / BLE. - **Cross-network routing & UI parity** — per-network connection banner, a node **network filter** with collapsible Meshtastic/MeshCore sections, network badges on nodes and messages, distinct map markers, MeshCore channels (group chats / private channels) in the send form, and DMs to MeshCore contacts — mirroring the Meshtastic experience. - **MCP (Model Context Protocol) server** — external AI agents (Claude, Perplexity, Hermes, custom) can call MESH-API core functions **and** extensions as tools, driving the mesh networks as an agentic backend. `POST /mcp` (Streamable HTTP / JSON-RPC 2.0), disabled by default, bearer-token auth. See **[MCP Server](README.md#mcp-server-model-context-protocol)**. - **Firmware & software updates** — detects the connected Meshtastic/MeshCore device, checks GitHub for newer Meshtastic firmware, MeshCore firmware, and MESH-API itself, and shows a 🔄 **Updates** notification with **stable / beta / alpha release-channel** selection per firmware. Optional one-click ESP32 flashing (off by default). See **[Firmware Updates](README.md#firmware--software-updates)**. - **Bug fixes:** **#59** (MeshCore-origin messages now reach plugins like Telegram and the AI) and **#58** (bounded Meshtastic (re)connect + an actually-running connection watchdog). - New config blocks in [config.json](config.json): `meshtastic_enabled`, `default_send_network`, `meshcore`, `mcp`, and `firmware`. - MeshCore requires the `meshcore` Python package (already in [requirements.txt](requirements.txt)): `pip install meshcore`. ESP32 firmware flashing additionally needs `esptool`. - **v0.6.0** — Full release! Plugin-based extensions system with 30 built-in extensions, 12 AI providers, drop-in plugin architecture, interactive node map, collapsible channel views, draggable dashboard layout, and a fully revamped WebUI. **Docker images now available** for x86_64 and ARM64 (Raspberry Pi 4/5)! > **Community note:** A massive amount of work has landed — the plugin-based extensions system, 30+ extensions, OpenClaw AI agent integration, MeshCore bridging, and the full WebUI overhaul all shipped in a compressed timeline. **I depend on the community to help test, identify, and crush bugs.** If something breaks, doesn't work as documented, or behaves unexpectedly — please open a [GitHub Issue](https://github.com/mr-tbot/mesh-api/issues) with as much detail as possible. --- ## Detailed History ### v0.7.4.1 Beta — Send Composer Revamp, Previously Seen Nodes, MeshCore Presence Fix - **Send a Message composer rebuilt.** The dashboard send form now has explicit **Broadcast** and **Direct** mode tabs (`setSendMode()`), replacing the old single mode toggle. - **Broadcast mode** exposes a per-network picker with checkboxes for 📡 **Meshtastic**, 🟣 **MeshCore**, and 🌉 **Bridged**; each enabled network shows its own channel dropdown, and a send fans out to every selected target (`/ui_send` now accepts a comma-separated `targets` list of `mt:idx` / `mc:idx` / `both:idx` tokens, with the legacy single `channel_index` path retained for backward compatibility). - **Bridged dropdown shows both channels.** The 🌉 Bridged channel dropdown now renders each option as `index → 📡 + 🟣 ` (e.g. `0 → 📡 LongFast + 🟣 Public`), pairing the live Meshtastic channel snapshot with the MeshCore channel cache, so the operator can see exactly which two channels a bridged broadcast will hit instead of a single ambiguous name. - **Direct mode** searches the combined node list across both networks and shows a hint indicating which network the selected destination lives on. - **Previously Seen node section.** The Available Nodes panel now splits nodes into a live list and a **Previously Seen** list for nodes that have gone quiet, controlled by an adjustable staleness threshold. Favorited nodes stay pinned in the main list. - **MeshCore presence fix.** MeshCore addressable contacts were being dropped into *Previously Seen* (or removed) because their occasional **advert age** was being treated like a continuous Meshtastic beacon. Presence for `!mc-` nodes is now **activity-based**: `getNodeLastHeardMs()` considers only message-activity signals (`last_msg` epoch + the message feed) for MeshCore nodes, while Meshtastic nodes keep using all presence signals. `meshcore_core.py`'s `get_nodes()` now surfaces a dedicated `last_msg` field (message-rx-only epoch) alongside `last_advert` / `last_heard`. This reflects that MeshCore nodes maintain a persistent contact book and advertise only occasionally rather than beaconing continuously. - **Footer link → mesh-api.dev.** The dashboard footer/masthead project link now points to `https://mesh-api.dev`. - **Docs reorganized.** The README was slimmed: the full extension-development guide moved to **[DEVELOPING_EXTENSIONS.md](DEVELOPING_EXTENSIONS.md)**, the configuration reference to **[CONFIGURATION.md](CONFIGURATION.md)**, and integration setup guides to **[INTEGRATIONS.md](INTEGRATIONS.md)**. ### v0.7.4 Beta — Setup Wizard Covers MeshCore - **Wizard brought in line with the multi-radio architecture.** The first-start Setup Wizard (also re-runnable from the **⚙️ Config** editor header via **🧙 Run Setup Wizard**) previously only configured a single Meshtastic radio. It now reflects the v0.7.x design where MeshCore is a first-class radio. - **New 🟣 MeshCore Radio step** — enable/disable MeshCore, pick the **connection type** (**serial** / **TCP** / **BLE**) with the relevant fields shown for each (serial port + baud, TCP host + port, or BLE address), and toggle **send adverts** and **channel bridging** (MT⇄MC). Writes the `meshcore` block of `config.json`. - **MeshCore-only / standalone toggle** — the Meshtastic step gained an **Enable Meshtastic radio** checkbox; unchecking it (`meshtastic_enabled=false`) lets a fresh install be configured as a MeshCore-only node directly from the wizard. - **Default Send Network selector** — the node-identity step now sets `default_send_network` (`auto` / Meshtastic / MeshCore / both). - **Pre-population** — all new fields load from the existing `config.json` when re-running the wizard, so nothing is lost. No backend/config schema changes — the wizard simply writes the same keys the Config editor already supports. ### v0.7.3.7 Beta — All Extensions Route to MeshCore - **Bug fix (GitHub [#59](https://github.com/mr-tbot/mesh-api/issues/59)).** Extension-originated mesh traffic now reaches **both** networks. A user running Meshtastic + MeshCore + Telegram reported that a message sent from Telegram arrived on Meshtastic but **never on MeshCore** ("like the TG extension is not known for MeshCore"). - **Root cause.** The shared `BaseExtension.send_to_mesh()` helper proxied straight to the Meshtastic-only `send_broadcast_chunks` / `send_direct_chunks`, ignoring MeshCore entirely. A few extensions (Discord inbound, Home Assistant replies) sent through the Meshtastic interface directly with the same blind spot. - **Fix.** `send_to_mesh()` now routes through the core **network-agnostic `web_send`** path (added in v0.7.0), which fans a broadcast out to every active radio and routes DMs by the destination's network prefix, honoring `default_send_network` (`auto` = whichever radios are connected). Discord's webhook + polling inbound and Home Assistant's reply path were updated to use the same helper. A Meshtastic-only fallback is retained for older cores. This makes **all 30+ extensions** reach MeshCore with no per-extension config. ### v0.7.3.6 Beta — AI Endpoint Heartbeat - **Token-free heartbeat for named AI endpoints.** A background thread (started in `main()`) periodically checks each named AI endpoint by issuing a plain `GET` to its OpenAI-compatible `/models` route — derived automatically from the endpoint's chat/completions URL. Any HTTP response means the server is reachable; the check never sends a chat completion, so it **spends no AI tokens**. - **Live status in the WebUI.** The **🔌 Manage AI Endpoints** panel (inside **🤖 Channel Agents**) now shows a per-endpoint status dot: 🟢 **online** (HTTP 200), 🟡 **reachable**/**auth?** (server up, or 401/403 key issue), 🔴 **offline** (connection refused / timeout / DNS error), with round-trip latency. The panel auto-refreshes status every 30s while open, and each row has a **Check now** button for an immediate probe. - **New endpoint:** `GET /api/ai_endpoints/health` returns cached per-endpoint status; pass `?check=1` to force an immediate live re-check. - **New config key:** `ai_endpoint_heartbeat_sec` (default `60`) controls the background heartbeat interval. ### v0.7.0 Beta — Initial Full MeshCore Support > Run MESH-API with a Meshtastic node, a MeshCore node, or **both** with > cross-network routing. Widely untested — community feedback wanted. #### Multi-radio (MeshCore as a first-class radio) - **MeshCore promoted to a core-owned radio** (`meshcore_core.py`) on equal footing with Meshtastic, feeding the *same* network-agnostic message pipeline. Connects over serial / TCP / BLE. - **Three topologies:** Meshtastic-only (unchanged), MeshCore-only standalone (`meshtastic_enabled: false`, no Meshtastic device needed), or both with MESH-API as the man-in-the-middle bridge. - **Cross-network everything** — slash commands, AI, and every extension now work on both networks; outbound send to one network or both at once. - **WebUI parity for MeshCore** — per-network connection banner; node **network filter** with **collapsible Meshtastic/MeshCore sections**; network badges (📡/🟣) on nodes & messages; distinct purple map markers with DM/interact; MeshCore channels (group chats / private channels) in the send form; DMs to MeshCore contacts. - **Staged startup + exponential backoff** so two USB radios on a power-limited host (e.g. Pi Zero) don't fight over the bus during connect. #### MCP server (Model Context Protocol) - New built-in **MCP server** (`mcp_server.py`) at `POST /mcp` (Streamable HTTP / JSON-RPC 2.0, no async deps). Lets external AI agents (Claude, Perplexity, Hermes, custom) call MESH-API core functions and extensions as **tools**, using the mesh as an agentic backend. - Core tools for sending, listing nodes/messages/channels, AI queries, running commands, and MeshCore contacts; **every extension slash command is auto-exposed** as `ext_cmd_*`, and extensions can add richer typed tools via `get_mcp_tools()` + `call_mcp_tool()`. - Disabled by default; bearer-token auth, Origin allowlist, rate limiting, gated emergency tool. #### Firmware & software updates - New **update manager** (`firmware_updater.py`) detects the connected Meshtastic/MeshCore device and notifies (🔄 Updates button + badge) when newer Meshtastic firmware, MeshCore firmware, or MESH-API is available. - **Stable / beta / alpha release channels** selectable per firmware. Optional ESP32 over-USB flashing via `esptool` (off by default); nRF52/UF2 + MeshCore use the web flasher. #### Bug fixes - **#59 — MeshCore-origin messages now reach plugins/AI.** Both radios funnel through one inbound pipeline, so a MeshCore message reaches Telegram, Discord, the AI provider, etc. - **#58 — Reconnect hangs.** Bounded Meshtastic (re)connect (no more infinite hang on a wedged Wi-Fi/TCP link) and the connection watchdog is now actually started; exponential reconnect backoff. - **OpenAI reasoning models** — `gpt-5`/`o1`/`o3`/`o4` now use `max_completion_tokens` with proper headroom, fixing empty AI replies. - **Logging cascade** — hardened `script.log` truncation against non-UTF-8 bytes that could spin into a `RecursionError`. #### New config blocks - `meshtastic_enabled`, `default_send_network`, and the `meshcore`, `mcp`, and `firmware` blocks in [config.json](config.json). Old configs keep working; the new keys are additive. ### v0.6.0 (Full Release) #### Bug Fixes - **#53 — Home Assistant interface stale after reconnect** — The `app_context["interface"]` reference is now refreshed after every successful reconnect, preventing `None` errors in HA and other extensions. Thanks to [@InstigatorX](https://github.com/InstigatorX) for reporting. *(GitHub Issue #53)* - **#51 — AI channel reply routing** — Added detailed dispatch logging to trace AI reply routing across channels and DMs. Verified the routing logic correctly respects `respond_to_broadcast_messages`, `respond_to_dms`, and `ai_respond_on_longfast` flags. Thanks to [@droidblastnz](https://github.com/droidblastnz) for reporting. *(GitHub Issue #51)* - **#44 — Stability improvements** — Smart word‑boundary message chunking (never splits mid‑word), `requests.Session()` connection pooling for Ollama calls, `num_predict` parameter to cap AI token generation, cross‑platform `OSError` handling with specific error code checks (errno 19, 32, 107, 108, 110). Thanks to [@omgitsgela](https://github.com/omgitsgela) for reporting. *(GitHub Issue #44)* #### New Features - **Interactive Node Map** — Leaflet.js map view with colored markers for all GPS‑enabled nodes. Dark mode (CARTO dark tiles) and light mode (OpenStreetMap) selectable in settings. Offline detection with a banner notice when tiles are unavailable. Connected node shown as a green circle. Popups display node name, hex ID, last heard, hop count, DM button, and Google Maps link. - **Collapsible Channel Groups** — Channel messages are now grouped by channel name. Each group has a clickable 📻 header that expands/collapses the messages. Unread message counts shown as orange pill badges. - **Draggable Dashboard Layout** — All major dashboard sections (Send Form, Node Map, Message Panels, Discord) can be reordered via ☰ drag handles. The three message columns (DMs, Channels, Nodes) are independently sortable. Sections can be hidden/shown from the UI Settings panel. Layout order persists in localStorage. - **Five Built‑in Notification Sounds** — Two‑Tone Beep, Triple Chirp, Alert Chime, Sonar Ping, Radio Blip generated via Web Audio API. Separate sound assignments for DMs, channels, and per‑node. Per‑node sounds use a dropdown populated from available nodes. Custom sound file upload also supported. Test button and volume slider in the settings panel. - **Compact Settings Panel** — UI Settings redesigned as a two‑column grid with emoji‑labeled sections (⚙️ UI Settings). Includes button theme color, section colors, dark/light map style, hue rotation, section visibility toggles, and an About section with links to Meshtastic, MeshCore, and project resources. - **Node Enhancements** — DM, PING, and PONG buttons shown for every node. Show on Map (fly‑to) and Google Maps buttons on the same line. Last‑heard time displayed with 📡 icon. Node items rendered as rounded cards with hover effects. - **Emoji Section Headers** — All dashboard panels now have emoji prefixes: ✉️ Send a Message, 🗺️ Node Map, 💬 Message Panels, 📨 Direct Messages, 📡 Channel Messages, 📋 Available Nodes, 🎮 Discord Messages. - **Differentiated Send Buttons** — Send, Reply to Last DM, and Reply to Last Channel buttons now have distinct colors (green, blue, purple) for quick visual identification. - **Welcome Setup Guide** — Initial popup changed from beta disclaimer to a friendly setup guide with configuration steps and links to documentation. - **Report a Bug** — Footer button links directly to GitHub Issues for easy bug reporting. #### Visual Overhaul - CSS custom properties (`--bg-primary`, `--bg-panel`, `--bg-input`, `--text-primary`, `--text-muted`, `--border-radius`) for consistent theming. - Segoe UI font stack, smooth transitions, hover effects on panels/messages/nodes. - Mobile‑responsive breakpoints: collapsible map, stacked masthead, footer, and send form at ≤600px. - "❤️ Support this Developer" PayPal donation button added to the footer alongside the version badge. #### Updated Dependencies - protobuf 6.33.5 → 7.34.0 - meshtastic 2.7.7 → 2.7.8 - Flask 3.1.2 → 3.1.3 - twilio 9.10.1 → 9.10.2 - bleak ≥0.22.0 → ≥2.1.1 - meshcore ≥2.2.0 → ≥2.2.30 ### v0.6.0 RC1 (Release Candidate 1) - **WebUI Extensions Manager** - New "Extensions" button in the dashboard toolbar opens a full Extensions Manager modal. - View all available extensions with color-coded status indicators (green=active, yellow=enabled but not loaded, grey=disabled). - Enable/disable extensions directly from the WebUI — toggles are saved to each extension's `config.json`. - Inline JSON config editor for each extension — edit and save any extension's configuration without touching the filesystem. - Hot-Reload button to live-reload all extensions without restarting the server. - New REST API endpoints: `GET /extensions/status`, `GET/PUT /extensions/config/`, `POST /extensions/toggle/`, `POST /extensions/reload`. - **Incoming Message Sound — Fixed & Improved** - The notification sound system has been completely rewritten. Previously, the `