Make mercury and sweep non experimental (#48227)

Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Ben Kunkle 2026-02-02 20:13:32 -06:00 committed by GitHub
parent 8fd3b85699
commit 81c65414ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 213 additions and 61 deletions

View file

@ -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");

View file

@ -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

View file

@ -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;
}

View file

@ -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()));
}
}

View file

@ -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,
);
}
}

View file

@ -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"),

View file

@ -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>()
{
edit_prediction::EditPredictionModel::Mercury
} else {
return false;
}
} else if user_store.read(cx).current_user().is_some() {
edit_prediction::EditPredictionModel::Zeta1
} else {
return false;
EditPredictionProvider::Zed
if user_store.read(cx).current_user().is_some() =>
{
edit_prediction::EditPredictionModel::Zeta1
}
_ => return false,
};
ep_store.set_edit_prediction_model(model);