From d172aaf60182fcdad831ceee39dd244efb01ce1f Mon Sep 17 00:00:00 2001 From: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co> Date: Sun, 19 Jul 2026 11:03:36 -0400 Subject: [PATCH] Ingest pair-scoped runtime lifecycle frames Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Tyler Longwell Signed-off-by: Tyler Longwell --- desktop/src-tauri/src/lib.rs | 3 +- .../src/managed_agents/runtime_commands.rs | 43 +++++++++++++++++++ .../src/managed_agents/runtime_types.rs | 9 ++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index 70e450008..851a256ff 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -49,7 +49,7 @@ use huddle::{ use managed_agents::{ backfill_persona_snapshots, ensure_nest, list_managed_agent_runtimes, reconcile_managed_agent_runtimes, restart_managed_agent_runtime, start_managed_agent_runtime, - stop_managed_agent_runtime, try_regenerate_nest, + stop_managed_agent_runtime, put_managed_agent_runtime_lifecycle, try_regenerate_nest, }; #[cfg(not(feature = "mesh-llm"))] use mesh_llm_stubs::*; @@ -866,6 +866,7 @@ pub fn run() { stop_managed_agent_runtime, restart_managed_agent_runtime, reconcile_managed_agent_runtimes, + put_managed_agent_runtime_lifecycle, create_managed_agent, start_managed_agent, stop_managed_agent, diff --git a/desktop/src-tauri/src/managed_agents/runtime_commands.rs b/desktop/src-tauri/src/managed_agents/runtime_commands.rs index 78d805832..390ec7a93 100644 --- a/desktop/src-tauri/src/managed_agents/runtime_commands.rs +++ b/desktop/src-tauri/src/managed_agents/runtime_commands.rs @@ -47,6 +47,49 @@ fn emit_status(app: &AppHandle, status: &ManagedAgentRuntimeStatus) { let _ = app.emit(STATUS_EVENT, status); } +#[tauri::command] +pub fn put_managed_agent_runtime_lifecycle( + outer_pubkey: String, + payload: super::ManagedAgentRuntimeLifecycleObserverPayload, + app: AppHandle, +) -> Result { + if outer_pubkey.to_ascii_lowercase() != payload.pubkey.to_ascii_lowercase() { + return Err("observer signer does not match lifecycle payload pubkey".into()); + } + if matches!( + payload.lifecycle, + ManagedAgentRuntimeLifecycle::Starting | ManagedAgentRuntimeLifecycle::Stopped + ) { + return Err("observer cannot author starting or stopped lifecycle".into()); + } + if payload.lifecycle == ManagedAgentRuntimeLifecycle::Failed && payload.error.is_none() { + return Err("failed lifecycle requires an error".into()); + } + if payload.lifecycle != ManagedAgentRuntimeLifecycle::Failed && payload.error.is_some() { + return Err("lifecycle error is only valid for failed".into()); + } + + let state = app.state::(); + let key = ManagedAgentRuntimeKey::new(payload.pubkey, &payload.relay_url)?; + let records = load_managed_agents(&app)?; + let record = records + .iter() + .find(|record| record.pubkey.eq_ignore_ascii_case(&key.pubkey)) + .ok_or_else(|| format!("agent {} not found", key.pubkey))?; + let mut runtimes = state.managed_agent_processes.lock().map_err(|e| e.to_string())?; + let runtime = runtimes + .get_mut(&key) + .ok_or_else(|| "lifecycle frame does not match a tracked runtime pair".to_string())?; + if runtime.child.try_wait().map_err(|e| e.to_string())?.is_some() { + return Err("lifecycle frame arrived after process exit".into()); + } + runtime.lifecycle = payload.lifecycle; + runtime.error = payload.error; + let status = status_for(&app, record, &key, Some(runtime), None); + emit_status(&app, &status); + Ok(status) +} + #[tauri::command] pub fn list_managed_agent_runtimes(app: AppHandle) -> Result, String> { let state = app.state::(); diff --git a/desktop/src-tauri/src/managed_agents/runtime_types.rs b/desktop/src-tauri/src/managed_agents/runtime_types.rs index 155e02bcd..139256032 100644 --- a/desktop/src-tauri/src/managed_agents/runtime_types.rs +++ b/desktop/src-tauri/src/managed_agents/runtime_types.rs @@ -85,6 +85,15 @@ pub struct ManagedAgentRuntimeStatus { pub log_path: Option, } +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ManagedAgentRuntimeLifecycleObserverPayload { + pub pubkey: String, + pub relay_url: String, + pub lifecycle: ManagedAgentRuntimeLifecycle, + pub error: Option, +} + #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ManagedAgentRuntimeTarget {