From d8ca1a9c3e70d2b017236b2a619dcc61cf4f47db Mon Sep 17 00:00:00 2001 From: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com> Date: Tue, 19 May 2026 16:59:57 -0400 Subject: [PATCH] mesh-llm: B7 Tauri commands surface desktop/src-tauri/src/commands/mesh_llm.rs (new): - mesh_get_endpoint_id(app) -> { endpoint_id }: creates the persisted iroh keypair on first call; returns the canonical Display form of the public key so the UI can show 'this device' identity. - mesh_get_sharing_prefs(app) -> ComputeSharingPrefs: reads the persisted prefs file (defaults applied when absent). - mesh_set_sharing_prefs(app, prefs) -> (): atomic write-through. - mesh_relay_iroh_url(state, relay_ws_url) -> Option: probes the relay's NIP-11 doc for iroh_relay_url; returns None gracefully when the relay doesn't advertise mesh-LLM. All four registered in lib.rs's tauri::generate_handler! block. Frontend hooks land in C1 (avatar-menu MeshComputeSettingsCard). Cleanup: drop wildcard re-exports from mesh_llm/mod.rs so unused publisher/dialer helpers don't trip top-level dead-code lints before B5/B6 are wired in. cargo check passes; clippy + fmt clean (relay-side workspace). Signed-off-by: Tyler Longwell <109685178+tlongwell-block@users.noreply.github.com> Co-authored-by: Dawn (sprout agent) --- desktop/src-tauri/src/commands/mesh_llm.rs | 72 ++++++++++++++++++++++ desktop/src-tauri/src/commands/mod.rs | 2 + desktop/src-tauri/src/lib.rs | 4 ++ desktop/src-tauri/src/mesh_llm/mod.rs | 12 ++-- 4 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 desktop/src-tauri/src/commands/mesh_llm.rs diff --git a/desktop/src-tauri/src/commands/mesh_llm.rs b/desktop/src-tauri/src/commands/mesh_llm.rs new file mode 100644 index 000000000..cca4e6e24 --- /dev/null +++ b/desktop/src-tauri/src/commands/mesh_llm.rs @@ -0,0 +1,72 @@ +//! Tauri commands for the mesh-LLM frontend surface. +//! +//! All commands deal with *the local user's own* mesh-LLM state: +//! - the persisted iroh endpoint id, +//! - the persisted compute-sharing preferences (the avatar-menu sliders), +//! - explicit toggle/save calls invoked when the user changes the prefs. +//! +//! Discovering and connecting to *other* members' offers happens through the +//! existing relay WebSocket pipeline, not these commands. + +use serde::Serialize; +use tauri::{AppHandle, State}; + +use crate::app_state::AppState; +use crate::mesh_llm; + +/// Result type for mesh-LLM commands: errors are surfaced as user-facing +/// strings by the frontend. +type CmdResult = Result; + +/// Stable identifier of the local iroh endpoint, in iroh's canonical +/// Display form. Returned to the frontend so the user can see *which* +/// machine identity they're publishing under (useful when one user has +/// multiple devices each running Sprout). +#[derive(Debug, Clone, Serialize)] +pub struct MeshEndpointInfo { + /// Iroh endpoint id (= public key) as displayed by `iroh-base`. + pub endpoint_id: String, +} + +/// Returns the local mesh-LLM iroh endpoint id, creating + persisting the +/// keypair on first call. +#[tauri::command] +pub fn mesh_get_endpoint_id(app: AppHandle) -> CmdResult { + let key = mesh_llm::load_or_create_endpoint_key(&app).map_err(|e| e.to_string())?; + Ok(MeshEndpointInfo { + endpoint_id: key.public().to_string(), + }) +} + +/// Returns the persisted compute-sharing preferences for the avatar menu. +#[tauri::command] +pub fn mesh_get_sharing_prefs(app: AppHandle) -> CmdResult { + mesh_llm::offer::load_prefs(&app).map_err(|e| e.to_string()) +} + +/// Replaces the persisted compute-sharing preferences. The caller is +/// responsible for republishing or deleting the kind:31990 offer to reflect +/// the change — this command only touches local state. +#[tauri::command] +pub fn mesh_set_sharing_prefs( + app: AppHandle, + prefs: mesh_llm::ComputeSharingPrefs, +) -> CmdResult<()> { + mesh_llm::offer::save_prefs(&app, &prefs).map_err(|e| e.to_string()) +} + +/// Probe the connected relay's NIP-11 for an `iroh_relay_url`. +/// +/// Returns: +/// - `Ok(Some(url))` if the relay advertises one, +/// - `Ok(None)` if it doesn't, or if the relay is unreachable / malformed. +/// - `Err(_)` only for caller-side errors (e.g. bad WS URL shape). +#[tauri::command] +pub async fn mesh_relay_iroh_url( + _state: State<'_, AppState>, + relay_ws_url: String, +) -> CmdResult> { + mesh_llm::fetch_iroh_relay_url(&relay_ws_url) + .await + .map_err(|e| e.to_string()) +} diff --git a/desktop/src-tauri/src/commands/mod.rs b/desktop/src-tauri/src/commands/mod.rs index 2bc5062f5..1d5fc6be2 100644 --- a/desktop/src-tauri/src/commands/mod.rs +++ b/desktop/src-tauri/src/commands/mod.rs @@ -10,6 +10,7 @@ mod export_util; mod identity; mod media; mod media_download; +mod mesh_llm; mod messages; pub mod pairing; mod personas; @@ -32,6 +33,7 @@ pub use dms::*; pub use identity::*; pub use media::*; pub use media_download::*; +pub use mesh_llm::*; pub use messages::*; pub use pairing::*; pub use personas::*; diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index 81a699963..96e618fba 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -455,6 +455,10 @@ pub fn run() { get_relay_ws_url, get_relay_http_url, get_media_proxy_port, + mesh_get_endpoint_id, + mesh_get_sharing_prefs, + mesh_set_sharing_prefs, + mesh_relay_iroh_url, discover_acp_providers, discover_managed_agent_prereqs, sign_event, diff --git a/desktop/src-tauri/src/mesh_llm/mod.rs b/desktop/src-tauri/src/mesh_llm/mod.rs index 1790bb5cd..40ed11dc6 100644 --- a/desktop/src-tauri/src/mesh_llm/mod.rs +++ b/desktop/src-tauri/src/mesh_llm/mod.rs @@ -20,7 +20,11 @@ pub mod nip11; pub mod nip98; pub mod offer; -pub use endpoint::{load_or_create_endpoint_key, EndpointKeyError}; -pub use nip11::{fetch_iroh_relay_url, Nip11Error}; -pub use nip98::{build_nip98_bearer, Nip98BearerError}; -pub use offer::{ComputeSharingPrefs, OfferPrefsError}; +// Wildcard re-exports are deliberately avoided so that adding an +// unused-by-design helper to a submodule (e.g. a publisher that hasn't been +// wired yet) doesn't trip dead-code lints at the top level. Callers reach +// into the submodules directly until a public API surface stabilises. + +pub use endpoint::load_or_create_endpoint_key; +pub use nip11::fetch_iroh_relay_url; +pub use offer::ComputeSharingPrefs;