[Feature] Integrate Meshroller into our mesh features + killer setup/use UX #50

Open
opened 2026-06-17 09:40:25 +00:00 by lfg2025 · 4 comments
Owner

Source: https://gitea.l484.com/clasko/Meshroller

Ask: integrate this work into our mesh features, including a killer UX for setting it up and using it.

Next steps:

  • Review the Meshroller repo (capabilities, license, transport/protocol, hardware assumptions)
  • Decide the integration seam vs. our existing mesh stack (core/archipelago/src/mesh/)
  • Design a dead-simple onboarding + usage flow (ties into the Telegram-quality mesh UX plan)
Source: https://gitea.l484.com/clasko/Meshroller Ask: integrate this work into our mesh features, including a killer UX for setting it up and using it. Next steps: - Review the Meshroller repo (capabilities, license, transport/protocol, hardware assumptions) - Decide the integration seam vs. our existing mesh stack (core/archipelago/src/mesh/) - Design a dead-simple onboarding + usage flow (ties into the Telegram-quality mesh UX plan)
Author
Owner

Phase 0 review done. License + meshcore questions resolved by maintainer; remaining gate is the architecture decision.

Reviewed the repo: Meshroller is a single ~29KB Python daemon (meshroller.py) that bridges a Meshtastic radio (via the meshtastic serial module) to an Ollama LLM (qwen2.5-coder), with trusted-node auth, scheduled/queued messaging, and command parsing on mesh channels. It's a daemon, not firmware or a library.

  • License: in-house (our developer) — no third-party blocker.
  • meshcore requirement: per maintainer it must also work with meshcore, but the meshtastic Python module can't drive meshcore hardware. So integrating the script as-is won't satisfy that.

Decision needed (architecture):

  • (a) Preferred for meshcore — lift Meshroller's behaviors (LLM bridge, trusted-node auth, scheduled messaging, command parser) into our Rust mesh stack as typed message kinds (MeshMessageType + listener/dispatch.rs), native to meshcore.
  • (b) Package the Python daemon as a container app and add a meshcore serial backend to it.

Captured in docs/REMAINING-ISSUES-PLAN.md (#50). Holding implementation until (a)/(b) is chosen.

**Phase 0 review done. License + meshcore questions resolved by maintainer; remaining gate is the architecture decision.** Reviewed the repo: Meshroller is a single ~29KB Python daemon (`meshroller.py`) that bridges a **Meshtastic** radio (via the `meshtastic` serial module) to an **Ollama** LLM (`qwen2.5-coder`), with trusted-node auth, scheduled/queued messaging, and command parsing on mesh channels. It's a daemon, not firmware or a library. - **License**: in-house (our developer) — no third-party blocker. - **meshcore requirement**: per maintainer it must also work with **meshcore**, but the `meshtastic` Python module can't drive meshcore hardware. So integrating the script as-is won't satisfy that. **Decision needed (architecture):** - (a) **Preferred for meshcore** — lift Meshroller's behaviors (LLM bridge, trusted-node auth, scheduled messaging, command parser) into our Rust mesh stack as typed message kinds (`MeshMessageType` + `listener/dispatch.rs`), native to meshcore. - (b) Package the Python daemon as a container app and add a meshcore serial backend to it. Captured in `docs/REMAINING-ISSUES-PLAN.md` (#50). Holding implementation until (a)/(b) is chosen.
Author
Owner

Architecture decision made (2026-06-17): seam (a) — Rust-native lift.

Rather than packaging the Python/Meshtastic daemon and writing a meshcore backend for it, we will lift Meshroller's behaviors — the LLM bridge, trusted-node auth, scheduled/queued messaging, and the on-channel command parser — into our existing Rust mesh stack (core/archipelago/src/mesh/) as typed message kinds. This is native to meshcore (our radio: Heltec V3), drops the Python + Meshtastic-serial dependency entirely, and reuses the MeshEvent push seam so the UI gets live updates (same path used for #48).

Next steps (design in progress):

  • Map each Meshroller behavior to a MeshMessageType + listener/dispatch.rs handler.
  • Trusted-node auth → reuse our existing trusted-node list.
  • LLM bridge → local model call (our stack, not Ollama-specific).
  • Phase 2: dead-simple Mesh-tab onboarding + the 1–2 killer actions (ties into the Telegram-quality mesh UX plan).

Verification still needs 2 radios (the .116 meshcore + a second). Issue stays open while the design + implementation land.

**Architecture decision made (2026-06-17): seam (a) — Rust-native lift.** Rather than packaging the Python/Meshtastic daemon and writing a meshcore backend for it, we will lift Meshroller's *behaviors* — the LLM bridge, trusted-node auth, scheduled/queued messaging, and the on-channel command parser — into our existing Rust mesh stack (`core/archipelago/src/mesh/`) as typed message kinds. This is native to **meshcore** (our radio: Heltec V3), drops the Python + Meshtastic-serial dependency entirely, and reuses the `MeshEvent` push seam so the UI gets live updates (same path used for #48). Next steps (design in progress): - Map each Meshroller behavior to a `MeshMessageType` + `listener/dispatch.rs` handler. - Trusted-node auth → reuse our existing trusted-node list. - LLM bridge → local model call (our stack, not Ollama-specific). - Phase 2: dead-simple Mesh-tab onboarding + the 1–2 killer actions (ties into the Telegram-quality mesh UX plan). Verification still needs **2 radios** (the .116 meshcore + a second). Issue stays open while the design + implementation land.
Author
Owner

Rust-native design writtendocs/meshroller-integration-design.md (verified against the real mesh seams).

Mapping (Meshroller behavior → our stack):

  • LLM bridge → two new MeshMessageType variants AssistQuery/AssistResponse (mesh/message_types.rs); inbound handler in listener/dispatch.rs mirrors the TxRelay arm (validate → gate → spawn), calls the local Ollama at :11434 over reqwest, replies via send_typed_wire.
  • Trusted-node auth → reuse federation TrustLevel::Trusted + ContactEntry.blocked; policy = trusted-only (default) / pick-contacts / anyone-on-channel.
  • On-channel command parser → in the plain Text path, a !ai/!ask trigger on channel 0/1 synthesises an AssistQuery, so any meshcore client can ask.
  • Scheduled/queued messaging → an AssistScheduler on MeshService with a persisted queue (scheduled.json), a timer task, offline-retry on PeerDiscovered, RPCs mesh.schedule-message/list/cancel.
  • UI → new MeshEvent variants flow through the existing event_tx broadcast; no extra wiring.

Airtime discipline (meshcore = ≤160 B frames, scarce bandwidth): cap replies (~480 chars / ≤3 chunks, !more for the tail), 1 in-flight query/sender, 60s Ollama timeout.

Phase 2 UX: one-screen onboarding (detect/install Ollama → pick model → who-can-ask → trigger word) + a Mesh-tab Assistant card and a composer with Ask the mesh AI / Send later.

Build order (each testable alone): enum+payloads → gated bridge → channel trigger → events → scheduler → UI. Min demoable slice = the first two. Verification needs 2 radios + Ollama on the answering node.

**Rust-native design written** → `docs/meshroller-integration-design.md` (verified against the real mesh seams). **Mapping (Meshroller behavior → our stack):** - *LLM bridge* → two new `MeshMessageType` variants `AssistQuery`/`AssistResponse` (`mesh/message_types.rs`); inbound handler in `listener/dispatch.rs` mirrors the `TxRelay` arm (validate → gate → spawn), calls the **local Ollama** at :11434 over `reqwest`, replies via `send_typed_wire`. - *Trusted-node auth* → reuse `federation` `TrustLevel::Trusted` + `ContactEntry.blocked`; policy = trusted-only (default) / pick-contacts / anyone-on-channel. - *On-channel command parser* → in the plain `Text` path, a `!ai`/`!ask` trigger on channel 0/1 synthesises an `AssistQuery`, so **any** meshcore client can ask. - *Scheduled/queued messaging* → an `AssistScheduler` on `MeshService` with a persisted queue (`scheduled.json`), a timer task, offline-retry on `PeerDiscovered`, RPCs `mesh.schedule-message`/`list`/`cancel`. - *UI* → new `MeshEvent` variants flow through the existing `event_tx` broadcast; no extra wiring. **Airtime discipline** (meshcore = ≤160 B frames, scarce bandwidth): cap replies (~480 chars / ≤3 chunks, `!more` for the tail), 1 in-flight query/sender, 60s Ollama timeout. **Phase 2 UX:** one-screen onboarding (detect/install Ollama → pick model → who-can-ask → trigger word) + a Mesh-tab Assistant card and a composer with *Ask the mesh AI* / *Send later*. **Build order (each testable alone):** enum+payloads → gated bridge → channel trigger → events → scheduler → UI. Min demoable slice = the first two. Verification needs **2 radios** + Ollama on the answering node.
Author
Owner

Progress (2026-06-17) — implementation underway on local branch meshroller-50, NOT yet merged/shipped.

Done & compiling (cargo check clean), 5 commits:

  • 1.1–1.4 typed AssistQuery/AssistResponse + Ollama bridge + trust/airtime gates (cap, chunk, 1 in-flight/asker).
  • 1.5 !ai/!ask channel trigger — any client (bare meshcore OR Meshtastic) can ask; plain-text answer broadcast back. Generalised reply target (typed-to-peer vs channel-text).
  • Meshtastic: confirmed already supported via the MeshRadioDevice abstraction; the assistant rides it. "Anyone can ask" works on both radios today.
  • Identity bridge: wired the previously-dead ARCHY:2 identity broadcast (send each advert tick + inbound parse, deduped by archipelago pubkey, self-echo guarded) so trusted-only authenticates radio askers on BOTH radios.
  • Phase 2 backend: mesh.assistant-status (+ local Ollama detect) / mesh.assistant-configure (live toggle, no restart).

Remaining before this can close:

  • Phase 2 UI (Mesh-tab Assistant panel; deep-link install when Ollama absent — per maintainer).
  • 1.7 scheduled/queued messaging (AssistScheduler + RPCs).
  • Merge to main + live 2-radio test (meshcore + Meshtastic) with Ollama.

Issue stays open.

**Progress (2026-06-17) — implementation underway on local branch `meshroller-50`, NOT yet merged/shipped.** Done & compiling (`cargo check` clean), 5 commits: - **1.1–1.4** typed `AssistQuery`/`AssistResponse` + Ollama bridge + trust/airtime gates (cap, chunk, 1 in-flight/asker). - **1.5** `!ai`/`!ask` channel trigger — any client (bare meshcore OR Meshtastic) can ask; plain-text answer broadcast back. Generalised reply target (typed-to-peer vs channel-text). - **Meshtastic:** confirmed already supported via the `MeshRadioDevice` abstraction; the assistant rides it. "Anyone can ask" works on both radios today. - **Identity bridge:** wired the previously-dead `ARCHY:2` identity broadcast (send each advert tick + inbound parse, deduped by archipelago pubkey, self-echo guarded) so trusted-only authenticates radio askers on BOTH radios. - **Phase 2 backend:** `mesh.assistant-status` (+ local Ollama detect) / `mesh.assistant-configure` (live toggle, no restart). Remaining before this can close: - Phase 2 **UI** (Mesh-tab Assistant panel; deep-link install when Ollama absent — per maintainer). - **1.7** scheduled/queued messaging (`AssistScheduler` + RPCs). - Merge to main + **live 2-radio test** (meshcore + Meshtastic) with Ollama. Issue stays **open**.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: lfg2025/archy#50
No description provided.