Regroup the menu: Mesh, Device management, Tools

Messaging becomes Mesh and takes in Nodes (between Channels and Map —
the "who's out there" view) and Send advert (last in section: its one
action, after its views), so everything mesh-wide lives under one
heading. Device becomes Device management and keeps the box-level
tools; Diagnostics becomes Tools.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jean-Pierre MartineauandClaude Fable 5 committed 2026-07-11 03:35:00 -04:00
1 parent 8ecfbc865d
commit 85fc82a606
13 files changed
+21 -20

No files matched your search

+2 -2
View File
@@ -28,8 +28,8 @@ class SendAdvertTool(Tool):
title = "Send advert"
icon = "📡"
help = "Announce this node to the mesh — zero-hop, flood, or share as QR"
category = "Device"
order = 10 # right after Device actions, before Device info
category = "Mesh"
order = 40 # the section's one action, after its views
popup = True # dialog-sized: float over the menu instead of replacing it
async def prompt_params(self, ctx: AppContext) -> Optional[dict[str, Any]]:
+6 -5
View File
@@ -149,10 +149,11 @@ class Tool(ABC):
_REGISTRY: dict[str, Tool] = {}
#: Explicit menu ordering for tool categories. Messaging (Chat + Channels) leads because it
#: holds the first-class, everyday features; the rest follow in a natural workflow order.
#: Categories not listed here sort last, alphabetically, so a new category still appears.
_CATEGORY_ORDER = ["Messaging", "Device", "Diagnostics"]
#: Explicit menu ordering for tool categories. Mesh leads because it holds the
#: first-class, everyday features (chat, channels, the nodes and map views, adverts);
#: the rest follow in a natural workflow order. Categories not listed here sort last,
#: alphabetically, so a new category still appears.
_CATEGORY_ORDER = ["Mesh", "Device management", "Tools"]
def _category_rank(category: str) -> int:
@@ -187,7 +188,7 @@ def register(cls: type[Tool]) -> type[Tool]:
def all_tools() -> list[Tool]:
"""Return all registered tools sorted by category rank, then order, then name.
Categories are ordered by :data:`_CATEGORY_ORDER` (Messaging first), so the first-class
Categories are ordered by :data:`_CATEGORY_ORDER` (Mesh first), so the first-class
Chat and Channels tools lead the menu; within a category, ``order`` then ``name`` break
ties.
+1 -1
View File
@@ -38,7 +38,7 @@ class ChannelsTool(Tool):
title = "Channels"
icon = "📻"
help = "Create, join, and share mesh channels (with QR codes)"
category = "Messaging"
category = "Mesh"
order = 20
async def run(self, ctx: AppContext, params: dict[str, Any]) -> ToolResult:
+1 -1
View File
@@ -46,7 +46,7 @@ class ChatTool(Tool):
title = "Chat"
icon = "💬"
help = "Channel and direct messaging — live chat, with stored history"
category = "Messaging"
category = "Mesh"
order = 10
async def prompt_params(self, ctx: AppContext) -> Optional[dict[str, Any]]:
+1 -1
View File
@@ -38,7 +38,7 @@ class ConfigTool(Tool):
title = "Device configuration"
icon = "🔧"
help = "View and change device settings — identity, radio, tuning, …"
category = "Device"
category = "Device management"
order = 8
async def prompt_params(self, ctx: AppContext) -> Optional[dict[str, Any]]:
+1 -1
View File
@@ -32,7 +32,7 @@ class DeviceActionsTool(Tool):
title = "Device actions"
icon = "🔨"
help = "Act on the device itself — advert, backup, identity key, reboot, reset"
category = "Device"
category = "Device management"
order = 9
async def prompt_params(self, ctx: AppContext) -> Optional[dict[str, Any]]:
+1 -1
View File
@@ -41,7 +41,7 @@ class DevicesTool(Tool):
name = "devices"
title = "Devices"
help = "List attached serial and Bluetooth devices, flagging likely companions"
category = "Device"
category = "Device management"
order = 5
menu_visible = False # CLI-only: a startup diagnostic with no place in a connected session
+1 -1
View File
@@ -28,7 +28,7 @@ class InfoTool(Tool):
title = "Device info"
icon = "📋"
help = "Show device status, identity, and radio config"
category = "Device"
category = "Device management"
order = 11 # after Send advert (10), which slots in behind Device actions
async def run(self, ctx: AppContext, params: dict[str, Any]) -> ToolResult:
+1 -1
View File
@@ -37,7 +37,7 @@ class MapTool(Tool):
title = "Map"
icon = "🌍"
help = "Show mesh nodes on a street map (pannable; repeaters highlighted)"
category = "Messaging"
category = "Mesh"
order = 30
async def run(self, ctx: AppContext, params: dict[str, Any]) -> ToolResult:
+1 -1
View File
@@ -38,7 +38,7 @@ class MonitorTool(Tool):
title = "Monitor"
icon = "🎧"
help = "Capture overheard packets live for a while and summarize them"
category = "Diagnostics"
category = "Tools"
order = 20
menu_visible = False # recording is always on; in the menu the header/Nodes/Map show it
+2 -2
View File
@@ -18,8 +18,8 @@ class NodesTool(Tool):
title = "Nodes"
icon = "👥"
help = "List this node and known contacts (last heard, packets, type, key)"
category = "Device"
order = 12
category = "Mesh"
order = 25 # between Channels and Map: the "who's out there" view
async def run(self, ctx: AppContext, params: dict[str, Any]) -> ToolResult:
"""Query the device and render the node/contact list.
+2 -2
View File
@@ -50,7 +50,7 @@ class TraceTool(Tool):
title = "Trace target"
icon = "🎯"
help = "Trace a target over a mirrored route and watch per-hop SNR"
category = "Diagnostics"
category = "Tools"
order = 10
async def prompt_params(self, ctx: AppContext) -> Optional[dict[str, Any]]:
@@ -225,7 +225,7 @@ class TracePathTool(Tool):
title = "Trace path"
icon = "👣"
help = "Walk a hand-composed route — out and back your way"
category = "Diagnostics"
category = "Tools"
order = 11
async def prompt_params(self, ctx: AppContext) -> Optional[dict[str, Any]]:
+1 -1
View File
@@ -39,7 +39,7 @@ class TxOptimizeTool(Tool):
title = "TX optimize"
icon = "📶"
help = "Tune a remote node's TX power for the best signal at a target"
category = "Diagnostics"
category = "Tools"
order = 15 # right after Trace, its measurement sibling
async def prompt_params(self, ctx: AppContext) -> Optional[dict[str, Any]]: