fix: re-read persona system_prompt at spawn time for non-pack agents#729
fix: re-read persona system_prompt at spawn time for non-pack agents#729tellaho wants to merge 2 commits into
Conversation
e04dcb9 to
99ed533
Compare
f402311 to
02d5850
Compare
Extract resolve_effective_prompt_and_model() as a pure, testable function that resolves the effective system prompt and model for a managed agent. When persona_id is set, looks up the persona in the store and returns its current values. Falls back to the record snapshot when no persona is linked or the persona can't be found. Add 5 unit tests covering: - persona_id matches → reads fresh prompt + model - no persona_id → falls back to record snapshot - persona_id not found in store → falls back to record snapshot - no persona and no record prompt → returns None/None - persona has no model → returns None (doesn't inherit record model)
044e21e to
a652632
Compare
|
@codex please review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f3778e9d47
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| match from_persona { | ||
| Some((prompt, model)) => (Some(prompt), model), | ||
| None => ( |
There was a problem hiding this comment.
Preserve per-agent model overrides for persona-linked agents
When a persona_id is present, this branch always returns the persona's model (including None) and never uses record_model, so a saved per-agent model choice is ignored at spawn time for non-pack persona agents. In practice, if a persona has no model set and the user selects one via update_managed_agent/ModelPicker, the value is persisted on the record but SPROUT_ACP_MODEL is removed on restart, causing the runtime default model to be used instead of the selected one.
Useful? React with 👍 / 👎.
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Review notes from my pass:
I think the user-facing goal is worth doing: persona edits should take effect after an agent restart. The current implementation looks too broad, though, because it changes the precedence semantics for all persona-linked local agents and leaves provider deploy on the old behavior.
Main things to address:
- Preserve or intentionally remove per-agent prompt/model overrides for persona-linked agents. Right now the UI still saves them, but local spawn ignores them when
persona_idresolves. - Apply the same effective prompt/model resolution to provider deploys, or document that this fix is local-only.
- Tighten the missing-persona test/description so it does not imply full spawn succeeds with a missing persona;
resolve_persona_env()still fails closed later inspawn_agent_child().
I could not complete the local targeted Tauri unit run because the build failed before tests on a missing sidecar resource: desktop/src-tauri/binaries/sprout-aarch64-apple-darwin.
| }); | ||
|
|
||
| match from_persona { | ||
| Some((prompt, model)) => (Some(prompt), model), |
There was a problem hiding this comment.
🤖 This makes the persona prompt/model always win whenever persona_id resolves, but the existing app still treats ManagedAgentRecord.system_prompt and .model as mutable per-agent settings. EditAgentDialog persists systemPrompt, and ModelPicker persists model; after this change those saved values become no-ops for persona-linked agents. In particular, if a persona has model: None, selecting a model on that agent will still save/display but spawn will remove SPROUT_ACP_MODEL. Can we either preserve explicit agent override precedence, or update the UI/data model so persona-backed agents cannot appear to have per-agent prompt/model overrides?
| Some((prompt, model)) => (Some(prompt), model), | ||
| None => (record.system_prompt.clone(), record.model.clone()), | ||
| }; | ||
| // Resolve system prompt and model via the extracted helper. Re-reads |
There was a problem hiding this comment.
🤖 This re-read is only wired into local spawn_agent_child(). Provider-backed starts/redeploys still build their payload from record.system_prompt and record.model in build_deploy_payload(), so persona edits will not propagate there. If provider agents are in scope, this effective prompt/model resolver should be shared with the deploy payload path too; if not, the PR description should call out that the fix is local-only.
| /// returns its current `system_prompt` and `model`. Falls back to the | ||
| /// agent record's stale snapshot (`record_prompt`, `record_model`) when: | ||
| /// - `persona_id` is `None` | ||
| /// - the persona can't be found in the store (e.g. deleted) |
There was a problem hiding this comment.
🤖 This fallback is true for the pure helper, but full spawn still calls resolve_persona_env(app, record.persona_id.as_deref())? later, which fails closed when persona_id is set and missing. The test/description around the missing-persona case may overstate runtime behavior unless the env resolution path is also adjusted.
What changed for users
Before: Editing a persona's system prompt or model had no effect on existing agents — even after stopping and restarting them. The only workaround was to delete the agent and recreate it from scratch.
After: Persona edits take effect on the very next agent spawn. Stop an agent, tweak its persona's instructions, start it again — it picks up the new prompt immediately. This makes agent iteration and improvement loops dramatically faster.
Technical changes
resolve_effective_prompt_and_model()— a pure function that resolves the effective system prompt and model given apersona_id, the persona store, and the record's stale snapshot values. NoAppHandledependency, trivially testable.spawn_agent_child()now re-reads the persona store at spawn time viaload_personas()then delegates to the extracted helper. Falls back torecord.system_prompt/record.modelwhen no persona is linked or the persona can't be found (graceful degradation).runtime/tests.rsfollowing theenv_vars/tests.rspattern, bringingruntime.rsunder the file-size linter limit.check-file-sizes.mjs.Testing
resolve_effective_prompt_and_model:persona_idmatches → reads fresh prompt + model from persona storepersona_id→ falls back to record snapshotpersona_idnot found (deleted) → graceful fallback to record snapshotcargo test --manifest-path desktop/src-tauri/Cargo.toml --lib→ 354/354 passrustfmt --check✅👆 Set the agent's instructions from
only respond with 5 words, starting with the letter P, sent a message, stopped it, set the instructions toonly respond with 5 words, starting with the letter B, then respawned it.Note for the team
The desktop Tauri crate has 354 unit tests (including 5 new ones from this PR), but
just test-unitandjust cidon't run them — onlycargo test --manifest-path desktop/src-tauri/Cargo.toml --libexercises them locally. Consider wiring this into the CI gate separately.