mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
feat(desktop): re-snapshot persona config on every agent spawn (#1268)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1fgdl5qqnh3k3f2xkqrvt7cujalhm623x4s7fdjdj5yrtp5fzjl9qrjpucw <4a1bfa0013bc6d14a8d600d8bf6392efefbd2a26ac3c96c9b2a106b0d12297ca@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
co-authored by
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7
npub1fgdl5qqnh3k3f2xkqrvt7cujalhm623x4s7fdjdj5yrtp5fzjl9qrjpucw
parent
0cee0435f7
commit
048e8fdc00
@@ -34,7 +34,9 @@ const overrides = new Map([
|
||||
// read-time relay-URL workspace fallback while keeping the create-time env
|
||||
// pin (the credential-leak guard). Load-bearing feature growth from the
|
||||
// rebase, queued to split with the rest of this list.
|
||||
["src-tauri/src/commands/agents.rs", 1350],
|
||||
// persona-refresh-on-spawn: re-snapshot + retain_managed_agent_pending call
|
||||
// in start_local_agent_with_preflight adds ~23 lines. Queued to split.
|
||||
["src-tauri/src/commands/agents.rs", 1380],
|
||||
// Residual repos_dir integration in ensure_nest_at: REPOS is provisioned
|
||||
// outside NEST_DIRS (it may be a symlink), so it needs its own create +
|
||||
// chmod-only-when-real-dir handling plus integration test coverage. The
|
||||
|
||||
@@ -255,8 +255,31 @@ async fn start_local_agent_with_preflight(
|
||||
if record.backend != BackendKind::Local {
|
||||
return Err(format!("agent {pubkey} is no longer a local agent"));
|
||||
}
|
||||
// Re-snapshot the persona onto the record at every spawn so the agent always
|
||||
// starts with the current persona config (system_prompt, model, provider,
|
||||
// env_vars). This clears the "out of date" drift badge without requiring a
|
||||
// delete+recreate. Agent-level env_vars overrides still win (persona_snapshot
|
||||
// layers persona env under agent overrides).
|
||||
if let Some(persona_id) = record.persona_id.clone() {
|
||||
let personas = load_personas(app).unwrap_or_default();
|
||||
if let Some(persona) = personas.iter().find(|p| p.id == persona_id) {
|
||||
let snapshot =
|
||||
crate::managed_agents::persona_events::persona_snapshot(persona, &record.env_vars);
|
||||
if let Some(prompt) = snapshot.system_prompt {
|
||||
record.system_prompt = Some(prompt);
|
||||
}
|
||||
record.model = snapshot.model;
|
||||
record.provider = snapshot.provider;
|
||||
record.env_vars = snapshot.env_vars;
|
||||
record.persona_source_version = Some(snapshot.source_version);
|
||||
record.updated_at = crate::util::now_iso();
|
||||
}
|
||||
}
|
||||
start_managed_agent_process(app, record, &mut runtimes, Some(owner_hex))?;
|
||||
save_managed_agents(app, &records)?;
|
||||
if let Some(saved_record) = records.iter().find(|r| r.pubkey == pubkey) {
|
||||
retain_managed_agent_pending(app, state, saved_record);
|
||||
}
|
||||
let record = records
|
||||
.iter()
|
||||
.find(|record| record.pubkey == pubkey)
|
||||
|
||||
@@ -91,7 +91,7 @@ pub async fn restore_managed_agents_on_launch(
|
||||
let state = app.state::<AppState>();
|
||||
|
||||
// ── Phase A (under lock): housekeeping + collect agents to restore ──
|
||||
let agents_to_start: Vec<super::ManagedAgentRecord>;
|
||||
let mut agents_to_start: Vec<super::ManagedAgentRecord>;
|
||||
{
|
||||
let _store_guard = state
|
||||
.managed_agents_store_lock
|
||||
@@ -151,6 +151,38 @@ pub async fn restore_managed_agents_on_launch(
|
||||
}
|
||||
agents_to_start = to_start;
|
||||
|
||||
// Re-snapshot persona config for agents about to be restored, matching
|
||||
// the interactive spawn path so auto-start agents also pick up the
|
||||
// current persona on app launch.
|
||||
let personas_for_snapshot = super::load_personas(app).unwrap_or_default();
|
||||
for record in records.iter_mut() {
|
||||
if !agents_to_start.iter().any(|r| r.pubkey == record.pubkey) {
|
||||
continue;
|
||||
}
|
||||
let Some(persona_id) = record.persona_id.clone() else {
|
||||
continue;
|
||||
};
|
||||
let Some(persona) = personas_for_snapshot.iter().find(|p| p.id == persona_id) else {
|
||||
continue;
|
||||
};
|
||||
let snapshot = super::persona_events::persona_snapshot(persona, &record.env_vars);
|
||||
if let Some(prompt) = snapshot.system_prompt {
|
||||
record.system_prompt = Some(prompt);
|
||||
}
|
||||
record.model = snapshot.model;
|
||||
record.provider = snapshot.provider;
|
||||
record.env_vars = snapshot.env_vars;
|
||||
record.persona_source_version = Some(snapshot.source_version);
|
||||
record.updated_at = util::now_iso();
|
||||
changed = true;
|
||||
}
|
||||
// Re-collect to_start from the updated records so Phase B spawns the refreshed config.
|
||||
agents_to_start = records
|
||||
.iter()
|
||||
.filter(|r| agents_to_start.iter().any(|s| s.pubkey == r.pubkey))
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
if changed {
|
||||
save_managed_agents(app, &records)?;
|
||||
}
|
||||
|
||||
@@ -276,8 +276,8 @@ function AgentSummary({
|
||||
</div>
|
||||
{agent.personaOutOfDate ? (
|
||||
<p className="mt-1.5 text-xs text-amber-600 dark:text-amber-400">
|
||||
Persona updated since this agent was created. Delete and respawn
|
||||
to apply the new configuration.
|
||||
Persona updated since this agent was created. Respawn to apply the
|
||||
new configuration.
|
||||
</p>
|
||||
) : null}
|
||||
{channelNames.length > 0 ? (
|
||||
|
||||
Reference in New Issue
Block a user