diff --git a/Cargo.lock b/Cargo.lock index 7817dcee3b..c99fa25712 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16757,12 +16757,13 @@ dependencies = [ [[package]] name = "zed_llm_client" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "656118e6b072924d28815cb892278f12c2548117794e733bd2c075ef4a0427e8" +checksum = "614669bead4741b2fc352ae1967318be16949cf46f59013e548c6dbfdfc01252" dependencies = [ "serde", "serde_json", + "uuid", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b203bd0af3..576f4bb797 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -561,7 +561,7 @@ wasmtime = { version = "24", default-features = false, features = [ wasmtime-wasi = "24" which = "6.0.0" wit-component = "0.201" -zed_llm_client = "0.3" +zed_llm_client = "0.4" zstd = "0.11" metal = "0.31" diff --git a/crates/copilot/src/copilot_completion_provider.rs b/crates/copilot/src/copilot_completion_provider.rs index 0e494056ec..e6757e9d7f 100644 --- a/crates/copilot/src/copilot_completion_provider.rs +++ b/crates/copilot/src/copilot_completion_provider.rs @@ -242,6 +242,7 @@ impl EditPredictionProvider for CopilotCompletionProvider { } else { let position = cursor_position.bias_right(buffer); Some(InlineCompletion { + id: None, edits: vec![(position..position, completion_text.into())], edit_preview: None, }) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index b5ef81bfba..15317e0999 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -490,6 +490,7 @@ enum InlineCompletion { struct InlineCompletionState { inlay_ids: Vec, completion: InlineCompletion, + completion_id: Option, invalidation_range: Range, } @@ -4893,7 +4894,11 @@ impl Editor { return; }; - self.report_inline_completion_event(true, cx); + self.report_inline_completion_event( + active_inline_completion.completion_id.clone(), + true, + cx, + ); match &active_inline_completion.completion { InlineCompletion::Move { target, .. } => { @@ -4942,7 +4947,11 @@ impl Editor { return; } - self.report_inline_completion_event(true, cx); + self.report_inline_completion_event( + active_inline_completion.completion_id.clone(), + true, + cx, + ); match &active_inline_completion.completion { InlineCompletion::Move { target, .. } => { @@ -5000,7 +5009,12 @@ impl Editor { cx: &mut Context, ) -> bool { if should_report_inline_completion_event { - self.report_inline_completion_event(false, cx); + let completion_id = self + .active_inline_completion + .as_ref() + .and_then(|active_completion| active_completion.completion_id.clone()); + + self.report_inline_completion_event(completion_id, false, cx); } if let Some(provider) = self.edit_prediction_provider() { @@ -5010,7 +5024,7 @@ impl Editor { self.take_active_inline_completion(cx) } - fn report_inline_completion_event(&self, accepted: bool, cx: &App) { + fn report_inline_completion_event(&self, id: Option, accepted: bool, cx: &App) { let Some(provider) = self.edit_prediction_provider() else { return; }; @@ -5035,6 +5049,7 @@ impl Editor { telemetry::event!( event_type, provider = provider.name(), + prediction_id = id, suggestion_accepted = accepted, file_extension = extension, ); @@ -5250,6 +5265,7 @@ impl Editor { self.active_inline_completion = Some(InlineCompletionState { inlay_ids, completion, + completion_id: inline_completion.id, invalidation_range, }); diff --git a/crates/editor/src/inline_completion_tests.rs b/crates/editor/src/inline_completion_tests.rs index 258a878094..c74de1fc93 100644 --- a/crates/editor/src/inline_completion_tests.rs +++ b/crates/editor/src/inline_completion_tests.rs @@ -333,6 +333,7 @@ fn propose_edits( cx.update(|_, cx| { provider.update(cx, |provider, _| { provider.set_inline_completion(Some(inline_completion::InlineCompletion { + id: None, edits: edits.collect(), edit_preview: None, })) diff --git a/crates/inline_completion/src/inline_completion.rs b/crates/inline_completion/src/inline_completion.rs index bc123f0580..cea21472ca 100644 --- a/crates/inline_completion/src/inline_completion.rs +++ b/crates/inline_completion/src/inline_completion.rs @@ -1,4 +1,4 @@ -use gpui::{App, Context, Entity}; +use gpui::{App, Context, Entity, SharedString}; use language::Buffer; use project::Project; use std::ops::Range; @@ -15,6 +15,8 @@ pub enum Direction { #[derive(Clone)] pub struct InlineCompletion { + /// The ID of the completion, if it has one. + pub id: Option, pub edits: Vec<(Range, String)>, pub edit_preview: Option, } diff --git a/crates/supermaven/src/supermaven_completion_provider.rs b/crates/supermaven/src/supermaven_completion_provider.rs index 3e70a1c576..4dc0ebbabb 100644 --- a/crates/supermaven/src/supermaven_completion_provider.rs +++ b/crates/supermaven/src/supermaven_completion_provider.rs @@ -92,6 +92,7 @@ fn completion_from_diff( } InlineCompletion { + id: None, edits, edit_preview: None, } diff --git a/crates/zeta/src/zeta.rs b/crates/zeta/src/zeta.rs index bdd5c6412b..14cd32b300 100644 --- a/crates/zeta/src/zeta.rs +++ b/crates/zeta/src/zeta.rs @@ -81,12 +81,6 @@ impl std::fmt::Display for InlineCompletionId { } } -impl InlineCompletionId { - fn new() -> Self { - Self(Uuid::new_v4()) - } -} - #[derive(Clone)] struct ZetaGlobal(Entity); @@ -452,11 +446,10 @@ impl Zeta { let response = perform_predict_edits(client, llm_token, is_staff, body).await?; - let output_excerpt = response.output_excerpt; - log::debug!("completion response: {}", output_excerpt); + log::debug!("completion response: {}", &response.output_excerpt); Self::process_completion_response( - output_excerpt, + response, buffer, &snapshot, values.editable_range, @@ -495,6 +488,7 @@ impl Zeta { &buffer, position, PredictEditsResponse { + request_id: Uuid::parse_str("e7861db5-0cea-4761-b1c5-ad083ac53a80").unwrap(), output_excerpt: format!("{EDITABLE_REGION_START_MARKER} a longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg line [here's an edit] @@ -511,6 +505,7 @@ and then another &buffer, position, PredictEditsResponse { + request_id: Uuid::parse_str("077c556a-2c49-44e2-bbc6-dafc09032a5e").unwrap(), output_excerpt: format!(r#"{EDITABLE_REGION_START_MARKER} a longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg line And maybe a short line @@ -527,6 +522,7 @@ and then another &buffer, position, PredictEditsResponse { + request_id: Uuid::parse_str("df8c7b23-3d1d-4f99-a306-1f6264a41277").unwrap(), output_excerpt: format!(r#"{EDITABLE_REGION_START_MARKER} a longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg line And maybe a short line @@ -544,6 +540,7 @@ and then another &buffer, position, PredictEditsResponse { + request_id: Uuid::parse_str("c743958d-e4d8-44a8-aa5b-eb1e305c5f5c").unwrap(), output_excerpt: format!(r#"{EDITABLE_REGION_START_MARKER} a longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg line And maybe a short line @@ -561,6 +558,7 @@ and then another &buffer, position, PredictEditsResponse { + request_id: Uuid::parse_str("ff5cd7ab-ad06-4808-986e-d3391e7b8355").unwrap(), output_excerpt: format!(r#"{EDITABLE_REGION_START_MARKER} a longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg line And maybe a short line @@ -577,6 +575,7 @@ and then another &buffer, position, PredictEditsResponse { + request_id: Uuid::parse_str("83cafa55-cdba-4b27-8474-1865ea06be94").unwrap(), output_excerpt: format!(r#"{EDITABLE_REGION_START_MARKER} a longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg line And maybe a short line @@ -592,6 +591,7 @@ and then another &buffer, position, PredictEditsResponse { + request_id: Uuid::parse_str("d5bd3afd-8723-47c7-bd77-15a3a926867b").unwrap(), output_excerpt: format!(r#"{EDITABLE_REGION_START_MARKER} a longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg line And maybe a short line @@ -703,7 +703,7 @@ and then another #[allow(clippy::too_many_arguments)] fn process_completion_response( - output_excerpt: String, + prediction_response: PredictEditsResponse, buffer: Entity, snapshot: &BufferSnapshot, editable_range: Range, @@ -716,6 +716,8 @@ and then another cx: &AsyncApp, ) -> Task>> { let snapshot = snapshot.clone(); + let request_id = prediction_response.request_id; + let output_excerpt = prediction_response.output_excerpt; cx.spawn(|cx| async move { let output_excerpt: Arc = output_excerpt.into(); @@ -746,7 +748,7 @@ and then another let edit_preview = edit_preview.await; Ok(Some(InlineCompletion { - id: InlineCompletionId::new(), + id: InlineCompletionId(request_id), path, excerpt_range: editable_range, cursor_offset, @@ -1550,6 +1552,7 @@ impl inline_completion::EditPredictionProvider for ZetaInlineCompletionProvider } Some(inline_completion::InlineCompletion { + id: Some(completion.id.to_string().into()), edits: edits[edit_start_ix..edit_end_ix].to_vec(), edit_preview: Some(completion.edit_preview.clone()), }) @@ -1598,7 +1601,7 @@ mod tests { edit_preview, path: Path::new("").into(), snapshot: cx.read(|cx| buffer.read(cx).snapshot()), - id: InlineCompletionId::new(), + id: InlineCompletionId(Uuid::new_v4()), excerpt_range: 0..0, cursor_offset: 0, input_outline: "".into(), @@ -1717,6 +1720,8 @@ mod tests { .status(200) .body( serde_json::to_string(&PredictEditsResponse { + request_id: Uuid::parse_str("7e86480f-3536-4d2c-9334-8213e3445d45") + .unwrap(), output_excerpt: completion_response.to_string(), }) .unwrap()