From 3fb5862cac4e78b367b228e4e9429042d5ffb548 Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Tue, 28 Jul 2026 10:02:14 -0500 Subject: [PATCH] edit_prediction: Normalize prompt paths to Unix style (#61792) # Objective - Fix V4 edit prediction requests failing for local Windows projects because native path separators do not match Unix-formatted context paths on the server. ## Solution - Canonicalize serialized buffer paths through the existing `RelPath` representation. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Suggested .rules additions - Paths serialized for edit prediction APIs must use `RelPath`'s Unix representation rather than platform-native `PathBuf` formatting. --- Release Notes: - N/A --- crates/edit_prediction/src/edit_prediction.rs | 15 +++++++++------ .../edit_prediction/src/edit_prediction_tests.rs | 11 ++++++++++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/crates/edit_prediction/src/edit_prediction.rs b/crates/edit_prediction/src/edit_prediction.rs index 965d8bc269..850851dc69 100644 --- a/crates/edit_prediction/src/edit_prediction.rs +++ b/crates/edit_prediction/src/edit_prediction.rs @@ -70,7 +70,7 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use thiserror::Error; -use util::ResultExt as _; +use util::{ResultExt as _, rel_path::RelPath}; pub mod cursor_excerpt; pub mod data_collection; @@ -904,11 +904,14 @@ pub(crate) fn buffer_path_with_id_fallback( snapshot: &TextBufferSnapshot, cx: &App, ) -> Arc { - if let Some(file) = file { - file.full_path(cx).into() - } else { - Path::new(&format!("untitled-{}", snapshot.remote_id())).into() - } + let Some(file) = file else { + return Path::new(&format!("untitled-{}", snapshot.remote_id())).into(); + }; + let full_path = file.full_path(cx); + let Some(path) = RelPath::new(&full_path, file.path_style(cx)).ok() else { + return Path::new(&format!("untitled-{}", snapshot.remote_id())).into(); + }; + path.as_std_path().into() } fn predict_edits_request_trigger_from_editor_trigger( diff --git a/crates/edit_prediction/src/edit_prediction_tests.rs b/crates/edit_prediction/src/edit_prediction_tests.rs index dd8b866a6b..eb0851ffb2 100644 --- a/crates/edit_prediction/src/edit_prediction_tests.rs +++ b/crates/edit_prediction/src/edit_prediction_tests.rs @@ -4127,13 +4127,22 @@ async fn test_edit_prediction_settled_drops_future_events_when_their_oss_status_ } #[gpui::test] -fn test_buffer_path_with_id_fallback_for_untitled_buffers(cx: &mut TestAppContext) { +fn test_buffer_path_with_id_fallback(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 windows_file: Arc = Arc::new(language::TestFile { + path: util::rel_path::rel_path("src/main.rs").into(), + root_name: "workspace".into(), + local_root: None, + }); + let windows_path = + cx.read(|cx| buffer_path_with_id_fallback(Some(&windows_file), &snapshot_1, cx)); + assert_eq!(windows_path.to_string_lossy(), "workspace/src/main.rs"); + 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));