Skip to content

Commit 7521e2a

Browse files
agu-zosyvokon
authored andcommitted
zeta2: Include a single unified diff for the edit history (zed-industries#40400)
Instead of producing multiple code blocks for each edit history event, we now produce a continuous unified diff. Release Notes: - N/A --------- Co-authored-by: Oleksiy Syvokon <[email protected]>
1 parent 942f0a0 commit 7521e2a

File tree

4 files changed

+123
-46
lines changed

4 files changed

+123
-46
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cloud_llm_client/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ workspace-hack.workspace = true
2525

2626
[dev-dependencies]
2727
pretty_assertions.workspace = true
28+
indoc.workspace = true

crates/cloud_llm_client/src/predict_edits_v3.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use chrono::Duration;
22
use serde::{Deserialize, Serialize};
33
use std::{
4+
fmt::Display,
45
ops::{Add, Range, Sub},
56
path::{Path, PathBuf},
67
sync::Arc,
@@ -91,6 +92,38 @@ pub enum Event {
9192
},
9293
}
9394

95+
impl Display for Event {
96+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97+
match self {
98+
Event::BufferChange {
99+
path,
100+
old_path,
101+
diff,
102+
predicted,
103+
} => {
104+
let new_path = path.as_deref().unwrap_or(Path::new("untitled"));
105+
let old_path = old_path.as_deref().unwrap_or(new_path);
106+
107+
if *predicted {
108+
write!(
109+
f,
110+
"// User accepted prediction:\n--- a/{}\n+++ b/{}\n{diff}",
111+
old_path.display(),
112+
new_path.display()
113+
)
114+
} else {
115+
write!(
116+
f,
117+
"--- a/{}\n+++ b/{}\n{diff}",
118+
old_path.display(),
119+
new_path.display()
120+
)
121+
}
122+
}
123+
}
124+
}
125+
}
126+
94127
#[derive(Debug, Clone, Serialize, Deserialize)]
95128
pub struct Signature {
96129
pub text: String,
@@ -204,3 +237,82 @@ impl Sub for Line {
204237
Self(self.0 - rhs.0)
205238
}
206239
}
240+
241+
#[cfg(test)]
242+
mod tests {
243+
use super::*;
244+
use indoc::indoc;
245+
use pretty_assertions::assert_eq;
246+
247+
#[test]
248+
fn test_event_display() {
249+
let ev = Event::BufferChange {
250+
path: None,
251+
old_path: None,
252+
diff: "@@ -1,2 +1,2 @@\n-a\n-b\n".into(),
253+
predicted: false,
254+
};
255+
assert_eq!(
256+
ev.to_string(),
257+
indoc! {"
258+
--- a/untitled
259+
+++ b/untitled
260+
@@ -1,2 +1,2 @@
261+
-a
262+
-b
263+
"}
264+
);
265+
266+
let ev = Event::BufferChange {
267+
path: Some(PathBuf::from("foo/bar.txt")),
268+
old_path: Some(PathBuf::from("foo/bar.txt")),
269+
diff: "@@ -1,2 +1,2 @@\n-a\n-b\n".into(),
270+
predicted: false,
271+
};
272+
assert_eq!(
273+
ev.to_string(),
274+
indoc! {"
275+
--- a/foo/bar.txt
276+
+++ b/foo/bar.txt
277+
@@ -1,2 +1,2 @@
278+
-a
279+
-b
280+
"}
281+
);
282+
283+
let ev = Event::BufferChange {
284+
path: Some(PathBuf::from("abc.txt")),
285+
old_path: Some(PathBuf::from("123.txt")),
286+
diff: "@@ -1,2 +1,2 @@\n-a\n-b\n".into(),
287+
predicted: false,
288+
};
289+
assert_eq!(
290+
ev.to_string(),
291+
indoc! {"
292+
--- a/123.txt
293+
+++ b/abc.txt
294+
@@ -1,2 +1,2 @@
295+
-a
296+
-b
297+
"}
298+
);
299+
300+
let ev = Event::BufferChange {
301+
path: Some(PathBuf::from("abc.txt")),
302+
old_path: Some(PathBuf::from("123.txt")),
303+
diff: "@@ -1,2 +1,2 @@\n-a\n-b\n".into(),
304+
predicted: true,
305+
};
306+
assert_eq!(
307+
ev.to_string(),
308+
indoc! {"
309+
// User accepted prediction:
310+
--- a/123.txt
311+
+++ b/abc.txt
312+
@@ -1,2 +1,2 @@
313+
-a
314+
-b
315+
"}
316+
);
317+
}
318+
}

crates/cloud_zeta2_prompt/src/cloud_zeta2_prompt.rs

Lines changed: 9 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
//! Zeta2 prompt planning and generation code shared with cloud.
22
33
use anyhow::{Context as _, Result, anyhow};
4-
use cloud_llm_client::predict_edits_v3::{
5-
self, Event, Line, Point, PromptFormat, ReferencedDeclaration,
6-
};
4+
use cloud_llm_client::predict_edits_v3::{self, Line, Point, PromptFormat, ReferencedDeclaration};
75
use indoc::indoc;
86
use ordered_float::OrderedFloat;
97
use rustc_hash::{FxHashMap, FxHashSet};
@@ -419,7 +417,7 @@ impl<'a> PlannedPrompt<'a> {
419417
};
420418

421419
if self.request.events.is_empty() {
422-
prompt.push_str("No edits yet.\n\n");
420+
prompt.push_str("(No edit history)\n\n");
423421
} else {
424422
prompt.push_str(
425423
"The following are the latest edits made by the user, from earlier to later.\n\n",
@@ -465,50 +463,15 @@ impl<'a> PlannedPrompt<'a> {
465463
}
466464

467465
fn push_events(output: &mut String, events: &[predict_edits_v3::Event]) {
468-
for event in events {
469-
match event {
470-
Event::BufferChange {
471-
path,
472-
old_path,
473-
diff,
474-
predicted,
475-
} => {
476-
if let Some(old_path) = &old_path
477-
&& let Some(new_path) = &path
478-
{
479-
if old_path != new_path {
480-
writeln!(
481-
output,
482-
"User renamed {} to {}\n\n",
483-
old_path.display(),
484-
new_path.display()
485-
)
486-
.unwrap();
487-
}
488-
}
466+
if events.is_empty() {
467+
return;
468+
};
489469

490-
let path = path
491-
.as_ref()
492-
.map_or_else(|| "untitled".to_string(), |path| path.display().to_string());
493-
494-
if *predicted {
495-
writeln!(
496-
output,
497-
"User accepted prediction {:?}:\n`````diff\n{}\n`````\n",
498-
path, diff
499-
)
500-
.unwrap();
501-
} else {
502-
writeln!(
503-
output,
504-
"User edited {:?}:\n`````diff\n{}\n`````\n",
505-
path, diff
506-
)
507-
.unwrap();
508-
}
509-
}
510-
}
470+
writeln!(output, "`````diff").unwrap();
471+
for event in events {
472+
writeln!(output, "{}", event).unwrap();
511473
}
474+
writeln!(output, "`````\n").unwrap();
512475
}
513476

514477
fn push_file_snippets(

0 commit comments

Comments
 (0)