agent_ui: Refine "reject"/"keep" behavior when regenerating previous prompts (#43347)
Danilo Leal
created
Closes https://github.com/zed-industries/zed/issues/42753
Consider the following flow: you submit prompt A. Prompt A generates
some edits. You don't click on either "reject" or "keep"; they stay in a
pending state. You then submit prompt B, but before the agent outputs
any response, you click to edit prompt B, thus submitting a
regeneration.
Before this PR, the above flow would make the edits originated from
prompt A to be auto-rejected. This feels very incorrect and can surprise
users when they see that the edits that were pending got rejected. It
feels more correct to only auto-reject changes if you're regenerating
the prompt that directly generated those edits in the first place. Then,
it also feels more correct to assume that if there was a follow-up
prompt after some edits were made, those edits were passively
"accepted".
So, this is what this PR is doing. Consider the following flow to get a
picture of the behavior change:
- You submit prompt A.
- Prompt A generates some edits.
- You don't click on either "reject" or "keep"; they're pending.
- You then submit prompt B, but before the agents outputs anything, you
click to edit prompt B, submitting a regeneration.
- Now, edits from prompt A will be auto-kept.
Release Notes:
- agent: Improved the "reject"/"keep" behavior when regenerating older
prompts by auto-keeping pending edits that don't originate from the
prompt to-be-regenerated.
@@ -1273,6 +1273,28 @@ impl AcpThreadView {
};
cx.spawn_in(window, async move |this, cx| {
+ // Check if there are any edits from prompts before the one being regenerated.
+ //
+ // If there are, we keep/accept them since we're not regenerating the prompt that created them.
+ //
+ // If editing the prompt that generated the edits, they are auto-rejected
+ // through the `rewind` function in the `acp_thread`.
+ let has_earlier_edits = thread.read_with(cx, |thread, _| {
+ thread
+ .entries()
+ .iter()
+ .take(entry_ix)
+ .any(|entry| entry.diffs().next().is_some())
+ })?;
+
+ if has_earlier_edits {
+ thread.update(cx, |thread, cx| {
+ thread.action_log().update(cx, |action_log, cx| {
+ action_log.keep_all_edits(None, cx);
+ });
+ })?;
+ }
+
thread
.update(cx, |thread, cx| thread.rewind(user_message_id, cx))?
.await?;