agent: Add Burn Mode setting migrator (#31718)

Danilo Leal created

Follow-up https://github.com/zed-industries/zed/pull/31470.

Release Notes:

- N/A

Change summary

crates/migrator/src/migrations.rs                       |  6 
crates/migrator/src/migrations/m_2025_05_29/settings.rs | 51 ++++++++
crates/migrator/src/migrator.rs                         | 69 +++++++++++
3 files changed, 126 insertions(+)

Detailed changes

crates/migrator/src/migrations.rs 🔗

@@ -69,3 +69,9 @@ pub(crate) mod m_2025_05_08 {
 
     pub(crate) use settings::SETTINGS_PATTERNS;
 }
+
+pub(crate) mod m_2025_05_29 {
+    mod settings;
+
+    pub(crate) use settings::SETTINGS_PATTERNS;
+}

crates/migrator/src/migrations/m_2025_05_29/settings.rs 🔗

@@ -0,0 +1,51 @@
+use std::ops::Range;
+use tree_sitter::{Query, QueryMatch};
+
+use crate::MigrationPatterns;
+use crate::patterns::SETTINGS_NESTED_KEY_VALUE_PATTERN;
+
+pub const SETTINGS_PATTERNS: MigrationPatterns = &[(
+    SETTINGS_NESTED_KEY_VALUE_PATTERN,
+    replace_preferred_completion_mode_value,
+)];
+
+fn replace_preferred_completion_mode_value(
+    contents: &str,
+    mat: &QueryMatch,
+    query: &Query,
+) -> Option<(Range<usize>, String)> {
+    let parent_object_capture_ix = query.capture_index_for_name("parent_key")?;
+    let parent_object_range = mat
+        .nodes_for_capture_index(parent_object_capture_ix)
+        .next()?
+        .byte_range();
+    let parent_object_name = contents.get(parent_object_range.clone())?;
+
+    if parent_object_name != "agent" {
+        return None;
+    }
+
+    let setting_name_capture_ix = query.capture_index_for_name("setting_name")?;
+    let setting_name_range = mat
+        .nodes_for_capture_index(setting_name_capture_ix)
+        .next()?
+        .byte_range();
+    let setting_name = contents.get(setting_name_range.clone())?;
+
+    if setting_name != "preferred_completion_mode" {
+        return None;
+    }
+
+    let value_capture_ix = query.capture_index_for_name("setting_value")?;
+    let value_range = mat
+        .nodes_for_capture_index(value_capture_ix)
+        .next()?
+        .byte_range();
+    let value = contents.get(value_range.clone())?;
+
+    if value.trim() == "\"max\"" {
+        Some((value_range, "\"burn\"".to_string()))
+    } else {
+        None
+    }
+}

crates/migrator/src/migrator.rs 🔗

@@ -144,6 +144,10 @@ pub fn migrate_settings(text: &str) -> Result<Option<String>> {
             migrations::m_2025_05_08::SETTINGS_PATTERNS,
             &SETTINGS_QUERY_2025_05_08,
         ),
+        (
+            migrations::m_2025_05_29::SETTINGS_PATTERNS,
+            &SETTINGS_QUERY_2025_05_29,
+        ),
     ];
     run_migrations(text, migrations)
 }
@@ -238,6 +242,10 @@ define_query!(
     SETTINGS_QUERY_2025_05_08,
     migrations::m_2025_05_08::SETTINGS_PATTERNS
 );
+define_query!(
+    SETTINGS_QUERY_2025_05_29,
+    migrations::m_2025_05_29::SETTINGS_PATTERNS
+);
 
 // custom query
 static EDIT_PREDICTION_SETTINGS_MIGRATION_QUERY: LazyLock<Query> = LazyLock::new(|| {
@@ -785,4 +793,65 @@ mod tests {
             ),
         );
     }
+
+    #[test]
+    fn test_preferred_completion_mode_migration() {
+        assert_migrate_settings(
+            r#"{
+                "agent": {
+                    "preferred_completion_mode": "max",
+                    "enabled": true
+                }
+            }"#,
+            Some(
+                r#"{
+                "agent": {
+                    "preferred_completion_mode": "burn",
+                    "enabled": true
+                }
+            }"#,
+            ),
+        );
+
+        assert_migrate_settings(
+            r#"{
+                "agent": {
+                    "preferred_completion_mode": "normal",
+                    "enabled": true
+                }
+            }"#,
+            None,
+        );
+
+        assert_migrate_settings(
+            r#"{
+                "agent": {
+                    "preferred_completion_mode": "burn",
+                    "enabled": true
+                }
+            }"#,
+            None,
+        );
+
+        assert_migrate_settings(
+            r#"{
+                "other_section": {
+                    "preferred_completion_mode": "max"
+                },
+                "agent": {
+                    "preferred_completion_mode": "max"
+                }
+            }"#,
+            Some(
+                r#"{
+                "other_section": {
+                    "preferred_completion_mode": "max"
+                },
+                "agent": {
+                    "preferred_completion_mode": "burn"
+                }
+            }"#,
+            ),
+        );
+    }
 }