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;