Detailed changes
@@ -401,6 +401,8 @@ fn update_command_palette_filter(cx: &mut App) {
}
EditPredictionProvider::Zed
| EditPredictionProvider::Codestral
+ | EditPredictionProvider::Sweep
+ | EditPredictionProvider::Mercury
| EditPredictionProvider::Experimental(_) => {
filter.show_namespace("edit_prediction");
filter.hide_namespace("copilot");
@@ -25,10 +25,7 @@ use language::{
use project::{DisableAiSettings, Project};
use regex::Regex;
use settings::{
- EXPERIMENTAL_MERCURY_EDIT_PREDICTION_PROVIDER_NAME,
- EXPERIMENTAL_SWEEP_EDIT_PREDICTION_PROVIDER_NAME,
- EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME, Settings, SettingsStore,
- update_settings_file,
+ EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME, Settings, SettingsStore, update_settings_file,
};
use std::{
sync::{Arc, LazyLock},
@@ -306,7 +303,10 @@ impl Render for EditPredictionButton {
.with_handle(self.popover_menu_handle.clone()),
)
}
- provider @ (EditPredictionProvider::Experimental(_) | EditPredictionProvider::Zed) => {
+ provider @ (EditPredictionProvider::Experimental(_)
+ | EditPredictionProvider::Zed
+ | EditPredictionProvider::Sweep
+ | EditPredictionProvider::Mercury) => {
let enabled = self.editor_enabled.unwrap_or(true);
let icons = self
.edit_prediction_provider
@@ -321,9 +321,7 @@ impl Render for EditPredictionButton {
let mut missing_token = false;
match provider {
- EditPredictionProvider::Experimental(
- EXPERIMENTAL_SWEEP_EDIT_PREDICTION_PROVIDER_NAME,
- ) => {
+ 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 };
@@ -333,9 +331,7 @@ impl Render for EditPredictionButton {
"Powered by Sweep"
};
}
- EditPredictionProvider::Experimental(
- EXPERIMENTAL_MERCURY_EDIT_PREDICTION_PROVIDER_NAME,
- ) => {
+ EditPredictionProvider::Mercury => {
ep_icon = if enabled { icons.base } else { icons.disabled };
missing_token = edit_prediction::EditPredictionStore::try_global(cx)
.is_some_and(|ep_store| !ep_store.read(cx).has_mercury_api_token(cx));
@@ -1327,9 +1323,7 @@ pub fn get_available_providers(cx: &mut App) -> Vec<EditPredictionProvider> {
.read(cx)
.has_key()
{
- providers.push(EditPredictionProvider::Experimental(
- EXPERIMENTAL_SWEEP_EDIT_PREDICTION_PROVIDER_NAME,
- ));
+ providers.push(EditPredictionProvider::Sweep);
}
if cx.has_flag::<MercuryFeatureFlag>()
@@ -1337,9 +1331,7 @@ pub fn get_available_providers(cx: &mut App) -> Vec<EditPredictionProvider> {
.read(cx)
.has_key()
{
- providers.push(EditPredictionProvider::Experimental(
- EXPERIMENTAL_MERCURY_EDIT_PREDICTION_PROVIDER_NAME,
- ));
+ providers.push(EditPredictionProvider::Mercury);
}
providers
@@ -171,3 +171,9 @@ pub(crate) mod m_2026_02_02 {
pub(crate) use settings::move_edit_prediction_provider_to_edit_predictions;
}
+
+pub(crate) mod m_2026_02_03 {
+ mod settings;
+
+ pub(crate) use settings::migrate_experimental_sweep_mercury;
+}
@@ -0,0 +1,44 @@
+use anyhow::Result;
+use serde_json::Value;
+
+pub fn migrate_experimental_sweep_mercury(value: &mut Value) -> Result<()> {
+ let Some(obj) = value.as_object_mut() else {
+ return Ok(());
+ };
+
+ if let Some(edit_predictions) = obj.get_mut("edit_predictions") {
+ if let Some(edit_predictions_obj) = edit_predictions.as_object_mut() {
+ migrate_provider_field(edit_predictions_obj, "provider");
+ }
+ }
+
+ if let Some(features) = obj.get_mut("features") {
+ if let Some(features_obj) = features.as_object_mut() {
+ migrate_provider_field(features_obj, "edit_prediction_provider");
+ }
+ }
+
+ Ok(())
+}
+
+fn migrate_provider_field(obj: &mut serde_json::Map<String, Value>, field_name: &str) {
+ let Some(provider) = obj.get(field_name) else {
+ return;
+ };
+
+ let Some(provider_obj) = provider.as_object() else {
+ return;
+ };
+
+ let Some(experimental_name) = provider_obj.get("experimental") else {
+ return;
+ };
+
+ let Some(name) = experimental_name.as_str() else {
+ return;
+ };
+
+ if name == "sweep" || name == "mercury" {
+ obj.insert(field_name.to_string(), Value::String(name.to_string()));
+ }
+}
@@ -235,6 +235,7 @@ pub fn migrate_settings(text: &str) -> Result<Option<String>> {
MigrationType::Json(
migrations::m_2026_02_02::move_edit_prediction_provider_to_edit_predictions,
),
+ MigrationType::Json(migrations::m_2026_02_03::migrate_experimental_sweep_mercury),
];
run_migrations(text, migrations)
}
@@ -2470,4 +2471,125 @@ mod tests {
None,
);
}
+
+ #[test]
+ fn test_migrate_experimental_sweep_mercury() {
+ assert_migrate_settings_with_migrations(
+ &[MigrationType::Json(
+ migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
+ )],
+ &r#"{ }"#.unindent(),
+ None,
+ );
+
+ assert_migrate_settings_with_migrations(
+ &[MigrationType::Json(
+ migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
+ )],
+ &r#"
+ {
+ "edit_predictions": {
+ "provider": {
+ "experimental": "sweep"
+ }
+ }
+ }
+ "#
+ .unindent(),
+ Some(
+ &r#"
+ {
+ "edit_predictions": {
+ "provider": "sweep"
+ }
+ }
+ "#
+ .unindent(),
+ ),
+ );
+
+ assert_migrate_settings_with_migrations(
+ &[MigrationType::Json(
+ migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
+ )],
+ &r#"
+ {
+ "edit_predictions": {
+ "provider": {
+ "experimental": "mercury"
+ }
+ }
+ }
+ "#
+ .unindent(),
+ Some(
+ &r#"
+ {
+ "edit_predictions": {
+ "provider": "mercury"
+ }
+ }
+ "#
+ .unindent(),
+ ),
+ );
+
+ assert_migrate_settings_with_migrations(
+ &[MigrationType::Json(
+ migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
+ )],
+ &r#"
+ {
+ "features": {
+ "edit_prediction_provider": {
+ "experimental": "sweep"
+ }
+ }
+ }
+ "#
+ .unindent(),
+ Some(
+ &r#"
+ {
+ "features": {
+ "edit_prediction_provider": "sweep"
+ }
+ }
+ "#
+ .unindent(),
+ ),
+ );
+
+ assert_migrate_settings_with_migrations(
+ &[MigrationType::Json(
+ migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
+ )],
+ &r#"
+ {
+ "edit_predictions": {
+ "provider": "zed"
+ }
+ }
+ "#
+ .unindent(),
+ None,
+ );
+
+ assert_migrate_settings_with_migrations(
+ &[MigrationType::Json(
+ migrations::m_2026_02_03::migrate_experimental_sweep_mercury,
+ )],
+ &r#"
+ {
+ "edit_predictions": {
+ "provider": {
+ "experimental": "zeta2"
+ }
+ }
+ }
+ "#
+ .unindent(),
+ None,
+ );
+ }
}
@@ -84,12 +84,12 @@ pub enum EditPredictionProvider {
Supermaven,
Zed,
Codestral,
+ Sweep,
+ Mercury,
Experimental(&'static str),
}
-pub const EXPERIMENTAL_SWEEP_EDIT_PREDICTION_PROVIDER_NAME: &str = "sweep";
pub const EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME: &str = "zeta2";
-pub const EXPERIMENTAL_MERCURY_EDIT_PREDICTION_PROVIDER_NAME: &str = "mercury";
impl<'de> Deserialize<'de> for EditPredictionProvider {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@@ -104,6 +104,8 @@ impl<'de> Deserialize<'de> for EditPredictionProvider {
Supermaven,
Zed,
Codestral,
+ Sweep,
+ Mercury,
Experimental(String),
}
@@ -113,20 +115,8 @@ impl<'de> Deserialize<'de> for EditPredictionProvider {
Content::Supermaven => EditPredictionProvider::Supermaven,
Content::Zed => EditPredictionProvider::Zed,
Content::Codestral => EditPredictionProvider::Codestral,
- Content::Experimental(name)
- if name == EXPERIMENTAL_SWEEP_EDIT_PREDICTION_PROVIDER_NAME =>
- {
- EditPredictionProvider::Experimental(
- EXPERIMENTAL_SWEEP_EDIT_PREDICTION_PROVIDER_NAME,
- )
- }
- Content::Experimental(name)
- if name == EXPERIMENTAL_MERCURY_EDIT_PREDICTION_PROVIDER_NAME =>
- {
- EditPredictionProvider::Experimental(
- EXPERIMENTAL_MERCURY_EDIT_PREDICTION_PROVIDER_NAME,
- )
- }
+ Content::Sweep => EditPredictionProvider::Sweep,
+ Content::Mercury => EditPredictionProvider::Mercury,
Content::Experimental(name)
if name == EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME =>
{
@@ -152,6 +142,8 @@ impl EditPredictionProvider {
| EditPredictionProvider::Copilot
| EditPredictionProvider::Supermaven
| EditPredictionProvider::Codestral
+ | EditPredictionProvider::Sweep
+ | EditPredictionProvider::Mercury
| EditPredictionProvider::Experimental(_) => false,
}
}
@@ -162,12 +154,8 @@ impl EditPredictionProvider {
EditPredictionProvider::Copilot => Some("GitHub Copilot"),
EditPredictionProvider::Supermaven => Some("Supermaven"),
EditPredictionProvider::Codestral => Some("Codestral"),
- EditPredictionProvider::Experimental(
- EXPERIMENTAL_SWEEP_EDIT_PREDICTION_PROVIDER_NAME,
- ) => Some("Sweep"),
- EditPredictionProvider::Experimental(
- EXPERIMENTAL_MERCURY_EDIT_PREDICTION_PROVIDER_NAME,
- ) => Some("Mercury"),
+ EditPredictionProvider::Sweep => Some("Sweep"),
+ EditPredictionProvider::Mercury => Some("Mercury"),
EditPredictionProvider::Experimental(
EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME,
) => Some("Zeta2"),
@@ -10,11 +10,7 @@ use feature_flags::FeatureFlagAppExt;
use gpui::{AnyWindowHandle, App, AppContext as _, Context, Entity, WeakEntity};
use language::language_settings::{EditPredictionProvider, all_language_settings};
use language_models::MistralLanguageModelProvider;
-use settings::{
- EXPERIMENTAL_MERCURY_EDIT_PREDICTION_PROVIDER_NAME,
- EXPERIMENTAL_SWEEP_EDIT_PREDICTION_PROVIDER_NAME,
- EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME, SettingsStore,
-};
+use settings::{EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME, SettingsStore};
use std::{cell::RefCell, rc::Rc, sync::Arc};
use supermaven::{Supermaven, SupermavenEditPredictionDelegate};
use ui::Window;
@@ -195,7 +191,10 @@ fn assign_edit_prediction_provider(
let provider = cx.new(|_| CodestralEditPredictionDelegate::new(http_client));
editor.set_edit_prediction_provider(Some(provider), window, cx);
}
- value @ (EditPredictionProvider::Experimental(_) | EditPredictionProvider::Zed) => {
+ value @ (EditPredictionProvider::Experimental(_)
+ | EditPredictionProvider::Zed
+ | EditPredictionProvider::Sweep
+ | EditPredictionProvider::Mercury) => {
let ep_store = edit_prediction::EditPredictionStore::global(client, &user_store, cx);
if let Some(project) = editor.project()
@@ -203,28 +202,27 @@ fn assign_edit_prediction_provider(
&& buffer.read(cx).file().is_some()
{
let has_model = ep_store.update(cx, |ep_store, cx| {
- let model = if let EditPredictionProvider::Experimental(name) = value {
- if name == EXPERIMENTAL_SWEEP_EDIT_PREDICTION_PROVIDER_NAME
- && cx.has_flag::<SweepFeatureFlag>()
- {
+ let model = match value {
+ EditPredictionProvider::Sweep if cx.has_flag::<SweepFeatureFlag>() => {
edit_prediction::EditPredictionModel::Sweep
- } else if name == EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME
- && cx.has_flag::<Zeta2FeatureFlag>()
+ }
+ EditPredictionProvider::Mercury if cx.has_flag::<MercuryFeatureFlag>() => {
+ edit_prediction::EditPredictionModel::Mercury
+ }
+ EditPredictionProvider::Experimental(name)
+ if name == EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME
+ && cx.has_flag::<Zeta2FeatureFlag>() =>
{
edit_prediction::EditPredictionModel::Zeta2 {
version: Default::default(),
}
- } else if name == EXPERIMENTAL_MERCURY_EDIT_PREDICTION_PROVIDER_NAME
- && cx.has_flag::<MercuryFeatureFlag>()
+ }
+ EditPredictionProvider::Zed
+ if user_store.read(cx).current_user().is_some() =>
{
- edit_prediction::EditPredictionModel::Mercury
- } else {
- return false;
+ edit_prediction::EditPredictionModel::Zeta1
}
- } else if user_store.read(cx).current_user().is_some() {
- edit_prediction::EditPredictionModel::Zeta1
- } else {
- return false;
+ _ => return false,
};
ep_store.set_edit_prediction_model(model);