refactor(desktop): feature-gate mesh-llm-sdk behind optional Cargo feature (#823)

This commit is contained in:
Will Pfleger
2026-06-02 20:25:01 +00:00
committed by GitHub
parent b72eee365f
commit fb514c8918
10 changed files with 118 additions and 36 deletions
+3 -3
View File
@@ -51,10 +51,10 @@ const overrides = new Map([
["src/shared/api/relayClientSession.ts", 1040], // durable websocket session manager with reconnect/replay/recovery state + sendTypingIndicator + fetchChannelHistoryBefore + subscribeToChannelLive (huddle TTS) + subscribeToHuddleEvents (huddle indicator) + disconnect() for workspace switch teardown + fetchEvents/subscribeLive/publishEvent for NIP-RS read state + publishUserStatus/subscribeToUserStatusUpdates (NIP-38) + ConnectionState plumbing & stall-watchdog wiring for half-open WS detection (Warp orange-icon case) + terminal session latch (auth rejection no longer racing back to reconnecting) — emitter + watchdog + reconnect policy logic extracted to relayConnectionStateEmitter.ts / relayStallWatchdog.ts / relayReconnectPolicy.ts ["src/shared/api/relayClientSession.ts", 1040], // durable websocket session manager with reconnect/replay/recovery state + sendTypingIndicator + fetchChannelHistoryBefore + subscribeToChannelLive (huddle TTS) + subscribeToHuddleEvents (huddle indicator) + disconnect() for workspace switch teardown + fetchEvents/subscribeLive/publishEvent for NIP-RS read state + publishUserStatus/subscribeToUserStatusUpdates (NIP-38) + ConnectionState plumbing & stall-watchdog wiring for half-open WS detection (Warp orange-icon case) + terminal session latch (auth rejection no longer racing back to reconnecting) — emitter + watchdog + reconnect policy logic extracted to relayConnectionStateEmitter.ts / relayStallWatchdog.ts / relayReconnectPolicy.ts
["src-tauri/src/migration.rs", 1010], // worktree shared-agent-data symlink sync (SHARED_AGENT_FILES + SHARED_AGENT_DIRS symlink-to-canonical + sibling pack migration) + mcp_command provider reconciliation + persona_pack_path reconciliation + tests ["src-tauri/src/migration.rs", 1010], // worktree shared-agent-data symlink sync (SHARED_AGENT_FILES + SHARED_AGENT_DIRS symlink-to-canonical + sibling pack migration) + mcp_command provider reconciliation + persona_pack_path reconciliation + tests
["src-tauri/src/commands/media.rs", 730], // ffmpeg video transcode + poster frame extraction + run_ffmpeg_with_timeout (find_ffmpeg via resolve_command, is_video_file, transcode_to_mp4, extract_poster_frame, transcode_and_extract_poster) + spawn_blocking wrappers + tests ["src-tauri/src/commands/media.rs", 730], // ffmpeg video transcode + poster frame extraction + run_ffmpeg_with_timeout (find_ffmpeg via resolve_command, is_video_file, transcode_to_mp4, extract_poster_frame, transcode_and_extract_poster) + spawn_blocking wrappers + tests
["src-tauri/src/commands/agents.rs", 900], // remote agent lifecycle routing (local + provider branches) + scope enforcement + persona pack metadata wiring + mcp_toolsets field + NIP-OA auth_tag in deploy payload + relay-mesh client preflight (start_local_agent_with_preflight + StartTarget split: async ensure outside store lock, then sync spawn under lock) ["src-tauri/src/commands/agents.rs", 910], // remote agent lifecycle routing (local + provider branches) + scope enforcement + persona pack metadata wiring + mcp_toolsets field + NIP-OA auth_tag in deploy payload + relay-mesh client preflight (start_local_agent_with_preflight + StartTarget split: async ensure outside store lock, then sync spawn under lock)
["src-tauri/src/commands/messages.rs", 515], // feed multi-query + NIP-50 search + forum thread resolution + thread ref + reactions via REQ + edit_message media_tags param (Slack-style attachment-editable edits) ["src-tauri/src/commands/messages.rs", 515], // feed multi-query + NIP-50 search + forum thread resolution + thread ref + reactions via REQ + edit_message media_tags param (Slack-style attachment-editable edits)
["src-tauri/src/nostr_convert.rs", 1150], // 12 Nostr event→model converters (channels, profiles, members, notes, search, agents, relay members) + rank_user_search_results helper for NIP-50 user search + 33 unit tests ["src-tauri/src/nostr_convert.rs", 1150], // 12 Nostr event→model converters (channels, profiles, members, notes, search, agents, relay members) + rank_user_search_results helper for NIP-50 user search + 33 unit tests
["src-tauri/src/managed_agents/runtime.rs", 1385], // ... + respond-to gate env (SPROUT_ACP_RESPOND_TO[_ALLOWLIST]) + per-mode env builder + tests + persona/agent env_vars spawn merge (helper + tests now in env_vars.rs) + system-wide orphan sweep (proc_listallpids/proc on macOS, /proc on Linux) + SPROUT_MANAGED_AGENT env marker check (KERN_PROCARGS2 on macOS, /proc/environ on Linux), instance-scoped by app identifier so coexisting Sprout instances don't reap each other's agents + relay_mesh_model_id detector (mesh preset-env match) + tests ["src-tauri/src/managed_agents/runtime.rs", 1390], // ... + respond-to gate env (SPROUT_ACP_RESPOND_TO[_ALLOWLIST]) + per-mode env builder + tests + persona/agent env_vars spawn merge (helper + tests now in env_vars.rs) + system-wide orphan sweep (proc_listallpids/proc on macOS, /proc on Linux) + SPROUT_MANAGED_AGENT env marker check (KERN_PROCARGS2 on macOS, /proc/environ on Linux), instance-scoped by app identifier so coexisting Sprout instances don't reap each other's agents + relay_mesh_model_id detector (mesh preset-env match) + tests
["src-tauri/src/managed_agents/discovery.rs", 680], // KNOWN_ACP_PROVIDERS catalog + resolve_command cache + login_shell_path + classify_provider (four-state: Available/AdapterMissing/CliMissing/NotInstalled) + discover_acp_providers with dynamic install_hint + known_acp_provider/known_acp_provider_exact + normalize_agent_args + 15 unit tests ["src-tauri/src/managed_agents/discovery.rs", 680], // KNOWN_ACP_PROVIDERS catalog + resolve_command cache + login_shell_path + classify_provider (four-state: Available/AdapterMissing/CliMissing/NotInstalled) + discover_acp_providers with dynamic install_hint + known_acp_provider/known_acp_provider_exact + normalize_agent_args + 15 unit tests
["src-tauri/src/managed_agents/types.rs", 745], // ManagedAgentRecord/Summary + Create/Update request structs + AcpProviderCatalogEntry + InstallRuntimeResult + RespondTo enum + validate_respond_to_allowlist + tests + persona/agent env_vars field ["src-tauri/src/managed_agents/types.rs", 745], // ManagedAgentRecord/Summary + Create/Update request structs + AcpProviderCatalogEntry + InstallRuntimeResult + RespondTo enum + validate_respond_to_allowlist + tests + persona/agent env_vars field
["src-tauri/src/managed_agents/backend.rs", 700], // provider IPC, validation, discovery, binary resolution + tests + redact_secrets_with for user env values + env_secrets_from_request + redact_env_values_in (shared with model discovery) ["src-tauri/src/managed_agents/backend.rs", 700], // provider IPC, validation, discovery, binary resolution + tests + redact_secrets_with for user env values + env_secrets_from_request + redact_env_values_in (shared with model discovery)
@@ -81,7 +81,7 @@ const overrides = new Map([
["src-tauri/src/huddle/tts.rs", 1380], // TTS pipeline + session warmup + cancel/shutdown handling + apply_fade_out (fade-out only — leading fade removed 2026-05-18 after onset-attenuation regression measured in examples/pocket_onset_probe.rs) + FIRST_APPEND_LEAD_IN_SAMPLES + build_sentence_append_plan (pure helper enforcing the lead-in fires exactly once per utterance, not per sentence — see lead_in_pad_fires_exactly_once_per_utterance regression test) + normalize_for_playback (per-sentence peak normalization to -3 dBFS ceiling with MAX_GAIN cap) + 30 unit tests (18 interrupt + 5 fade-out + 1 first-append-lead-in + 3 build-sentence-append-plan + 6 normalize) ["src-tauri/src/huddle/tts.rs", 1380], // TTS pipeline + session warmup + cancel/shutdown handling + apply_fade_out (fade-out only — leading fade removed 2026-05-18 after onset-attenuation regression measured in examples/pocket_onset_probe.rs) + FIRST_APPEND_LEAD_IN_SAMPLES + build_sentence_append_plan (pure helper enforcing the lead-in fires exactly once per utterance, not per sentence — see lead_in_pad_fires_exactly_once_per_utterance regression test) + normalize_for_playback (per-sentence peak normalization to -3 dBFS ceiling with MAX_GAIN cap) + 30 unit tests (18 interrupt + 5 fade-out + 1 first-append-lead-in + 3 build-sentence-append-plan + 6 normalize)
["src-tauri/src/relay.rs", 510], // +4 lines for NIP-OA auth tag injection in profile sync (build_profile_event) + verification test ["src-tauri/src/relay.rs", 510], // +4 lines for NIP-OA auth tag injection in profile sync (build_profile_event) + verification test
["src-tauri/src/commands/pairing.rs", 600], // NIP-AB pairing actor: 3 Tauri commands + background WS task + NIP-42 auth + NIP-43 probe + event parsing helpers ["src-tauri/src/commands/pairing.rs", 600], // NIP-AB pairing actor: 3 Tauri commands + background WS task + NIP-42 auth + NIP-43 probe + event parsing helpers
["src-tauri/src/lib.rs", 780], // + mesh command registrations + PairingHandle managed state + 3 pairing command registrations + parse_message_deep_link helper extracted with 6 unit tests covering empty-param filter regression + mod migration + sync_shared_agent_data/reconcile_provider_mcp_commands/reconcile_persona_pack_paths calls on launch + SIGINT/SIGTERM/SIGHUP signal handlers for agent process cleanup ["src-tauri/src/lib.rs", 835], // + mesh_llm_stubs module (feature-gated no-op Tauri commands) + mesh command registrations + PairingHandle managed state + 3 pairing command registrations + parse_message_deep_link helper extracted with 6 unit tests covering empty-param filter regression + mod migration + sync_shared_agent_data/reconcile_provider_mcp_commands/reconcile_persona_pack_paths calls on launch + SIGINT/SIGTERM/SIGHUP signal handlers for agent process cleanup
["src/shared/api/tauri.ts", 1212], // pairing command wrappers + applyWorkspace + NIP-44 encrypt/decrypt wrappers + observer_url field + relay member API functions (list/get/add/remove/change-role) + prevent sleep + AcpProviderCatalogEntry raw types + fromRawAcpProviderCatalogEntry converter + installAcpRuntime ["src/shared/api/tauri.ts", 1212], // pairing command wrappers + applyWorkspace + NIP-44 encrypt/decrypt wrappers + observer_url field + relay member API functions (list/get/add/remove/change-role) + prevent sleep + AcpProviderCatalogEntry raw types + fromRawAcpProviderCatalogEntry converter + installAcpRuntime
]); ]);
-6
View File
@@ -1,6 +0,0 @@
[env]
# Workaround for mesh-llm prepare-llama.sh `git -C` directory-escape bug.
# The script's git commands walk upward into the enclosing Sprout repo when
# .deps/llama.cpp/.git is missing. Disabling auto-build prevents the script
# from running. Remove once mesh-llm-sdk is bumped past Mesh-LLM/mesh-llm#780.
SKIPPY_LLAMA_AUTO_BUILD = "0"
+5 -1
View File
@@ -16,6 +16,10 @@ edition = "2021"
name = "sprout_lib" name = "sprout_lib"
crate-type = ["staticlib", "cdylib", "rlib"] crate-type = ["staticlib", "cdylib", "rlib"]
[features]
default = []
mesh-llm = ["dep:mesh-llm-sdk"]
[build-dependencies] [build-dependencies]
tauri-build = { version = "2", features = [] } tauri-build = { version = "2", features = [] }
@@ -57,7 +61,7 @@ url = "2"
sprout-core = { path = "../../crates/sprout-core" } sprout-core = { path = "../../crates/sprout-core" }
sprout-persona = { path = "../../crates/sprout-persona" } sprout-persona = { path = "../../crates/sprout-persona" }
sprout-sdk = { path = "../../crates/sprout-sdk" } sprout-sdk = { path = "../../crates/sprout-sdk" }
mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "bd16da4955a9dceee8f1e0a02c5814944f4e12a5", package = "mesh-llm-sdk", default-features = false, features = ["client", "serve"] } mesh-llm-sdk = { git = "https://github.com/Mesh-LLM/mesh-llm.git", rev = "bd16da4955a9dceee8f1e0a02c5814944f4e12a5", package = "mesh-llm-sdk", default-features = false, features = ["client", "serve"], optional = true }
base64 = "0.22" base64 = "0.22"
sha2 = "0.11" sha2 = "0.11"
tar = "0.4" tar = "0.4"
+3
View File
@@ -6,6 +6,7 @@ use std::{
use nostr::{Keys, ToBech32}; use nostr::{Keys, ToBech32};
use tauri::{AppHandle, Manager}; use tauri::{AppHandle, Manager};
#[cfg(feature = "mesh-llm")]
use tokio::sync::Mutex as AsyncMutex; use tokio::sync::Mutex as AsyncMutex;
use crate::huddle::HuddleState; use crate::huddle::HuddleState;
@@ -35,6 +36,7 @@ pub struct AppState {
/// IOKit power assertion state — prevents idle sleep while agents run. /// IOKit power assertion state — prevents idle sleep while agents run.
pub prevent_sleep: Arc<Mutex<crate::prevent_sleep::PreventSleepState>>, pub prevent_sleep: Arc<Mutex<crate::prevent_sleep::PreventSleepState>>,
/// In-process mesh-llm node started by Sprout Desktop. /// In-process mesh-llm node started by Sprout Desktop.
#[cfg(feature = "mesh-llm")]
pub mesh_llm_runtime: AsyncMutex<Option<crate::mesh_llm::DesktopMeshRuntime>>, pub mesh_llm_runtime: AsyncMutex<Option<crate::mesh_llm::DesktopMeshRuntime>>,
} }
@@ -81,6 +83,7 @@ pub fn build_app_state() -> AppState {
prevent_sleep: Arc::new(Mutex::new( prevent_sleep: Arc::new(Mutex::new(
crate::prevent_sleep::PreventSleepState::default(), crate::prevent_sleep::PreventSleepState::default(),
)), )),
#[cfg(feature = "mesh-llm")]
mesh_llm_runtime: AsyncMutex::new(None), mesh_llm_runtime: AsyncMutex::new(None),
} }
} }
+18 -7
View File
@@ -1,19 +1,21 @@
use nostr::{Keys, ToBech32}; use nostr::{Keys, ToBech32};
use tauri::{AppHandle, State}; use tauri::{AppHandle, State};
#[cfg(feature = "mesh-llm")]
use crate::managed_agents::relay_mesh_model_id;
use crate::{ use crate::{
app_state::AppState, app_state::AppState,
managed_agents::{ managed_agents::{
build_managed_agent_summary, discover_provider_candidates, ensure_persona_is_active, build_managed_agent_summary, discover_provider_candidates, ensure_persona_is_active,
find_managed_agent_mut, invoke_provider, load_managed_agents, load_personas, find_managed_agent_mut, invoke_provider, load_managed_agents, load_personas,
managed_agent_avatar_url, managed_agent_log_path, managed_agents_base_dir, managed_agent_avatar_url, managed_agent_log_path, managed_agents_base_dir,
normalize_agent_args, provider_deploy, read_log_tail, relay_mesh_model_id, normalize_agent_args, provider_deploy, read_log_tail, resolve_provider_binary,
resolve_provider_binary, save_managed_agents, start_managed_agent_process, save_managed_agents, start_managed_agent_process, stop_managed_agent_process,
stop_managed_agent_process, sync_managed_agent_processes, try_regenerate_nest, sync_managed_agent_processes, try_regenerate_nest, validate_provider_config, BackendKind,
validate_provider_config, BackendKind, BackendProviderInfo, CreateManagedAgentRequest, BackendProviderInfo, CreateManagedAgentRequest, CreateManagedAgentResponse,
CreateManagedAgentResponse, ManagedAgentLogResponse, ManagedAgentRecord, ManagedAgentLogResponse, ManagedAgentRecord, ManagedAgentSummary, DEFAULT_ACP_COMMAND,
ManagedAgentSummary, DEFAULT_ACP_COMMAND, DEFAULT_AGENT_COMMAND, DEFAULT_AGENT_PARALLELISM, DEFAULT_AGENT_COMMAND, DEFAULT_AGENT_PARALLELISM, DEFAULT_AGENT_TURN_TIMEOUT_SECONDS,
DEFAULT_AGENT_TURN_TIMEOUT_SECONDS, DEFAULT_MCP_COMMAND, DEFAULT_MCP_COMMAND,
}, },
relay::{relay_ws_url_with_override, sync_managed_agent_profile}, relay::{relay_ws_url_with_override, sync_managed_agent_profile},
util::now_iso, util::now_iso,
@@ -27,6 +29,7 @@ fn workspace_owner_hex(state: &AppState) -> Result<String, String> {
Ok(keys.public_key().to_hex()) Ok(keys.public_key().to_hex())
} }
#[cfg(feature = "mesh-llm")]
async fn ensure_relay_mesh_for_record( async fn ensure_relay_mesh_for_record(
state: &AppState, state: &AppState,
record: &ManagedAgentRecord, record: &ManagedAgentRecord,
@@ -38,6 +41,14 @@ async fn ensure_relay_mesh_for_record(
Ok(()) Ok(())
} }
#[cfg(not(feature = "mesh-llm"))]
async fn ensure_relay_mesh_for_record(
_state: &AppState,
_record: &ManagedAgentRecord,
) -> Result<(), String> {
Ok(())
}
async fn start_local_agent_with_preflight( async fn start_local_agent_with_preflight(
app: &AppHandle, app: &AppHandle,
state: &AppState, state: &AppState,
+2
View File
@@ -12,6 +12,7 @@ mod identity_archive;
mod media; mod media;
mod media_download; mod media_download;
mod media_transcode; mod media_transcode;
#[cfg(feature = "mesh-llm")]
mod mesh_llm; mod mesh_llm;
mod messages; mod messages;
pub mod pairing; pub mod pairing;
@@ -36,6 +37,7 @@ pub use identity::*;
pub use identity_archive::*; pub use identity_archive::*;
pub use media::*; pub use media::*;
pub use media_download::*; pub use media_download::*;
#[cfg(feature = "mesh-llm")]
pub use mesh_llm::*; pub use mesh_llm::*;
pub use messages::*; pub use messages::*;
pub use pairing::*; pub use pairing::*;
+57
View File
@@ -4,6 +4,7 @@ mod events;
mod huddle; mod huddle;
mod managed_agents; mod managed_agents;
mod media_proxy; mod media_proxy;
#[cfg(feature = "mesh-llm")]
mod mesh_llm; mod mesh_llm;
mod migration; mod migration;
mod models; mod models;
@@ -13,6 +14,62 @@ mod relay;
mod templates; mod templates;
mod util; mod util;
#[cfg(not(feature = "mesh-llm"))]
mod mesh_llm_stubs {
use tauri::State;
use crate::app_state::AppState;
type CmdResult<T> = Result<T, String>;
#[tauri::command]
pub async fn mesh_availability(_state: State<'_, AppState>) -> CmdResult<serde_json::Value> {
Err("mesh-llm feature not enabled".to_string())
}
#[tauri::command]
pub async fn mesh_start_node(
_app: tauri::AppHandle,
_state: State<'_, AppState>,
_request: serde_json::Value,
) -> CmdResult<serde_json::Value> {
Err("mesh-llm feature not enabled".to_string())
}
#[tauri::command]
pub async fn mesh_ensure_client_node(
_state: State<'_, AppState>,
_request: serde_json::Value,
) -> CmdResult<serde_json::Value> {
Err("mesh-llm feature not enabled".to_string())
}
#[tauri::command]
pub async fn mesh_stop_node(_state: State<'_, AppState>) -> CmdResult<serde_json::Value> {
Err("mesh-llm feature not enabled".to_string())
}
#[tauri::command]
pub async fn mesh_node_status(_state: State<'_, AppState>) -> CmdResult<serde_json::Value> {
Err("mesh-llm feature not enabled".to_string())
}
#[tauri::command]
pub async fn mesh_installed_models(
_state: State<'_, AppState>,
) -> CmdResult<Vec<serde_json::Value>> {
Err("mesh-llm feature not enabled".to_string())
}
#[tauri::command]
pub fn mesh_agent_preset(_request: serde_json::Value) -> CmdResult<serde_json::Value> {
Err("mesh-llm feature not enabled".to_string())
}
}
#[cfg(not(feature = "mesh-llm"))]
use mesh_llm_stubs::*;
use app_state::{build_app_state, resolve_persisted_identity, AppState}; use app_state::{build_app_state, resolve_persisted_identity, AppState};
use commands::*; use commands::*;
use huddle::audio_output::{ use huddle::audio_output::{
+23 -16
View File
@@ -1,7 +1,8 @@
#[cfg(feature = "mesh-llm")]
use super::relay_mesh_model_id;
use super::{ use super::{
find_managed_agent_mut, kill_stale_tracked_processes, load_managed_agents, relay_mesh_model_id, find_managed_agent_mut, kill_stale_tracked_processes, load_managed_agents, save_managed_agents,
save_managed_agents, spawn_agent_child, sync_managed_agent_processes, BackendKind, spawn_agent_child, sync_managed_agent_processes, BackendKind, ManagedAgentProcess,
ManagedAgentProcess,
}; };
use crate::app_state::AppState; use crate::app_state::AppState;
use crate::util; use crate::util;
@@ -103,20 +104,25 @@ pub async fn restore_managed_agents_on_launch(
.ok() .ok()
.map(|k| k.public_key().to_hex()); .map(|k| k.public_key().to_hex());
let mut mesh_preflight_failures = std::collections::HashSet::new(); #[cfg(feature = "mesh-llm")]
for record in &agents_to_start { let agents_to_start = {
let Some(model_id) = relay_mesh_model_id(record) else { let mut mesh_preflight_failures = std::collections::HashSet::new();
continue; for record in &agents_to_start {
}; let Some(model_id) = relay_mesh_model_id(record) else {
if let Err(error) = crate::commands::ensure_client_node_for_model(&state, model_id).await { continue;
persist_restore_error(app, &state, &record.pubkey, error)?; };
mesh_preflight_failures.insert(record.pubkey.clone()); if let Err(error) =
crate::commands::mesh_llm::ensure_client_node_for_model(&state, model_id).await
{
persist_restore_error(app, &state, &record.pubkey, error)?;
mesh_preflight_failures.insert(record.pubkey.clone());
}
} }
} agents_to_start
let agents_to_start: Vec<_> = agents_to_start .into_iter()
.into_iter() .filter(|record| !mesh_preflight_failures.contains(&record.pubkey))
.filter(|record| !mesh_preflight_failures.contains(&record.pubkey)) .collect::<Vec<_>>()
.collect(); };
if agents_to_start.is_empty() { if agents_to_start.is_empty() {
return Ok(()); return Ok(());
} }
@@ -183,6 +189,7 @@ pub async fn restore_managed_agents_on_launch(
Ok(()) Ok(())
} }
#[cfg(feature = "mesh-llm")]
fn persist_restore_error( fn persist_restore_error(
app: &tauri::AppHandle, app: &tauri::AppHandle,
state: &AppState, state: &AppState,
@@ -1046,6 +1046,7 @@ fn child_rust_log_filter() -> String {
/// Returns the relay-mesh model id for agents whose provider env points at the /// Returns the relay-mesh model id for agents whose provider env points at the
/// local mesh client endpoint. The caller is responsible for ensuring that /// local mesh client endpoint. The caller is responsible for ensuring that
/// endpoint is alive before spawning the agent process. /// endpoint is alive before spawning the agent process.
#[cfg(feature = "mesh-llm")]
pub fn relay_mesh_model_id(record: &ManagedAgentRecord) -> Option<String> { pub fn relay_mesh_model_id(record: &ManagedAgentRecord) -> Option<String> {
let base_url = record.env_vars.get("OPENAI_COMPAT_BASE_URL")?.trim(); let base_url = record.env_vars.get("OPENAI_COMPAT_BASE_URL")?.trim();
if base_url.trim_end_matches('/') != "http://127.0.0.1:9337/v1" { if base_url.trim_end_matches('/') != "http://127.0.0.1:9337/v1" {
@@ -1169,6 +1170,7 @@ pub fn stop_managed_agent_process(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[cfg(feature = "mesh-llm")]
use super::relay_mesh_model_id; use super::relay_mesh_model_id;
use crate::managed_agents::known_acp_provider; use crate::managed_agents::known_acp_provider;
@@ -1261,6 +1263,7 @@ mod tests {
} }
} }
#[cfg(feature = "mesh-llm")]
#[test] #[test]
fn relay_mesh_model_id_detects_mesh_preset_env() { fn relay_mesh_model_id_detects_mesh_preset_env() {
let mut rec = fixture(RespondTo::OwnerOnly, vec![], Some("tag".into())); let mut rec = fixture(RespondTo::OwnerOnly, vec![], Some("tag".into()));
@@ -1276,6 +1279,7 @@ mod tests {
assert_eq!(relay_mesh_model_id(&rec).as_deref(), Some("Qwen3")); assert_eq!(relay_mesh_model_id(&rec).as_deref(), Some("Qwen3"));
} }
#[cfg(feature = "mesh-llm")]
#[test] #[test]
fn relay_mesh_model_id_ignores_non_mesh_openai_env() { fn relay_mesh_model_id_ignores_non_mesh_openai_env() {
let mut rec = fixture(RespondTo::OwnerOnly, vec![], Some("tag".into())); let mut rec = fixture(RespondTo::OwnerOnly, vec![], Some("tag".into()));
+3 -3
View File
@@ -181,7 +181,7 @@ desktop-release-build target="aarch64-apple-darwin":
touch "desktop/src-tauri/binaries/git-credential-nostr-$TARGET" touch "desktop/src-tauri/binaries/git-credential-nostr-$TARGET"
touch "desktop/src-tauri/binaries/sprout-$TARGET" touch "desktop/src-tauri/binaries/sprout-$TARGET"
pnpm install pnpm install
cd {{desktop_dir}} && pnpm tauri build --target {{target}} cd {{desktop_dir}} && TAURI_CLI_EXTRA_CARGO_ARGS="--features=mesh-llm" pnpm tauri build --target {{target}}
# Run desktop checks suitable for CI / pre-push # Run desktop checks suitable for CI / pre-push
desktop-ci: desktop-check desktop-test desktop-tauri-fmt-check desktop-build desktop-tauri-check desktop-tauri-test desktop-ci: desktop-check desktop-test desktop-tauri-fmt-check desktop-build desktop-tauri-check desktop-tauri-test
@@ -263,7 +263,7 @@ dev *ARGS: _ensure-sidecar-stubs
[[ -d node_modules ]] || pnpm install [[ -d node_modules ]] || pnpm install
source ../scripts/instance-env.sh source ../scripts/instance-env.sh
echo "Starting on Vite port ${SPROUT_VITE_PORT}, relay ${SPROUT_RELAY_URL}" echo "Starting on Vite port ${SPROUT_VITE_PORT}, relay ${SPROUT_RELAY_URL}"
pnpm exec tauri dev --config "$SPROUT_TAURI_CONFIG" {{ARGS}} TAURI_CLI_EXTRA_CARGO_ARGS="--features=mesh-llm" pnpm exec tauri dev --config "$SPROUT_TAURI_CONFIG" {{ARGS}}
# Run the desktop app against the internal staging relay (installs deps + builds agent tools automatically) # Run the desktop app against the internal staging relay (installs deps + builds agent tools automatically)
staging *ARGS: _ensure-sidecar-stubs staging *ARGS: _ensure-sidecar-stubs
@@ -279,7 +279,7 @@ staging *ARGS: _ensure-sidecar-stubs
source ../scripts/instance-env.sh source ../scripts/instance-env.sh
export SPROUT_RELAY_URL="wss://sprout-oss.stage.blox.sqprod.co" export SPROUT_RELAY_URL="wss://sprout-oss.stage.blox.sqprod.co"
echo "Starting staging on Vite port ${SPROUT_VITE_PORT}, relay ${SPROUT_RELAY_URL}" echo "Starting staging on Vite port ${SPROUT_VITE_PORT}, relay ${SPROUT_RELAY_URL}"
pnpm exec tauri dev --config "$SPROUT_TAURI_CONFIG" {{ARGS}} TAURI_CLI_EXTRA_CARGO_ARGS="--features=mesh-llm" pnpm exec tauri dev --config "$SPROUT_TAURI_CONFIG" {{ARGS}}
# Run the desktop frontend dev server (port derived from worktree) # Run the desktop frontend dev server (port derived from worktree)
desktop-dev: desktop-dev: