diff --git a/crates/cloud_llm_client/src/cloud_llm_client.rs b/crates/cloud_llm_client/src/cloud_llm_client.rs index 2bc734cc10e..adbcffe9be8 100644 --- a/crates/cloud_llm_client/src/cloud_llm_client.rs +++ b/crates/cloud_llm_client/src/cloud_llm_client.rs @@ -198,6 +198,8 @@ pub enum EditPredictionRejectReason { InterpolatedEmpty, /// Edits returned, but could not be interpolated after buffer changes InterpolateFailed, + /// A patch was returned, but could not be applied to the buffer + PatchApplyFailed, /// The new prediction was preferred over the current one Replaced, /// The current prediction was preferred over the new one diff --git a/crates/edit_prediction/src/prediction.rs b/crates/edit_prediction/src/prediction.rs index 0f7896bc882..592d5e3b1af 100644 --- a/crates/edit_prediction/src/prediction.rs +++ b/crates/edit_prediction/src/prediction.rs @@ -104,6 +104,34 @@ impl EditPredictionResult { e2e_latency, } } + + pub fn new_rejected( + id: EditPredictionId, + edited_buffer: &Entity, + edited_buffer_snapshot: &BufferSnapshot, + inputs: EditPredictionInputs, + model_version: Option, + trigger: PredictEditsRequestTrigger, + e2e_latency: std::time::Duration, + reject_reason: EditPredictionRejectReason, + ) -> Self { + Self { + prediction: EditPrediction { + id, + edits: Arc::default(), + cursor_position: None, + editable_range: None, + snapshot: edited_buffer_snapshot.clone(), + edit_preview: EditPreview::unchanged(edited_buffer_snapshot), + inputs, + buffer: edited_buffer.clone(), + model_version, + trigger, + }, + reject_reason: Some(reject_reason), + e2e_latency, + } + } } #[derive(Clone)] diff --git a/crates/edit_prediction/src/zeta.rs b/crates/edit_prediction/src/zeta.rs index 009d91c5b57..54b324253ad 100644 --- a/crates/edit_prediction/src/zeta.rs +++ b/crates/edit_prediction/src/zeta.rs @@ -9,7 +9,9 @@ use crate::{ udiff::prediction_edits_for_single_file_diff, }; use anyhow::{Context as _, Result}; -use cloud_llm_client::{AcceptEditPredictionBody, predict_edits_v3::RawCompletionRequest}; +use cloud_llm_client::{ + AcceptEditPredictionBody, EditPredictionRejectReason, predict_edits_v3::RawCompletionRequest, +}; use edit_prediction_types::PredictedCursorPosition; use gpui::{App, AppContext as _, Entity, Task, TaskExt, WeakEntity, prelude::*}; use language::{ @@ -516,26 +518,41 @@ pub(crate) fn request_prediction_with_zeta( snapshot: fallback_snapshot, patch, } => { - let Some((buffer, snapshot, edits, cursor_position)) = - prediction_edits_for_single_file_diff(&patch, &project, cx).await? - else { - return Ok(Some( - EditPredictionResult::new( - id, - &fallback_buffer, - &fallback_snapshot, - Arc::new([]), - None, - None, - inputs, - model_version, - trigger, - request_duration, - cx, - ) - .await, - )); - }; + let (buffer, snapshot, edits, cursor_position) = + match prediction_edits_for_single_file_diff(&patch, &project, cx).await { + Ok(Some(edits)) => edits, + Ok(None) => { + return Ok(Some( + EditPredictionResult::new( + id, + &fallback_buffer, + &fallback_snapshot, + Arc::new([]), + None, + None, + inputs, + model_version, + trigger, + request_duration, + cx, + ) + .await, + )); + } + Err(error) => { + log::error!("failed to apply edit prediction patch: {error:?}"); + return Ok(Some(EditPredictionResult::new_rejected( + id, + &fallback_buffer, + &fallback_snapshot, + inputs, + model_version, + trigger, + request_duration, + EditPredictionRejectReason::PatchApplyFailed, + ))); + } + }; let editable_range_in_buffer = edits .iter()