From 4d94c640f4412242312108e2ecf1f6630495679c Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Wed, 25 Mar 2026 09:23:05 -0500 Subject: [PATCH] Remove Sweep Integration (#52348) Closes #52115 ## Context Removes the third party edit prediction integration for Sweep AI ahead of their servers shutting down. This PR will not affect those who are already use or plan to use their open weighted models. The code removed by this PR was required for integrating with their proprietary API. ## 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 is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Removed support for using the Sweep AI edit prediction provider through their proprietary API, as the servers are shutting down https://discord.com/channels/1100625416022138902/1100625417272045639/1480644297903575142, https://x.com/wwzeng1/status/2033302698360180949 --- Cargo.lock | 37 - assets/icons/sweep_ai.svg | 1 - assets/icons/sweep_ai_disabled.svg | 1 - assets/icons/sweep_ai_down.svg | 1 - assets/icons/sweep_ai_error.svg | 1 - assets/icons/sweep_ai_up.svg | 1 - assets/settings/default.json | 7 - crates/agent_ui/src/agent_ui.rs | 1 - crates/edit_prediction/Cargo.toml | 1 - crates/edit_prediction/src/edit_prediction.rs | 134 +--- crates/edit_prediction/src/sweep_ai.rs | 669 ------------------ .../src/zed_edit_prediction_delegate.rs | 11 +- crates/edit_prediction_cli/src/main.rs | 5 +- crates/edit_prediction_cli/src/predict.rs | 1 - .../src/edit_prediction_button.rs | 25 +- crates/icons/src/icons.rs | 5 - crates/language/src/language_settings.rs | 16 - crates/settings_content/src/language.rs | 23 +- .../pages/edit_prediction_provider_setup.rs | 58 -- .../zed/src/zed/edit_prediction_registry.rs | 5 +- docs/src/ai/edit-prediction.md | 28 +- 21 files changed, 15 insertions(+), 1016 deletions(-) delete mode 100644 assets/icons/sweep_ai.svg delete mode 100644 assets/icons/sweep_ai_disabled.svg delete mode 100644 assets/icons/sweep_ai_down.svg delete mode 100644 assets/icons/sweep_ai_error.svg delete mode 100644 assets/icons/sweep_ai_up.svg delete mode 100644 crates/edit_prediction/src/sweep_ai.rs diff --git a/Cargo.lock b/Cargo.lock index 07a058a403..37cb42f56b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -511,21 +511,6 @@ dependencies = [ "equator", ] -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - [[package]] name = "allocator-api2" version = "0.2.21" @@ -2247,27 +2232,6 @@ dependencies = [ "workspace", ] -[[package]] -name = "brotli" -version = "8.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - [[package]] name = "brush-parser" version = "0.3.0" @@ -5244,7 +5208,6 @@ version = "0.1.0" dependencies = [ "ai_onboarding", "anyhow", - "brotli", "buffer_diff", "client", "clock", diff --git a/assets/icons/sweep_ai.svg b/assets/icons/sweep_ai.svg deleted file mode 100644 index 9c63c810dd..0000000000 --- a/assets/icons/sweep_ai.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/icons/sweep_ai_disabled.svg b/assets/icons/sweep_ai_disabled.svg deleted file mode 100644 index b15a8d8526..0000000000 --- a/assets/icons/sweep_ai_disabled.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/icons/sweep_ai_down.svg b/assets/icons/sweep_ai_down.svg deleted file mode 100644 index f08dcb1718..0000000000 --- a/assets/icons/sweep_ai_down.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/icons/sweep_ai_error.svg b/assets/icons/sweep_ai_error.svg deleted file mode 100644 index 95285a1273..0000000000 --- a/assets/icons/sweep_ai_error.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/icons/sweep_ai_up.svg b/assets/icons/sweep_ai_up.svg deleted file mode 100644 index 7c28282a6a..0000000000 --- a/assets/icons/sweep_ai_up.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/assets/settings/default.json b/assets/settings/default.json index d3fb32fd43..6a973314fc 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -1585,13 +1585,6 @@ "model": "codestral-latest", "max_tokens": 150, }, - "sweep": { - // When enabled, Sweep will not store edit prediction inputs or outputs. - // When disabled, Sweep may collect data including buffer contents, - // diagnostics, file paths, repository names, and generated predictions - // to improve the service. - "privacy_mode": false, - }, "ollama": { "api_url": "http://localhost:11434", "model": "qwen2.5-coder:7b-base", diff --git a/crates/agent_ui/src/agent_ui.rs b/crates/agent_ui/src/agent_ui.rs index 8f41944723..1817fdbe31 100644 --- a/crates/agent_ui/src/agent_ui.rs +++ b/crates/agent_ui/src/agent_ui.rs @@ -502,7 +502,6 @@ fn update_command_palette_filter(cx: &mut App) { | EditPredictionProvider::Codestral | EditPredictionProvider::Ollama | EditPredictionProvider::OpenAiCompatibleApi - | EditPredictionProvider::Sweep | EditPredictionProvider::Mercury | EditPredictionProvider::Experimental(_) => { filter.show_namespace("edit_prediction"); diff --git a/crates/edit_prediction/Cargo.toml b/crates/edit_prediction/Cargo.toml index a6a7d8777c..75a589dea8 100644 --- a/crates/edit_prediction/Cargo.toml +++ b/crates/edit_prediction/Cargo.toml @@ -18,7 +18,6 @@ cli-support = [] ai_onboarding.workspace = true anyhow.workspace = true heapless.workspace = true -brotli.workspace = true buffer_diff.workspace = true client.workspace = true clock.workspace = true diff --git a/crates/edit_prediction/src/edit_prediction.rs b/crates/edit_prediction/src/edit_prediction.rs index 421a51b055..3ae4eb72b3 100644 --- a/crates/edit_prediction/src/edit_prediction.rs +++ b/crates/edit_prediction/src/edit_prediction.rs @@ -50,7 +50,8 @@ use std::path::Path; use std::rc::Rc; use std::str::FromStr as _; use std::sync::Arc; -use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; +use std::time::{Duration, Instant}; + use thiserror::Error; use util::{RangeExt as _, ResultExt as _}; @@ -63,7 +64,6 @@ pub mod ollama; mod onboarding_modal; pub mod open_ai_response; mod prediction; -pub mod sweep_ai; pub mod udiff; @@ -83,7 +83,6 @@ use crate::onboarding_modal::ZedPredictModal; pub use crate::prediction::EditPrediction; pub use crate::prediction::EditPredictionId; use crate::prediction::EditPredictionResult; -pub use crate::sweep_ai::SweepAi; pub use capture_example::capture_example; pub use language_model::ApiKeyState; pub use telemetry_events::EditPredictionRating; @@ -143,7 +142,6 @@ pub struct EditPredictionStore { zeta2_raw_config: Option, preferred_experiment: Option, available_experiments: Vec, - pub sweep_ai: SweepAi, pub mercury: Mercury, data_collection_choice: DataCollectionChoice, reject_predictions_tx: mpsc::UnboundedSender, @@ -163,7 +161,6 @@ pub(crate) struct EditPredictionRejectionPayload { pub enum EditPredictionModel { Zeta, Fim { format: EditPredictionPromptFormat }, - Sweep, Mercury, } @@ -175,13 +172,11 @@ pub struct EditPredictionModelInput { position: Anchor, events: Vec>, related_files: Vec, - recent_paths: VecDeque, trigger: PredictEditsRequestTrigger, diagnostic_search_range: Range, debug_tx: Option>, can_collect_data: bool, is_open_source: bool, - pub user_actions: Vec, } #[derive(Debug)] @@ -220,26 +215,6 @@ pub struct EditPredictionFinishedDebugEvent { pub model_output: Option, } -const USER_ACTION_HISTORY_SIZE: usize = 16; - -#[derive(Clone, Debug)] -pub struct UserActionRecord { - pub action_type: UserActionType, - pub buffer_id: EntityId, - pub line_number: u32, - pub offset: usize, - pub timestamp_epoch_ms: u64, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum UserActionType { - InsertChar, - InsertSelection, - DeleteChar, - DeleteSelection, - CursorMovement, -} - /// An event with associated metadata for reconstructing buffer state. #[derive(Clone)] pub struct StoredEvent { @@ -339,19 +314,11 @@ struct ProjectState { cancelled_predictions: HashSet, context: Entity, license_detection_watchers: HashMap>, - user_actions: VecDeque, _subscriptions: [gpui::Subscription; 2], copilot: Option>, } impl ProjectState { - fn record_user_action(&mut self, action: UserActionRecord) { - if self.user_actions.len() >= USER_ACTION_HISTORY_SIZE { - self.user_actions.pop_front(); - } - self.user_actions.push_back(action); - } - pub fn events(&self, cx: &App) -> Vec { self.events .iter() @@ -828,7 +795,6 @@ impl EditPredictionStore { zeta2_raw_config: Self::zeta2_raw_config_from_env(), preferred_experiment: None, available_experiments: Vec::new(), - sweep_ai: SweepAi::new(cx), mercury: Mercury::new(cx), data_collection_choice, @@ -939,13 +905,6 @@ impl EditPredictionStore { pub fn icons(&self, cx: &App) -> edit_prediction_types::EditPredictionIconSet { use ui::IconName; match self.edit_prediction_model { - EditPredictionModel::Sweep => { - edit_prediction_types::EditPredictionIconSet::new(IconName::SweepAi) - .with_disabled(IconName::SweepAiDisabled) - .with_up(IconName::SweepAiUp) - .with_down(IconName::SweepAiDown) - .with_error(IconName::SweepAiError) - } EditPredictionModel::Mercury => { edit_prediction_types::EditPredictionIconSet::new(IconName::Inception) } @@ -970,10 +929,6 @@ impl EditPredictionStore { } } - pub fn has_sweep_api_token(&self, cx: &App) -> bool { - self.sweep_ai.api_token.read(cx).has_key() - } - pub fn has_mercury_api_token(&self, cx: &App) -> bool { self.mercury.api_token.read(cx).has_key() } @@ -1132,7 +1087,6 @@ impl EditPredictionStore { last_edit_prediction_refresh: None, last_jump_prediction_refresh: None, license_detection_watchers: HashMap::default(), - user_actions: VecDeque::with_capacity(USER_ACTION_HISTORY_SIZE), _subscriptions: [ cx.subscribe(&project, Self::handle_project_event), cx.observe_release(&project, move |this, _, cx| { @@ -1347,24 +1301,16 @@ impl EditPredictionStore { } let old_file = mem::replace(&mut registered_buffer.file, new_file.clone()); let old_snapshot = mem::replace(&mut registered_buffer.snapshot, new_snapshot.clone()); - let mut num_edits = 0usize; - let mut total_deleted = 0usize; - let mut total_inserted = 0usize; let mut edit_range: Option> = None; - let mut last_offset: Option = None; let now = cx.background_executor().now(); - for (edit, anchor_range) in + for (_edit, anchor_range) in new_snapshot.anchored_edits_since::(&old_snapshot.version) { - num_edits += 1; - total_deleted += edit.old.len(); - total_inserted += edit.new.len(); edit_range = Some(match edit_range { None => anchor_range, Some(acc) => acc.start..anchor_range.end, }); - last_offset = Some(edit.new.end); } let Some(edit_range) = edit_range else { @@ -1387,32 +1333,6 @@ impl EditPredictionStore { cx, ); - if is_local { - let action_type = match (total_deleted, total_inserted, num_edits) { - (0, ins, n) if ins == n => UserActionType::InsertChar, - (0, _, _) => UserActionType::InsertSelection, - (del, 0, n) if del == n => UserActionType::DeleteChar, - (_, 0, _) => UserActionType::DeleteSelection, - (_, ins, n) if ins == n => UserActionType::InsertChar, - (_, _, _) => UserActionType::InsertSelection, - }; - - if let Some(offset) = last_offset { - let point = new_snapshot.offset_to_point(offset); - let timestamp_epoch_ms = SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|d| d.as_millis() as u64) - .unwrap_or(0); - project_state.record_user_action(UserActionRecord { - action_type, - buffer_id: buffer.entity_id(), - line_number: point.row, - offset, - timestamp_epoch_ms, - }); - } - } - if !include_in_history { return; } @@ -1562,9 +1482,6 @@ impl EditPredictionStore { } match self.edit_prediction_model { - EditPredictionModel::Sweep => { - sweep_ai::edit_prediction_accepted(self, current_prediction, cx) - } EditPredictionModel::Mercury => { mercury::edit_prediction_accepted( current_prediction.prediction.id, @@ -1792,7 +1709,7 @@ impl EditPredictionStore { &mut self, project: &Entity, display_type: edit_prediction_types::SuggestionDisplayType, - cx: &mut Context, + _cx: &mut Context, ) { let Some(project_state) = self.projects.get_mut(&project.entity_id()) else { return; @@ -1815,18 +1732,6 @@ impl EditPredictionStore { current_prediction.was_shown = true; } - let display_type_changed = previous_shown_with != Some(display_type); - - if self.edit_prediction_model == EditPredictionModel::Sweep && display_type_changed { - sweep_ai::edit_prediction_shown( - &self.sweep_ai, - self.client.clone(), - ¤t_prediction.prediction, - display_type, - cx, - ); - } - if is_first_non_jump_show { self.shown_predictions .push_front(current_prediction.prediction.clone()); @@ -1883,7 +1788,7 @@ impl EditPredictionStore { cx, ); } - EditPredictionModel::Sweep | EditPredictionModel::Fim { .. } => {} + EditPredictionModel::Fim { .. } => {} } } @@ -2108,7 +2013,6 @@ fn currently_following(project: &Entity, cx: &App) -> bool { fn is_ep_store_provider(provider: EditPredictionProvider) -> bool { match provider { EditPredictionProvider::Zed - | EditPredictionProvider::Sweep | EditPredictionProvider::Mercury | EditPredictionProvider::Ollama | EditPredictionProvider::OpenAiCompatibleApi @@ -2148,7 +2052,6 @@ impl EditPredictionStore { let (needs_acceptance_tracking, max_pending_predictions) = match all_language_settings(None, cx).edit_predictions.provider { EditPredictionProvider::Zed - | EditPredictionProvider::Sweep | EditPredictionProvider::Mercury | EditPredictionProvider::Experimental(_) => (true, 2), EditPredictionProvider::Ollama => (false, 1), @@ -2370,28 +2273,6 @@ impl EditPredictionStore { let snapshot = active_buffer.read(cx).snapshot(); let cursor_point = position.to_point(&snapshot); - let current_offset = position.to_offset(&snapshot); - - let mut user_actions: Vec = - project_state.user_actions.iter().cloned().collect(); - - if let Some(last_action) = user_actions.last() { - if last_action.buffer_id == active_buffer.entity_id() - && current_offset != last_action.offset - { - let timestamp_epoch_ms = SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|d| d.as_millis() as u64) - .unwrap_or(0); - user_actions.push(UserActionRecord { - action_type: UserActionType::CursorMovement, - buffer_id: active_buffer.entity_id(), - line_number: cursor_point.row, - offset: current_offset, - timestamp_epoch_ms, - }); - } - } let diagnostic_search_start = cursor_point.row.saturating_sub(DIAGNOSTIC_LINES_RANGE); let diagnostic_search_end = cursor_point.row + DIAGNOSTIC_LINES_RANGE; let diagnostic_search_range = @@ -2410,8 +2291,6 @@ impl EditPredictionStore { && self.is_data_collection_enabled(cx) && matches!(self.edit_prediction_model, EditPredictionModel::Zeta); - let recent_paths = project_state.recent_paths.clone(); - let inputs = EditPredictionModelInput { project: project.clone(), buffer: active_buffer, @@ -2419,11 +2298,9 @@ impl EditPredictionStore { position, events, related_files, - recent_paths, trigger, diagnostic_search_range: diagnostic_search_range, debug_tx, - user_actions, can_collect_data, is_open_source, }; @@ -2435,7 +2312,6 @@ impl EditPredictionStore { zeta::request_prediction_with_zeta(self, inputs, capture_data, cx) } EditPredictionModel::Fim { format } => fim::request_prediction(inputs, format, cx), - EditPredictionModel::Sweep => self.sweep_ai.request_prediction_with_sweep(inputs, cx), EditPredictionModel::Mercury => self.mercury.request_prediction(inputs, cx), }; diff --git a/crates/edit_prediction/src/sweep_ai.rs b/crates/edit_prediction/src/sweep_ai.rs deleted file mode 100644 index 93a9a34340..0000000000 --- a/crates/edit_prediction/src/sweep_ai.rs +++ /dev/null @@ -1,669 +0,0 @@ -use crate::{ - CurrentEditPrediction, DebugEvent, EditPrediction, EditPredictionFinishedDebugEvent, - EditPredictionId, EditPredictionModelInput, EditPredictionStartedDebugEvent, - EditPredictionStore, UserActionRecord, UserActionType, prediction::EditPredictionResult, -}; -use anyhow::{Result, bail}; -use client::Client; -use edit_prediction_types::SuggestionDisplayType; -use futures::{AsyncReadExt as _, channel::mpsc}; -use gpui::{ - App, AppContext as _, Entity, Global, SharedString, Task, - http_client::{self, AsyncBody, Method}, -}; -use language::language_settings::all_language_settings; -use language::{Anchor, Buffer, BufferSnapshot, Point, ToOffset as _}; -use language_model::{ApiKeyState, EnvVar, env_var}; -use lsp::DiagnosticSeverity; -use serde::{Deserialize, Serialize}; -use std::{ - fmt::{self, Write as _}, - ops::Range, - path::Path, - sync::Arc, -}; - -const SWEEP_API_URL: &str = "https://autocomplete.sweep.dev/backend/next_edit_autocomplete"; -const SWEEP_METRICS_URL: &str = "https://backend.app.sweep.dev/backend/track_autocomplete_metrics"; - -pub struct SweepAi { - pub api_token: Entity, - pub debug_info: Arc, -} - -impl SweepAi { - pub fn new(cx: &mut App) -> Self { - SweepAi { - api_token: sweep_api_token(cx), - debug_info: debug_info(cx), - } - } - - pub fn request_prediction_with_sweep( - &self, - inputs: EditPredictionModelInput, - cx: &mut App, - ) -> Task>> { - let privacy_mode_enabled = all_language_settings(None, cx) - .edit_predictions - .sweep - .privacy_mode; - let debug_info = self.debug_info.clone(); - let request_start = cx.background_executor().now(); - self.api_token.update(cx, |key_state, cx| { - _ = key_state.load_if_needed(SWEEP_CREDENTIALS_URL, |s| s, cx); - }); - - let buffer = inputs.buffer.clone(); - let debug_tx = inputs.debug_tx.clone(); - - let Some(api_token) = self.api_token.read(cx).key(&SWEEP_CREDENTIALS_URL) else { - return Task::ready(Ok(None)); - }; - let full_path: Arc = inputs - .snapshot - .file() - .map(|file| file.full_path(cx)) - .unwrap_or_else(|| "untitled".into()) - .into(); - - let project_file = project::File::from_dyn(inputs.snapshot.file()); - let repo_name = project_file - .map(|file| file.worktree.read(cx).root_name_str()) - .unwrap_or("untitled") - .into(); - let offset = inputs.position.to_offset(&inputs.snapshot); - let buffer_entity_id = inputs.buffer.entity_id(); - - let recent_buffers = inputs.recent_paths.iter().cloned(); - let http_client = cx.http_client(); - - let recent_buffer_snapshots = recent_buffers - .filter_map(|project_path| { - let buffer = inputs.project.read(cx).get_open_buffer(&project_path, cx)?; - if inputs.buffer == buffer { - None - } else { - Some(buffer.read(cx).snapshot()) - } - }) - .take(3) - .collect::>(); - - let result = cx.background_spawn(async move { - let text = inputs.snapshot.text(); - - let mut recent_changes = String::new(); - for event in &inputs.events { - write_event(event.as_ref(), &mut recent_changes).unwrap(); - } - - let file_chunks = recent_buffer_snapshots - .into_iter() - .map(|snapshot| { - let end_point = Point::new(30, 0).min(snapshot.max_point()); - FileChunk { - content: snapshot.text_for_range(Point::zero()..end_point).collect(), - file_path: snapshot - .file() - .map(|f| f.path().as_unix_str()) - .unwrap_or("untitled") - .to_string(), - start_line: 0, - end_line: end_point.row as usize, - timestamp: snapshot.file().and_then(|file| { - Some( - file.disk_state() - .mtime()? - .to_seconds_and_nanos_for_persistence()? - .0, - ) - }), - } - }) - .collect::>(); - - let mut retrieval_chunks: Vec = inputs - .related_files - .iter() - .flat_map(|related_file| { - related_file.excerpts.iter().map(|excerpt| FileChunk { - file_path: related_file.path.to_string_lossy().to_string(), - start_line: excerpt.row_range.start as usize, - end_line: excerpt.row_range.end as usize, - content: excerpt.text.to_string(), - timestamp: None, - }) - }) - .collect(); - - let diagnostic_entries = inputs - .snapshot - .diagnostics_in_range(inputs.diagnostic_search_range, false); - let mut diagnostic_content = String::new(); - let mut diagnostic_count = 0; - - for entry in diagnostic_entries { - let start_point: Point = entry.range.start; - - let severity = match entry.diagnostic.severity { - DiagnosticSeverity::ERROR => "error", - DiagnosticSeverity::WARNING => "warning", - DiagnosticSeverity::INFORMATION => "info", - DiagnosticSeverity::HINT => "hint", - _ => continue, - }; - - diagnostic_count += 1; - - writeln!( - &mut diagnostic_content, - "{}:{}:{}: {}: {}", - full_path.display(), - start_point.row + 1, - start_point.column + 1, - severity, - entry.diagnostic.message - )?; - } - - if !diagnostic_content.is_empty() { - retrieval_chunks.push(FileChunk { - file_path: "diagnostics".to_string(), - start_line: 1, - end_line: diagnostic_count, - content: diagnostic_content, - timestamp: None, - }); - } - - let file_path_str = full_path.display().to_string(); - let recent_user_actions = inputs - .user_actions - .iter() - .filter(|r| r.buffer_id == buffer_entity_id) - .map(|r| to_sweep_user_action(r, &file_path_str)) - .collect(); - - let request_body = AutocompleteRequest { - debug_info, - repo_name, - file_path: full_path.clone(), - file_contents: text.clone(), - original_file_contents: text, - cursor_position: offset, - recent_changes: recent_changes.clone(), - changes_above_cursor: true, - multiple_suggestions: false, - branch: None, - file_chunks, - retrieval_chunks, - recent_user_actions, - use_bytes: true, - privacy_mode_enabled, - }; - - let mut buf: Vec = Vec::new(); - let writer = brotli::CompressorWriter::new(&mut buf, 4096, 1, 22); - serde_json::to_writer(writer, &request_body)?; - let body: AsyncBody = buf.into(); - - let ep_inputs = zeta_prompt::ZetaPromptInput { - events: inputs.events, - related_files: Some(inputs.related_files.clone()), - active_buffer_diagnostics: vec![], - cursor_path: full_path.clone(), - cursor_excerpt: request_body.file_contents.clone().into(), - cursor_offset_in_excerpt: request_body.cursor_position, - excerpt_start_row: Some(0), - excerpt_ranges: zeta_prompt::ExcerptRanges { - editable_150: 0..inputs.snapshot.len(), - editable_180: 0..inputs.snapshot.len(), - editable_350: 0..inputs.snapshot.len(), - editable_150_context_350: 0..inputs.snapshot.len(), - editable_180_context_350: 0..inputs.snapshot.len(), - editable_350_context_150: 0..inputs.snapshot.len(), - ..Default::default() - }, - syntax_ranges: None, - experiment: None, - in_open_source_repo: false, - can_collect_data: false, - repo_url: None, - }; - - send_started_event( - &debug_tx, - &buffer, - inputs.position, - serde_json::to_string(&request_body).unwrap_or_default(), - ); - - let request = http_client::Request::builder() - .uri(SWEEP_API_URL) - .header("Content-Type", "application/json") - .header("Authorization", format!("Bearer {}", api_token)) - .header("Connection", "keep-alive") - .header("Content-Encoding", "br") - .method(Method::POST) - .body(body)?; - - let mut response = http_client.send(request).await?; - - let mut body = String::new(); - response.body_mut().read_to_string(&mut body).await?; - - if !response.status().is_success() { - let message = format!( - "Request failed with status: {:?}\nBody: {}", - response.status(), - body, - ); - send_finished_event(&debug_tx, &buffer, inputs.position, message.clone()); - bail!(message); - }; - - let response: AutocompleteResponse = serde_json::from_str(&body)?; - - send_finished_event(&debug_tx, &buffer, inputs.position, body); - - let old_text = inputs - .snapshot - .text_for_range(response.start_index..response.end_index) - .collect::(); - let edits = language::text_diff(&old_text, &response.completion) - .into_iter() - .map(|(range, text)| { - ( - inputs - .snapshot - .anchor_after(response.start_index + range.start) - ..inputs - .snapshot - .anchor_before(response.start_index + range.end), - text, - ) - }) - .collect::>(); - - anyhow::Ok((response.autocomplete_id, edits, inputs.snapshot, ep_inputs)) - }); - - let buffer = inputs.buffer.clone(); - - cx.spawn(async move |cx| { - let (id, edits, old_snapshot, inputs) = result.await?; - anyhow::Ok(Some( - EditPredictionResult::new( - EditPredictionId(id.into()), - &buffer, - &old_snapshot, - edits.into(), - None, - inputs, - None, - cx.background_executor().now() - request_start, - cx, - ) - .await, - )) - }) - } -} - -fn send_started_event( - debug_tx: &Option>, - buffer: &Entity, - position: Anchor, - prompt: String, -) { - if let Some(debug_tx) = debug_tx { - _ = debug_tx.unbounded_send(DebugEvent::EditPredictionStarted( - EditPredictionStartedDebugEvent { - buffer: buffer.downgrade(), - position, - prompt: Some(prompt), - }, - )); - } -} - -fn send_finished_event( - debug_tx: &Option>, - buffer: &Entity, - position: Anchor, - model_output: String, -) { - if let Some(debug_tx) = debug_tx { - _ = debug_tx.unbounded_send(DebugEvent::EditPredictionFinished( - EditPredictionFinishedDebugEvent { - buffer: buffer.downgrade(), - position, - model_output: Some(model_output), - }, - )); - } -} - -pub const SWEEP_CREDENTIALS_URL: SharedString = - SharedString::new_static("https://autocomplete.sweep.dev"); -pub const SWEEP_CREDENTIALS_USERNAME: &str = "sweep-api-token"; -pub static SWEEP_AI_TOKEN_ENV_VAR: std::sync::LazyLock = env_var!("SWEEP_AI_TOKEN"); - -struct GlobalSweepApiKey(Entity); - -impl Global for GlobalSweepApiKey {} - -pub fn sweep_api_token(cx: &mut App) -> Entity { - if let Some(global) = cx.try_global::() { - return global.0.clone(); - } - let entity = - cx.new(|_| ApiKeyState::new(SWEEP_CREDENTIALS_URL, SWEEP_AI_TOKEN_ENV_VAR.clone())); - cx.set_global(GlobalSweepApiKey(entity.clone())); - entity -} - -pub fn load_sweep_api_token(cx: &mut App) -> Task> { - sweep_api_token(cx).update(cx, |key_state, cx| { - key_state.load_if_needed(SWEEP_CREDENTIALS_URL, |s| s, cx) - }) -} - -#[derive(Debug, Clone, Serialize)] -struct AutocompleteRequest { - pub debug_info: Arc, - pub repo_name: String, - pub branch: Option, - pub file_path: Arc, - pub file_contents: String, - pub recent_changes: String, - pub cursor_position: usize, - pub original_file_contents: String, - pub file_chunks: Vec, - pub retrieval_chunks: Vec, - pub recent_user_actions: Vec, - pub multiple_suggestions: bool, - pub privacy_mode_enabled: bool, - pub changes_above_cursor: bool, - pub use_bytes: bool, -} - -#[derive(Debug, Clone, Serialize)] -struct FileChunk { - pub file_path: String, - pub start_line: usize, - pub end_line: usize, - pub content: String, - pub timestamp: Option, -} - -#[derive(Debug, Clone, Serialize)] -struct UserAction { - pub action_type: ActionType, - pub line_number: usize, - pub offset: usize, - pub file_path: String, - pub timestamp: u64, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] -#[serde(rename_all = "SCREAMING_SNAKE_CASE")] -enum ActionType { - CursorMovement, - InsertChar, - DeleteChar, - InsertSelection, - DeleteSelection, -} - -fn to_sweep_user_action(record: &UserActionRecord, file_path: &str) -> UserAction { - UserAction { - action_type: match record.action_type { - UserActionType::InsertChar => ActionType::InsertChar, - UserActionType::InsertSelection => ActionType::InsertSelection, - UserActionType::DeleteChar => ActionType::DeleteChar, - UserActionType::DeleteSelection => ActionType::DeleteSelection, - UserActionType::CursorMovement => ActionType::CursorMovement, - }, - line_number: record.line_number as usize, - offset: record.offset, - file_path: file_path.to_string(), - timestamp: record.timestamp_epoch_ms, - } -} - -#[derive(Debug, Clone, Deserialize)] -struct AutocompleteResponse { - pub autocomplete_id: String, - pub start_index: usize, - pub end_index: usize, - pub completion: String, - #[allow(dead_code)] - pub confidence: f64, - #[allow(dead_code)] - pub logprobs: Option, - #[allow(dead_code)] - pub finish_reason: Option, - #[allow(dead_code)] - pub elapsed_time_ms: u64, - #[allow(dead_code)] - #[serde(default, rename = "completions")] - pub additional_completions: Vec, -} - -#[allow(dead_code)] -#[derive(Debug, Clone, Deserialize)] -struct AdditionalCompletion { - pub start_index: usize, - pub end_index: usize, - pub completion: String, - pub confidence: f64, - pub autocomplete_id: String, - pub logprobs: Option, - pub finish_reason: Option, -} - -fn write_event(event: &zeta_prompt::Event, f: &mut impl fmt::Write) -> fmt::Result { - match event { - zeta_prompt::Event::BufferChange { - old_path, - path, - diff, - .. - } => { - if old_path != path { - // TODO confirm how to do this for sweep - // writeln!(f, "User renamed {:?} to {:?}\n", old_path, new_path)?; - } - - if !diff.is_empty() { - write!(f, "File: {}:\n{}\n", path.display(), diff)? - } - - fmt::Result::Ok(()) - } - } -} - -fn debug_info(cx: &gpui::App) -> Arc { - format!( - "Zed v{version} ({sha}) - OS: {os} - Zed v{version}", - version = release_channel::AppVersion::global(cx), - sha = release_channel::AppCommitSha::try_global(cx) - .map_or("unknown".to_string(), |sha| sha.full()), - os = client::telemetry::os_name(), - ) - .into() -} - -#[derive(Debug, Clone, Copy, Serialize)] -#[serde(rename_all = "snake_case")] -pub enum SweepEventType { - AutocompleteSuggestionShown, - AutocompleteSuggestionAccepted, -} - -#[derive(Debug, Clone, Copy, Serialize)] -#[serde(rename_all = "SCREAMING_SNAKE_CASE")] -pub enum SweepSuggestionType { - GhostText, - Popup, - JumpToEdit, -} - -#[derive(Debug, Clone, Serialize)] -struct AutocompleteMetricsRequest { - event_type: SweepEventType, - suggestion_type: SweepSuggestionType, - additions: u32, - deletions: u32, - autocomplete_id: String, - edit_tracking: String, - edit_tracking_line: Option, - lifespan: Option, - debug_info: Arc, - device_id: String, - privacy_mode_enabled: bool, -} - -fn send_autocomplete_metrics_request( - cx: &App, - client: Arc, - api_token: Arc, - request_body: AutocompleteMetricsRequest, -) { - let http_client = client.http_client(); - cx.background_spawn(async move { - let body: AsyncBody = serde_json::to_string(&request_body)?.into(); - - let request = http_client::Request::builder() - .uri(SWEEP_METRICS_URL) - .header("Content-Type", "application/json") - .header("Authorization", format!("Bearer {}", api_token)) - .method(Method::POST) - .body(body)?; - - let mut response = http_client.send(request).await?; - - if !response.status().is_success() { - let mut body = String::new(); - response.body_mut().read_to_string(&mut body).await?; - anyhow::bail!( - "Failed to send autocomplete metrics for sweep_ai: {:?}\nBody: {}", - response.status(), - body, - ); - } - - Ok(()) - }) - .detach_and_log_err(cx); -} - -pub(crate) fn edit_prediction_accepted( - store: &EditPredictionStore, - current_prediction: CurrentEditPrediction, - cx: &App, -) { - let Some(api_token) = store - .sweep_ai - .api_token - .read(cx) - .key(&SWEEP_CREDENTIALS_URL) - else { - return; - }; - let debug_info = store.sweep_ai.debug_info.clone(); - - let prediction = current_prediction.prediction; - - let (additions, deletions) = compute_edit_metrics(&prediction.edits, &prediction.snapshot); - let autocomplete_id = prediction.id.to_string(); - - let device_id = store - .client - .user_id() - .as_ref() - .map(ToString::to_string) - .unwrap_or_default(); - - let suggestion_type = match current_prediction.shown_with { - Some(SuggestionDisplayType::DiffPopover) => SweepSuggestionType::Popup, - Some(SuggestionDisplayType::Jump) => return, // should'nt happen - Some(SuggestionDisplayType::GhostText) | None => SweepSuggestionType::GhostText, - }; - - let request_body = AutocompleteMetricsRequest { - event_type: SweepEventType::AutocompleteSuggestionAccepted, - suggestion_type, - additions, - deletions, - autocomplete_id, - edit_tracking: String::new(), - edit_tracking_line: None, - lifespan: None, - debug_info, - device_id, - privacy_mode_enabled: false, - }; - - send_autocomplete_metrics_request(cx, store.client.clone(), api_token, request_body); -} - -pub fn edit_prediction_shown( - sweep_ai: &SweepAi, - client: Arc, - prediction: &EditPrediction, - display_type: SuggestionDisplayType, - cx: &App, -) { - let Some(api_token) = sweep_ai.api_token.read(cx).key(&SWEEP_CREDENTIALS_URL) else { - return; - }; - let debug_info = sweep_ai.debug_info.clone(); - - let (additions, deletions) = compute_edit_metrics(&prediction.edits, &prediction.snapshot); - let autocomplete_id = prediction.id.to_string(); - - let suggestion_type = match display_type { - SuggestionDisplayType::GhostText => SweepSuggestionType::GhostText, - SuggestionDisplayType::DiffPopover => SweepSuggestionType::Popup, - SuggestionDisplayType::Jump => SweepSuggestionType::JumpToEdit, - }; - - let request_body = AutocompleteMetricsRequest { - event_type: SweepEventType::AutocompleteSuggestionShown, - suggestion_type, - additions, - deletions, - autocomplete_id, - edit_tracking: String::new(), - edit_tracking_line: None, - lifespan: None, - debug_info, - device_id: String::new(), - privacy_mode_enabled: false, - }; - - send_autocomplete_metrics_request(cx, client, api_token, request_body); -} - -fn compute_edit_metrics( - edits: &[(Range, Arc)], - snapshot: &BufferSnapshot, -) -> (u32, u32) { - let mut additions = 0u32; - let mut deletions = 0u32; - - for (range, new_text) in edits { - let old_text = snapshot.text_for_range(range.clone()); - deletions += old_text - .map(|chunk| chunk.lines().count()) - .sum::() - .max(1) as u32; - additions += new_text.lines().count().max(1) as u32; - } - - (additions, deletions) -} diff --git a/crates/edit_prediction/src/zed_edit_prediction_delegate.rs b/crates/edit_prediction/src/zed_edit_prediction_delegate.rs index b5ae954e84..c5e97fd87e 100644 --- a/crates/edit_prediction/src/zed_edit_prediction_delegate.rs +++ b/crates/edit_prediction/src/zed_edit_prediction_delegate.rs @@ -10,7 +10,7 @@ use gpui::{App, Entity, prelude::*}; use language::{Buffer, ToPoint as _}; use project::Project; -use crate::{BufferEditPrediction, EditPredictionModel, EditPredictionStore}; +use crate::{BufferEditPrediction, EditPredictionStore}; pub struct ZedEditPredictionDelegate { store: Entity, @@ -103,14 +103,9 @@ impl EditPredictionDelegate for ZedEditPredictionDelegate { &self, _buffer: &Entity, _cursor_position: language::Anchor, - cx: &App, + _cx: &App, ) -> bool { - let store = self.store.read(cx); - if store.edit_prediction_model == EditPredictionModel::Sweep { - store.has_sweep_api_token(cx) - } else { - true - } + true } fn is_refreshing(&self, cx: &App) -> bool { diff --git a/crates/edit_prediction_cli/src/main.rs b/crates/edit_prediction_cli/src/main.rs index 06fdbadbf5..cf9232a04a 100644 --- a/crates/edit_prediction_cli/src/main.rs +++ b/crates/edit_prediction_cli/src/main.rs @@ -358,7 +358,6 @@ impl TeacherBackend { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] enum PredictionProvider { - Sweep, Mercury, Zeta1, Zeta2(ZetaFormat), @@ -379,7 +378,6 @@ impl Default for PredictionProvider { impl std::fmt::Display for PredictionProvider { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - PredictionProvider::Sweep => write!(f, "sweep"), PredictionProvider::Mercury => write!(f, "mercury"), PredictionProvider::Zeta1 => write!(f, "zeta1"), PredictionProvider::Zeta2(format) => write!(f, "zeta2:{format}"), @@ -407,7 +405,6 @@ impl std::str::FromStr for PredictionProvider { let provider_lower = provider.to_lowercase(); match provider_lower.as_str() { - "sweep" => Ok(PredictionProvider::Sweep), "mercury" => Ok(PredictionProvider::Mercury), "zeta1" => Ok(PredictionProvider::Zeta1), "zeta2" => { @@ -452,7 +449,7 @@ impl std::str::FromStr for PredictionProvider { } _ => { anyhow::bail!( - "unknown provider `{provider}`. Valid options: sweep, mercury, zeta1, zeta2, zeta2:, teacher, teacher:, teacher-multi-region, teacher-multi-region:, teacher-non-batching, teacher-multi-region-non-batching, repair\n\ + "unknown provider `{provider}`. Valid options: mercury, zeta1, zeta2, zeta2:, teacher, teacher:, teacher-multi-region, teacher-multi-region:, teacher-non-batching, teacher-multi-region-non-batching, repair\n\ For zeta2, you can optionally specify a version like `zeta2:ordered` or `zeta2:V0113_Ordered`.\n\ For teacher providers, you can specify a backend like `teacher:sonnet46`, `teacher-multi-region:sonnet46`, `teacher-multi-region-non-batching:sonnet46`, or `teacher:gpt52`.\n\ Available zeta versions:\n{}", diff --git a/crates/edit_prediction_cli/src/predict.rs b/crates/edit_prediction_cli/src/predict.rs index 1effca9d21..f2a55455b3 100644 --- a/crates/edit_prediction_cli/src/predict.rs +++ b/crates/edit_prediction_cli/src/predict.rs @@ -137,7 +137,6 @@ pub async fn run_prediction( let model = match provider { PredictionProvider::Zeta1 => edit_prediction::EditPredictionModel::Zeta, PredictionProvider::Zeta2(_) => edit_prediction::EditPredictionModel::Zeta, - PredictionProvider::Sweep => edit_prediction::EditPredictionModel::Sweep, PredictionProvider::Mercury => edit_prediction::EditPredictionModel::Mercury, PredictionProvider::Teacher(..) | PredictionProvider::TeacherMultiRegion(..) diff --git a/crates/edit_prediction_ui/src/edit_prediction_button.rs b/crates/edit_prediction_ui/src/edit_prediction_button.rs index d85ccded26..e6e6501212 100644 --- a/crates/edit_prediction_ui/src/edit_prediction_button.rs +++ b/crates/edit_prediction_ui/src/edit_prediction_button.rs @@ -325,7 +325,6 @@ impl Render for EditPredictionButton { } provider @ (EditPredictionProvider::Experimental(_) | EditPredictionProvider::Zed - | EditPredictionProvider::Sweep | EditPredictionProvider::Mercury) => { let enabled = self.editor_enabled.unwrap_or(true); let file = self.file.clone(); @@ -349,16 +348,6 @@ impl Render for EditPredictionButton { let mut missing_token = false; match provider { - EditPredictionProvider::Sweep => { - missing_token = edit_prediction::EditPredictionStore::try_global(cx) - .is_some_and(|ep_store| !ep_store.read(cx).has_sweep_api_token(cx)); - ep_icon = if enabled { icons.base } else { icons.disabled }; - tooltip_meta = if missing_token { - "Missing API key for Sweep" - } else { - "Powered by Sweep" - }; - } EditPredictionProvider::Mercury => { ep_icon = if enabled { icons.base } else { icons.disabled }; let mercury_has_error = @@ -548,17 +537,12 @@ impl EditPredictionButton { .detach(); edit_prediction::ollama::ensure_authenticated(cx); - let sweep_api_token_task = edit_prediction::sweep_ai::load_sweep_api_token(cx); let mercury_api_token_task = edit_prediction::mercury::load_mercury_api_token(cx); let open_ai_compatible_api_token_task = edit_prediction::open_ai_compatible::load_open_ai_compatible_api_token(cx); cx.spawn(async move |this, cx| { - _ = futures::join!( - sweep_api_token_task, - mercury_api_token_task, - open_ai_compatible_api_token_task - ); + _ = futures::join!(mercury_api_token_task, open_ai_compatible_api_token_task); this.update(cx, |_, cx| { cx.notify(); }) @@ -1457,13 +1441,6 @@ pub fn get_available_providers(cx: &mut App) -> Vec { providers.push(EditPredictionProvider::OpenAiCompatibleApi); } - if edit_prediction::sweep_ai::sweep_api_token(cx) - .read(cx) - .has_key() - { - providers.push(EditPredictionProvider::Sweep); - } - if edit_prediction::mercury::mercury_api_token(cx) .read(cx) .has_key() diff --git a/crates/icons/src/icons.rs b/crates/icons/src/icons.rs index 625b51f9c1..c8bf3b4e77 100644 --- a/crates/icons/src/icons.rs +++ b/crates/icons/src/icons.rs @@ -233,11 +233,6 @@ pub enum IconName { Star, StarFilled, Stop, - SweepAi, - SweepAiDisabled, - SweepAiDown, - SweepAiError, - SweepAiUp, Tab, Terminal, TerminalAlt, diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index 5f74247ab0..1e7910fa54 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -469,8 +469,6 @@ pub struct EditPredictionSettings { pub copilot: CopilotSettings, /// Settings specific to Codestral. pub codestral: CodestralSettings, - /// Settings specific to Sweep. - pub sweep: SweepSettings, /// Settings specific to Ollama. pub ollama: Option, pub open_ai_compatible_api: Option, @@ -522,15 +520,6 @@ pub struct CodestralSettings { pub api_url: Option, } -#[derive(Clone, Debug, Default)] -pub struct SweepSettings { - /// When enabled, Sweep will not store edit prediction inputs or outputs. - /// When disabled, Sweep may collect data including buffer contents, - /// diagnostics, file paths, repository names, and generated predictions - /// to improve the service. - pub privacy_mode: bool, -} - #[derive(Clone, Debug, Default)] pub struct OpenAiCompatibleEditPredictionSettings { /// Model to use for completions. @@ -805,10 +794,6 @@ impl settings::Settings for AllLanguageSettings { api_url: codestral.api_url, }; - let sweep = edit_predictions.sweep.unwrap(); - let sweep_settings = SweepSettings { - privacy_mode: sweep.privacy_mode.unwrap(), - }; let ollama = edit_predictions.ollama.unwrap(); let ollama_settings = ollama .model @@ -872,7 +857,6 @@ impl settings::Settings for AllLanguageSettings { mode: edit_predictions_mode, copilot: copilot_settings, codestral: codestral_settings, - sweep: sweep_settings, ollama: ollama_settings, open_ai_compatible_api: openai_compatible_settings, enabled_in_text_threads, diff --git a/crates/settings_content/src/language.rs b/crates/settings_content/src/language.rs index 30a1e7a317..4578d2eb58 100644 --- a/crates/settings_content/src/language.rs +++ b/crates/settings_content/src/language.rs @@ -85,7 +85,6 @@ pub enum EditPredictionProvider { Codestral, Ollama, OpenAiCompatibleApi, - Sweep, Mercury, Experimental(&'static str), } @@ -106,7 +105,6 @@ impl<'de> Deserialize<'de> for EditPredictionProvider { Codestral, Ollama, OpenAiCompatibleApi, - Sweep, Mercury, Experimental(String), } @@ -118,7 +116,6 @@ impl<'de> Deserialize<'de> for EditPredictionProvider { Content::Codestral => EditPredictionProvider::Codestral, Content::Ollama => EditPredictionProvider::Ollama, Content::OpenAiCompatibleApi => EditPredictionProvider::OpenAiCompatibleApi, - Content::Sweep => EditPredictionProvider::Sweep, Content::Mercury => EditPredictionProvider::Mercury, Content::Experimental(name) if name == EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME => @@ -144,7 +141,6 @@ impl EditPredictionProvider { | EditPredictionProvider::Codestral | EditPredictionProvider::Ollama | EditPredictionProvider::OpenAiCompatibleApi - | EditPredictionProvider::Sweep | EditPredictionProvider::Mercury | EditPredictionProvider::Experimental(_) => false, } @@ -155,7 +151,6 @@ impl EditPredictionProvider { EditPredictionProvider::Zed => Some("Zed AI"), EditPredictionProvider::Copilot => Some("GitHub Copilot"), EditPredictionProvider::Codestral => Some("Codestral"), - EditPredictionProvider::Sweep => Some("Sweep"), EditPredictionProvider::Mercury => Some("Mercury"), EditPredictionProvider::Experimental(_) | EditPredictionProvider::None => None, EditPredictionProvider::Ollama => Some("Ollama"), @@ -181,8 +176,6 @@ pub struct EditPredictionSettingsContent { pub copilot: Option, /// Settings specific to Codestral. pub codestral: Option, - /// Settings specific to Sweep. - pub sweep: Option, /// Settings specific to Ollama. pub ollama: Option, /// Settings specific to using custom OpenAI-compatible servers for edit prediction. @@ -209,8 +202,7 @@ pub struct CustomEditPredictionProviderSettingsContent { /// /// Default: "" pub model: Option, - /// Maximum tokens to generate for FIM models. - /// This setting does not apply to sweep models. + /// Maximum tokens to generate. /// /// Default: 256 pub max_output_tokens: Option, @@ -283,18 +275,6 @@ pub struct CodestralSettingsContent { pub api_url: Option, } -#[with_fallible_options] -#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)] -pub struct SweepSettingsContent { - /// When enabled, Sweep will not store edit prediction inputs or outputs. - /// When disabled, Sweep may collect data including buffer contents, - /// diagnostics, file paths, repository names, and generated predictions - /// to improve the service. - /// - /// Default: false - pub privacy_mode: Option, -} - /// Ollama model name for edit predictions. #[with_fallible_options] #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)] @@ -327,7 +307,6 @@ pub struct OllamaEditPredictionSettingsContent { /// Default: none pub model: Option, /// Maximum tokens to generate for FIM models. - /// This setting does not apply to sweep models. /// /// Default: 256 pub max_output_tokens: Option, diff --git a/crates/settings_ui/src/pages/edit_prediction_provider_setup.rs b/crates/settings_ui/src/pages/edit_prediction_provider_setup.rs index 736a8e83e3..0357f2040b 100644 --- a/crates/settings_ui/src/pages/edit_prediction_provider_setup.rs +++ b/crates/settings_ui/src/pages/edit_prediction_provider_setup.rs @@ -3,7 +3,6 @@ use edit_prediction::{ ApiKeyState, mercury::{MERCURY_CREDENTIALS_URL, mercury_api_token}, open_ai_compatible::{open_ai_compatible_api_token, open_ai_compatible_api_url}, - sweep_ai::{SWEEP_CREDENTIALS_URL, sweep_api_token}, }; use edit_prediction_ui::{get_available_providers, set_completion_provider}; use gpui::{Entity, ScrollHandle, prelude::*}; @@ -45,30 +44,6 @@ pub(crate) fn render_edit_prediction_setup_page( ) .into_any_element(), ), - Some( - render_api_key_provider( - IconName::SweepAi, - "Sweep", - ApiKeyDocs::Link { - dashboard_url: "https://app.sweep.dev/".into(), - }, - sweep_api_token(cx), - |_cx| SWEEP_CREDENTIALS_URL, - Some( - settings_window - .render_sub_page_items_section( - sweep_settings().iter().enumerate(), - true, - window, - cx, - ) - .into_any_element(), - ), - window, - cx, - ) - .into_any_element(), - ), Some( render_api_key_provider( IconName::AiMistral, @@ -345,39 +320,6 @@ fn render_api_key_provider( }) } -fn sweep_settings() -> Box<[SettingsPageItem]> { - Box::new([SettingsPageItem::SettingItem(SettingItem { - title: "Privacy Mode", - description: "When enabled, Sweep will not store edit prediction inputs or outputs. When disabled, Sweep may collect data including buffer contents, diagnostics, file paths, and generated predictions to improve the service.", - field: Box::new(SettingField { - pick: |settings| { - settings - .project - .all_languages - .edit_predictions - .as_ref()? - .sweep - .as_ref()? - .privacy_mode - .as_ref() - }, - write: |settings, value| { - settings - .project - .all_languages - .edit_predictions - .get_or_insert_default() - .sweep - .get_or_insert_default() - .privacy_mode = value; - }, - json_path: Some("edit_predictions.sweep.privacy_mode"), - }), - metadata: None, - files: USER, - })]) -} - fn render_ollama_provider( settings_window: &SettingsWindow, window: &mut Window, diff --git a/crates/zed/src/zed/edit_prediction_registry.rs b/crates/zed/src/zed/edit_prediction_registry.rs index 952c840d4a..8c9e74a42e 100644 --- a/crates/zed/src/zed/edit_prediction_registry.rs +++ b/crates/zed/src/zed/edit_prediction_registry.rs @@ -141,9 +141,7 @@ fn edit_prediction_provider_config_for_settings(cx: &App) -> Option Some(EditPredictionProviderConfig::Zed( - EditPredictionModel::Sweep, - )), + EditPredictionProvider::Mercury => Some(EditPredictionProviderConfig::Zed( EditPredictionModel::Mercury, )), @@ -183,7 +181,6 @@ impl EditPredictionProviderConfig { EditPredictionProviderConfig::Zed(model) => match model { EditPredictionModel::Zeta => "Zeta", EditPredictionModel::Fim { .. } => "FIM", - EditPredictionModel::Sweep => "Sweep", EditPredictionModel::Mercury => "Mercury", }, } diff --git a/docs/src/ai/edit-prediction.md b/docs/src/ai/edit-prediction.md index 92fde3eddd..5c0bae7f93 100644 --- a/docs/src/ai/edit-prediction.md +++ b/docs/src/ai/edit-prediction.md @@ -1,6 +1,6 @@ --- -title: AI Code Completion in Zed - Zeta, Copilot, Sweep, Mercury Coder -description: Set up AI code completions in Zed with Zeta (built-in), GitHub Copilot, Sweep, Codestral, or Mercury Coder. Multi-line predictions on every keystroke. +title: AI Code Completion in Zed - Zeta, Copilot, Codestral, Mercury Coder +description: Set up AI code completions in Zed with Zeta (built-in), GitHub Copilot, Codestral, or Mercury Coder. Multi-line predictions on every keystroke. --- # Edit Prediction @@ -8,7 +8,7 @@ description: Set up AI code completions in Zed with Zeta (built-in), GitHub Copi Edit Prediction is how Zed's AI code completions work: an LLM predicts the code you want to write. Each keystroke sends a new request to the edit prediction provider, which returns individual or multi-line suggestions that can be quickly accepted by pressing `tab`. -The default provider is [Zeta, a proprietary open source and open dataset model](https://huggingface.co/zed-industries/zeta), but you can also use [other providers](#other-providers) like GitHub Copilot, Sweep, Mercury Coder, and Codestral. +The default provider is [Zeta, a proprietary open source and open dataset model](https://huggingface.co/zed-industries/zeta), but you can also use [other providers](#other-providers) like GitHub Copilot, Mercury Coder, and Codestral. ## Configuring Zeta @@ -338,28 +338,6 @@ Copilot can provide multiple completion alternatives, and these can be navigated - {#action editor::NextEditPrediction} ({#kb editor::NextEditPrediction}): To cycle to the next edit prediction - {#action editor::PreviousEditPrediction} ({#kb editor::PreviousEditPrediction}): To cycle to the previous edit prediction -### Sweep {#sweep} - -To use [Sweep](https://sweep.dev/) as your provider: - -1. Open the Settings Editor (`Cmd+,` on macOS, `Ctrl+,` on Linux/Windows) -2. Search for "Edit Predictions" and click **Configure Providers** -3. Find the Sweep section and enter your API key from the - [Sweep dashboard](https://app.sweep.dev/) - -Alternatively, click the edit prediction icon in the status bar and select -**Configure Providers** from the menu. - -After adding your API key, Sweep will appear in the provider dropdown in the status bar menu, where you can select it. You can also set it directly in your settings file: - -```json [settings] -{ - "edit_predictions": { - "provider": "sweep" - } -} -``` - ### Mercury Coder {#mercury-coder} To use [Mercury Coder](https://www.inceptionlabs.ai/) by Inception Labs as your provider: