fix(desktop): resolve effective model and prompt from persona in display path (#972)

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
Will Pfleger
2026-06-11 13:29:38 -04:00
committed by GitHub
parent 1bb8b8d547
commit 63738139ba
5 changed files with 51 additions and 17 deletions

View File

@@ -30,7 +30,7 @@ const rules = [
// Do not add to this list; split the file instead. Remove each entry as its
// file is broken up. Tracked as a follow-up.
const overrides = new Map([
["src-tauri/src/commands/agents.rs", 1287],
["src-tauri/src/commands/agents.rs", 1294],
["src-tauri/src/managed_agents/nest.rs", 1420],
["src-tauri/src/managed_agents/runtime.rs", 1940],
["src-tauri/src/managed_agents/personas.rs", 1080],

View File

@@ -7,8 +7,9 @@ use crate::{
app_state::AppState,
managed_agents::{
build_managed_agent_summary, default_agent_workdir, find_managed_agent_mut,
known_acp_runtime, load_managed_agents, managed_agent_avatar_url, missing_command_message,
normalize_agent_args, resolve_command, save_managed_agents, sync_managed_agent_processes,
known_acp_runtime, load_managed_agents, load_personas, managed_agent_avatar_url,
missing_command_message, normalize_agent_args, resolve_command,
resolve_effective_prompt_model_provider, save_managed_agents, sync_managed_agent_processes,
try_regenerate_nest, AgentModelInfo, AgentModelsResponse, UpdateManagedAgentRequest,
UpdateManagedAgentResponse,
},
@@ -62,7 +63,17 @@ pub async fn get_agent_models(
crate::managed_agents::resolve_persona_env(&app, record.persona_id.as_deref())?;
let env = crate::managed_agents::merged_user_env(&persona_env, &record.env_vars);
(resolved, resolved_agent, args, record.model.clone(), env)
// Resolve the effective model from the linked persona so the ModelPicker
// dropdown shows the current persona model as selected.
let personas = load_personas(&app).unwrap_or_default();
let (_prompt, effective_model, _provider) = resolve_effective_prompt_model_provider(
record.persona_id.as_deref(),
&personas,
record.system_prompt.clone(),
record.model.clone(),
);
(resolved, resolved_agent, args, effective_model, env)
}; // store lock released — subprocess runs without holding the lock
// Clone the env map for redaction below — `merged_env` is moved
@@ -249,7 +260,10 @@ pub async fn update_managed_agent(
None
};
let summary = build_managed_agent_summary(&app, record, &runtimes)?;
let summary = {
let personas = load_personas(&app).unwrap_or_default();
build_managed_agent_summary(&app, record, &runtimes, &personas)?
};
(summary, sync_params)
}; // lock dropped here

View File

@@ -3,7 +3,7 @@ use tauri::{AppHandle, State};
use crate::{
app_state::AppState,
managed_agents::{
build_managed_agent_summary, find_managed_agent_mut, load_managed_agents,
build_managed_agent_summary, find_managed_agent_mut, load_managed_agents, load_personas,
save_managed_agents, sync_managed_agent_processes, ManagedAgentSummary,
},
util::now_iso,
@@ -41,5 +41,6 @@ pub fn set_managed_agent_start_on_app_launch(
.iter()
.find(|record| record.pubkey == pubkey)
.ok_or_else(|| format!("agent {pubkey} not found"))?;
build_managed_agent_summary(&app, record, &runtimes)
let personas = load_personas(&app).unwrap_or_default();
build_managed_agent_summary(&app, record, &runtimes, &personas)
}

View File

@@ -111,7 +111,8 @@ async fn start_local_agent_with_preflight(
.iter()
.find(|record| record.pubkey == pubkey)
.ok_or_else(|| format!("agent {pubkey} not found"))?;
build_managed_agent_summary(app, record, &runtimes)
let personas = load_personas(app).unwrap_or_default();
build_managed_agent_summary(app, record, &runtimes, &personas)
}
/// Build the standard agent JSON payload for provider deploy calls.
@@ -283,9 +284,10 @@ pub fn list_managed_agents(
save_managed_agents(&app, &records)?;
}
let personas = load_personas(&app).unwrap_or_default();
records
.iter()
.map(|record| build_managed_agent_summary(&app, record, &runtimes))
.map(|record| build_managed_agent_summary(&app, record, &runtimes, &personas))
.collect()
}
@@ -565,8 +567,9 @@ pub async fn create_managed_agent(
.iter()
.find(|record| record.pubkey == pubkey)
.ok_or_else(|| "created agent disappeared unexpectedly".to_string())?;
let personas = load_personas(&app).unwrap_or_default();
(
build_managed_agent_summary(&app, record, &runtimes)?,
build_managed_agent_summary(&app, record, &runtimes, &personas)?,
resolved_avatar_url,
)
};
@@ -595,7 +598,8 @@ pub async fn create_managed_agent(
.iter()
.find(|record| record.pubkey == pubkey)
.ok_or_else(|| "created agent disappeared unexpectedly".to_string())?;
build_managed_agent_summary(&app, record, &runtimes)?
let personas = load_personas(&app).unwrap_or_default();
build_managed_agent_summary(&app, record, &runtimes, &personas)?
}
}
} else {
@@ -681,7 +685,8 @@ pub async fn create_managed_agent(
.iter()
.find(|r| r.pubkey == pubkey)
.ok_or_else(|| "agent disappeared".to_string())?;
build_managed_agent_summary(&app, record, &runtimes)?
let personas = load_personas(&app).unwrap_or_default();
build_managed_agent_summary(&app, record, &runtimes, &personas)?
} else {
agent
};
@@ -811,7 +816,8 @@ pub async fn start_managed_agent(
.iter()
.find(|r| r.pubkey == pubkey)
.ok_or_else(|| format!("agent {pubkey} not found"))?;
build_managed_agent_summary(&app, record, &runtimes)
let personas = load_personas(&app).unwrap_or_default();
build_managed_agent_summary(&app, record, &runtimes, &personas)
}
StartTarget::Provider { backend, .. } => Err(format!(
"agent {pubkey} has unsupported backend kind: {backend:?}"
@@ -1003,7 +1009,8 @@ pub fn stop_managed_agent(
.iter()
.find(|record| record.pubkey == pubkey)
.ok_or_else(|| format!("agent {pubkey} not found"))?;
build_managed_agent_summary(&app, record, &runtimes)
let personas = load_personas(&app).unwrap_or_default();
build_managed_agent_summary(&app, record, &runtimes, &personas)
}
#[tauri::command]

View File

@@ -1278,6 +1278,7 @@ pub fn build_managed_agent_summary(
app: &AppHandle,
record: &ManagedAgentRecord,
runtimes: &HashMap<String, ManagedAgentProcess>,
personas: &[crate::managed_agents::types::PersonaRecord],
) -> Result<ManagedAgentSummary, String> {
use crate::managed_agents::BackendKind;
@@ -1330,6 +1331,17 @@ pub fn build_managed_agent_summary(
}
};
// Resolve the effective model and system_prompt from the linked persona
// (mirrors spawn-time logic) so the UI displays the current persona values,
// not the stale record snapshot.
let (effective_prompt, effective_model, _effective_provider) =
resolve_effective_prompt_model_provider(
record.persona_id.as_deref(),
personas,
record.system_prompt.clone(),
record.model.clone(),
);
Ok(ManagedAgentSummary {
pubkey: record.pubkey.clone(),
name: record.name.clone(),
@@ -1343,8 +1355,8 @@ pub fn build_managed_agent_summary(
idle_timeout_seconds: record.idle_timeout_seconds,
max_turn_duration_seconds: record.max_turn_duration_seconds,
parallelism: record.parallelism,
system_prompt: record.system_prompt.clone(),
model: record.model.clone(),
system_prompt: effective_prompt,
model: effective_model,
mcp_toolsets: record.mcp_toolsets.clone(),
env_vars: record.env_vars.clone(),
backend: record.backend.clone(),
@@ -1435,7 +1447,7 @@ pub(crate) fn build_respond_to_env(
/// linked persona always wins so persona edits propagate on the next spawn; the
/// record snapshot is the fallback only when no persona is linked or it was
/// deleted. Provider comes from the persona (the record has no provider field).
fn resolve_effective_prompt_model_provider(
pub(crate) fn resolve_effective_prompt_model_provider(
persona_id: Option<&str>,
personas: &[crate::managed_agents::types::PersonaRecord],
record_prompt: Option<String>,