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)
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.
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.
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.
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.
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.
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).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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:
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 themeshtasticserial 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.meshtasticPython module can't drive meshcore hardware. So integrating the script as-is won't satisfy that.Decision needed (architecture):
MeshMessageType+listener/dispatch.rs), native to meshcore.Captured in
docs/REMAINING-ISSUES-PLAN.md(#50). Holding implementation until (a)/(b) is chosen.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 theMeshEventpush seam so the UI gets live updates (same path used for #48).Next steps (design in progress):
MeshMessageType+listener/dispatch.rshandler.Verification still needs 2 radios (the .116 meshcore + a second). Issue stays open while the design + implementation land.
Rust-native design written →
docs/meshroller-integration-design.md(verified against the real mesh seams).Mapping (Meshroller behavior → our stack):
MeshMessageTypevariantsAssistQuery/AssistResponse(mesh/message_types.rs); inbound handler inlistener/dispatch.rsmirrors theTxRelayarm (validate → gate → spawn), calls the local Ollama at :11434 overreqwest, replies viasend_typed_wire.federationTrustLevel::Trusted+ContactEntry.blocked; policy = trusted-only (default) / pick-contacts / anyone-on-channel.Textpath, a!ai/!asktrigger on channel 0/1 synthesises anAssistQuery, so any meshcore client can ask.AssistScheduleronMeshServicewith a persisted queue (scheduled.json), a timer task, offline-retry onPeerDiscovered, RPCsmesh.schedule-message/list/cancel.MeshEventvariants flow through the existingevent_txbroadcast; no extra wiring.Airtime discipline (meshcore = ≤160 B frames, scarce bandwidth): cap replies (~480 chars / ≤3 chunks,
!morefor 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.
Progress (2026-06-17) — implementation underway on local branch
meshroller-50, NOT yet merged/shipped.Done & compiling (
cargo checkclean), 5 commits:AssistQuery/AssistResponse+ Ollama bridge + trust/airtime gates (cap, chunk, 1 in-flight/asker).!ai/!askchannel trigger — any client (bare meshcore OR Meshtastic) can ask; plain-text answer broadcast back. Generalised reply target (typed-to-peer vs channel-text).MeshRadioDeviceabstraction; the assistant rides it. "Anyone can ask" works on both radios today.ARCHY:2identity broadcast (send each advert tick + inbound parse, deduped by archipelago pubkey, self-echo guarded) so trusted-only authenticates radio askers on BOTH radios.mesh.assistant-status(+ local Ollama detect) /mesh.assistant-configure(live toggle, no restart).Remaining before this can close:
AssistScheduler+ RPCs).Issue stays open.