From b178949033c8062c817bcf6a02fd0d5de87fd9dd Mon Sep 17 00:00:00 2001 From: Rocky Shi Date: Mon, 27 Apr 2026 21:31:45 +1200 Subject: [PATCH] Enable edit prediction and Copilot for untitled buffers (#45764) Closes [#45631](https://github.com/zed-industries/zed/issues/45631) Recording: https://github.com/user-attachments/assets/a5143eb4-fae3-42a7-9d64-fb7c42ee97c2 Release Notes: - copilot: Edit predictions now work in temporary files --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> --- crates/edit_prediction/src/edit_prediction.rs | 2 +- .../src/edit_prediction_tests.rs | 22 +++++++++++++++++++ crates/edit_prediction/src/zeta.rs | 7 ++---- .../zed/src/zed/edit_prediction_registry.rs | 4 +--- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/crates/edit_prediction/src/edit_prediction.rs b/crates/edit_prediction/src/edit_prediction.rs index c156e694666..f43b94212c0 100644 --- a/crates/edit_prediction/src/edit_prediction.rs +++ b/crates/edit_prediction/src/edit_prediction.rs @@ -725,7 +725,7 @@ fn compute_diff_between_snapshots_in_range( Some((diff, new_start_point..new_end_point)) } -fn buffer_path_with_id_fallback( +pub(crate) fn buffer_path_with_id_fallback( file: Option<&Arc>, snapshot: &TextBufferSnapshot, cx: &App, diff --git a/crates/edit_prediction/src/edit_prediction_tests.rs b/crates/edit_prediction/src/edit_prediction_tests.rs index 8869e1c3f3a..6cc38a875e1 100644 --- a/crates/edit_prediction/src/edit_prediction_tests.rs +++ b/crates/edit_prediction/src/edit_prediction_tests.rs @@ -3417,6 +3417,28 @@ async fn test_edit_prediction_settled(cx: &mut TestAppContext) { } } +#[gpui::test] +fn test_buffer_path_with_id_fallback_for_untitled_buffers(cx: &mut TestAppContext) { + let buffer_1 = cx.new(|cx| Buffer::local("one", cx)); + let buffer_2 = cx.new(|cx| Buffer::local("two", cx)); + + let snapshot_1 = buffer_1.read_with(cx, |buffer, _| buffer.text_snapshot()); + let snapshot_2 = buffer_2.read_with(cx, |buffer, _| buffer.text_snapshot()); + + let path_1 = cx.read(|cx| buffer_path_with_id_fallback(None, &snapshot_1, cx)); + let path_2 = cx.read(|cx| buffer_path_with_id_fallback(None, &snapshot_2, cx)); + + assert_eq!( + path_1.as_ref(), + Path::new(&format!("untitled-{}", snapshot_1.remote_id())) + ); + assert_eq!( + path_2.as_ref(), + Path::new(&format!("untitled-{}", snapshot_2.remote_id())) + ); + assert_ne!(path_1.as_ref(), path_2.as_ref()); +} + #[gpui::test] async fn test_data_collection_disabled_by_default(cx: &mut TestAppContext) { let (ep_store, _channels) = init_test_with_fake_client(cx); diff --git a/crates/edit_prediction/src/zeta.rs b/crates/edit_prediction/src/zeta.rs index 7b124533534..6a287847fd2 100644 --- a/crates/edit_prediction/src/zeta.rs +++ b/crates/edit_prediction/src/zeta.rs @@ -1,7 +1,7 @@ use crate::{ CurrentEditPrediction, DebugEvent, EditPredictionFinishedDebugEvent, EditPredictionId, EditPredictionModelInput, EditPredictionStartedDebugEvent, EditPredictionStore, StoredEvent, - ZedUpdateRequiredError, + ZedUpdateRequiredError, buffer_path_with_id_fallback, cursor_excerpt::{self, compute_cursor_excerpt, compute_syntax_ranges}, prediction::EditPredictionResult, }; @@ -70,10 +70,7 @@ pub fn request_prediction_with_zeta( let preferred_experiment = store.preferred_experiment().map(|s| s.to_owned()); let open_ai_compatible_api_key = load_open_ai_compatible_api_key_if_needed(provider, cx); - let excerpt_path: Arc = snapshot - .file() - .map(|file| -> Arc { file.full_path(cx).into() }) - .unwrap_or_else(|| Arc::from(Path::new("untitled"))); + let excerpt_path = buffer_path_with_id_fallback(snapshot.file(), &snapshot.text, cx); let repo_url = if can_collect_data { let buffer_id = buffer.read(cx).remote_id(); diff --git a/crates/zed/src/zed/edit_prediction_registry.rs b/crates/zed/src/zed/edit_prediction_registry.rs index e1245615542..ad394cc5e76 100644 --- a/crates/zed/src/zed/edit_prediction_registry.rs +++ b/crates/zed/src/zed/edit_prediction_registry.rs @@ -258,9 +258,7 @@ fn assign_edit_prediction_provider( ep_store.update(cx, |this, cx| this.start_copilot_for_project(&project, cx)); if let Some(copilot) = copilot { - if let Some(buffer) = singleton_buffer - && buffer.read(cx).file().is_some() - { + if let Some(buffer) = singleton_buffer { copilot.update(cx, |copilot, cx| { copilot.register_buffer(&buffer, cx); });