Commit Graph
6 Commits
Author SHA1 Message Date
Jean-Pierre MartineauandClaude Opus 4.8 4c725bd22a Key channel history by identity and mark channel openness in chat
Store channel messages under a slot-independent channel identity (sha256 of
the effective secret) instead of the raw slot index, so reordering or re-keying
slots no longer scrambles history. DB schema v3->v4 adds a channel_id column
with an idempotent migration and a lazy backfill that maps legacy rows to the
channel currently in each slot.

Recognize the firmware's fixed-key default "Public" channel as public: add
DEFAULT_PUBLIC_SECRET / KNOWN_PUBLIC_SECRETS and split is_name_derived (key
reproducible from the name, so it can be re-derived on write) from
is_public_channel (shared meshwide). The default channel no longer mislabels
itself as private, and its well-known key is preserved on edit/reorder.

Lead each chat picker row with a glyph: the channel's openness marker
(# name-derived, globe fixed-key public, lock private) or, for a direct chat,
a speech balloon once we've exchanged messages and a person before. A shared
channel_glyph() keeps the channel manager and the picker in sync.

Round out the messaging UX: live callable row titles and plain-text filtering
in the TUI select screen, plus assorted device-picker, monitor, route-map, and
config-editor menu refinements.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 20:31:44 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 6856b682b1 Add channel/direct chat feature and polish the passive-monitor UX
Introduce channel and direct messaging: an always-on ChatService that
records inbound messages to history, a live full-screen chat screen, and
a chat tool (interactive picker plus send/history/list/listen CLI). This
bumps the DB schema to v3 and adds the supporting models, repository
queries, and connection wiring.

Also polish the monitor/menu UX:
- Stop console log handlers from corrupting the full-screen TUI by
  detaching the RichHandler for the life of the session (file logging
  continues); most visible when toggling the monitor.
- Colour only the header's monitor glyph (green ● on, red ○ off).
- Crop the header to a single line instead of wrapping on narrow terminals.
- Drop the redundant toggle-confirmation window so toggling returns
  straight to the main menu.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 17:41:12 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 20c32f9642 Introduce an always-on event hub and broaden the device event surface
Decouple listening from consuming as the first step toward a full MeshCore
client. A new always-on EventHub owns the single device subscription and fans
typed MeshEvents out to any number of subscribers; passive-monitor history
logging becomes just one subscriber, so listening is now unconditional while the
on/off toggle controls only persistence.

- core/events.py: MeshEvent envelope + EventKind (OBSERVATION/MESSAGE/ACK)
- services/event_hub.py: subscribe/stream/wait_for fan-out, always-on pump
- connection.py: Device.subscribe_observations -> unified subscribe_events
  emitting observations, inbound messages, and acks; add message_from_event /
  ack_from_event mappers and a simulated message stream on MockDevice
- core/models.py: Message and Ack domain models
- monitor_service.py: slim to a hub subscriber (recording, not listening)
- context.py/menu.py: wire ctx.events into the session lifecycle
- config.py: connect_on_start setting (default on) to allow lazy connect
- Remove monitor --seconds / foreground capture and Device.listen; monitoring
  is passive/background only

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 21:20:24 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 2a9facc56e Replace questionary with a full-screen prompt_toolkit TUI
Introduce a UI surface abstraction (ctx.ui) that tools use for all input
and output instead of touching questionary or the console directly. Two
backends implement it: PlainUi for scripted CLI runs (prints immediately,
byte-for-byte unchanged) and TuiUi for the interactive menu (bounded,
scrollable result windows over a full-screen TuiSession).

The new meshtools/ui/tui package reimplements the slice of questionary the
app used — validated text input, confirm, autocomplete, and selectable
lists — plus framing, progress, and screen management. Swap the dependency
from questionary to prompt_toolkit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 14:09:18 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 1036ff52f6 Make passive monitor a non-blocking background toggle with live counts
The monitor was a blocking listen window that monopolized the app. Convert
it to an always-on background subscription that logs overheard adverts/
telemetry while the user keeps using the menu.

- Device: add subscribe_observations() as the non-blocking capture primitive;
  listen() is now a thin foreground wrapper over it. Mock streams a live
  packet burst + cadence instead of a bounded synth loop.
- MonitorService (ctx.monitor): owns the subscription, session/total counters,
  and the on/off preference; logs each packet as it arrives.
- MonitorStore: persist on/off in <config_dir>/monitor.json, default off,
  remembered between sessions and auto-resumed at launch.
- Menu: the monitor entry is now a toggle/heard-nodes control panel; the
  header shows live session/total counts and repaints ~1s via refresh_interval.
- CLI monitor gains --on/--off (preference) and keeps --seconds for a scripted
  foreground capture.
- Add Repository.observation_count(); README + tests (129 pass).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 13:35:43 -04:00
Jean-Pierre MartineauandClaude Opus 4.8 eba264385b Add passive mesh monitor (longitudinal advert/telemetry logger)
Adds a Device.listen capability (real + mock), an Observation/HeardNode
domain model, an observations table with Repository.record_observation /
heard_nodes aggregation, and a `monitor` tool that listens for a window and
logs every overheard advert/telemetry (SNR, RSSI, shared location) to the
database. This is the longitudinal substrate later features read back.

The real-hardware event-payload mapping is best-effort and, like the trace
mapping, flagged for validation against the firmware's event schema; the mock
device synthesizes plausible adverts so the tool and tests run without a radio.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:48:17 -04:00