agent: Remove context server settings when uninstalling MCP extension (#32560)
Release Notes: - agent: Automatically remove context server settings when uninstalling MCP extension
This commit is contained in:
parent
e8ba8bb1eb
commit
717bf35484
6 changed files with 171 additions and 19 deletions
|
@ -1349,16 +1349,23 @@ fn update_value_in_json_text<'a>(
|
|||
if let (Value::Object(old_object), Value::Object(new_object)) = (old_value, new_value) {
|
||||
for (key, old_sub_value) in old_object.iter() {
|
||||
key_path.push(key);
|
||||
let new_sub_value = new_object.get(key).unwrap_or(&Value::Null);
|
||||
update_value_in_json_text(
|
||||
text,
|
||||
key_path,
|
||||
tab_size,
|
||||
old_sub_value,
|
||||
new_sub_value,
|
||||
preserved_keys,
|
||||
edits,
|
||||
);
|
||||
if let Some(new_sub_value) = new_object.get(key) {
|
||||
// Key exists in both old and new, recursively update
|
||||
update_value_in_json_text(
|
||||
text,
|
||||
key_path,
|
||||
tab_size,
|
||||
old_sub_value,
|
||||
new_sub_value,
|
||||
preserved_keys,
|
||||
edits,
|
||||
);
|
||||
} else {
|
||||
// Key was removed from new object, remove the entire key-value pair
|
||||
let (range, replacement) = replace_value_in_json_text(text, key_path, 0, None);
|
||||
text.replace_range(range.clone(), &replacement);
|
||||
edits.push((range, replacement));
|
||||
}
|
||||
key_path.pop();
|
||||
}
|
||||
for (key, new_sub_value) in new_object.iter() {
|
||||
|
@ -1385,7 +1392,8 @@ fn update_value_in_json_text<'a>(
|
|||
if let Some(new_object) = new_value.as_object_mut() {
|
||||
new_object.retain(|_, v| !v.is_null());
|
||||
}
|
||||
let (range, replacement) = replace_value_in_json_text(text, key_path, tab_size, &new_value);
|
||||
let (range, replacement) =
|
||||
replace_value_in_json_text(text, key_path, tab_size, Some(&new_value));
|
||||
text.replace_range(range.clone(), &replacement);
|
||||
edits.push((range, replacement));
|
||||
}
|
||||
|
@ -1395,7 +1403,7 @@ fn replace_value_in_json_text(
|
|||
text: &str,
|
||||
key_path: &[&str],
|
||||
tab_size: usize,
|
||||
new_value: &Value,
|
||||
new_value: Option<&Value>,
|
||||
) -> (Range<usize>, String) {
|
||||
static PAIR_QUERY: LazyLock<Query> = LazyLock::new(|| {
|
||||
Query::new(
|
||||
|
@ -1461,16 +1469,64 @@ fn replace_value_in_json_text(
|
|||
}
|
||||
}
|
||||
|
||||
// We found the exact key we want, insert the new value
|
||||
// We found the exact key we want
|
||||
if depth == key_path.len() {
|
||||
let new_val = to_pretty_json(&new_value, tab_size, tab_size * depth);
|
||||
(existing_value_range, new_val)
|
||||
if let Some(new_value) = new_value {
|
||||
let new_val = to_pretty_json(new_value, tab_size, tab_size * depth);
|
||||
(existing_value_range, new_val)
|
||||
} else {
|
||||
let mut removal_start = first_key_start.unwrap_or(existing_value_range.start);
|
||||
let mut removal_end = existing_value_range.end;
|
||||
|
||||
// Find the actual key position by looking for the key in the pair
|
||||
// We need to extend the range to include the key, not just the value
|
||||
if let Some(key_start) = text[..existing_value_range.start].rfind('"') {
|
||||
if let Some(prev_key_start) = text[..key_start].rfind('"') {
|
||||
removal_start = prev_key_start;
|
||||
} else {
|
||||
removal_start = key_start;
|
||||
}
|
||||
}
|
||||
|
||||
// Look backward for a preceding comma first
|
||||
let preceding_text = text.get(0..removal_start).unwrap_or("");
|
||||
if let Some(comma_pos) = preceding_text.rfind(',') {
|
||||
// Check if there are only whitespace characters between the comma and our key
|
||||
let between_comma_and_key = text.get(comma_pos + 1..removal_start).unwrap_or("");
|
||||
if between_comma_and_key.trim().is_empty() {
|
||||
removal_start = comma_pos;
|
||||
}
|
||||
} else {
|
||||
// No preceding comma, check for trailing comma
|
||||
if let Some(remaining_text) = text.get(existing_value_range.end..) {
|
||||
let mut chars = remaining_text.char_indices();
|
||||
while let Some((offset, ch)) = chars.next() {
|
||||
if ch == ',' {
|
||||
removal_end = existing_value_range.end + offset + 1;
|
||||
// Also consume whitespace after the comma
|
||||
while let Some((_, next_ch)) = chars.next() {
|
||||
if next_ch.is_whitespace() {
|
||||
removal_end += next_ch.len_utf8();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if !ch.is_whitespace() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(removal_start..removal_end, String::new())
|
||||
}
|
||||
} else {
|
||||
// We have key paths, construct the sub objects
|
||||
let new_key = key_path[depth];
|
||||
|
||||
// We don't have the key, construct the nested objects
|
||||
let mut new_value = serde_json::to_value(new_value).unwrap();
|
||||
let mut new_value =
|
||||
serde_json::to_value(new_value.unwrap_or(&serde_json::Value::Null)).unwrap();
|
||||
for key in key_path[(depth + 1)..].iter().rev() {
|
||||
new_value = serde_json::json!({ key.to_string(): new_value });
|
||||
}
|
||||
|
@ -1775,6 +1831,61 @@ mod tests {
|
|||
cx,
|
||||
);
|
||||
|
||||
// entries removed
|
||||
check_settings_update::<LanguageSettings>(
|
||||
&mut store,
|
||||
r#"{
|
||||
"languages": {
|
||||
"Rust": {
|
||||
"language_setting_2": true
|
||||
},
|
||||
"JSON": {
|
||||
"language_setting_1": false
|
||||
}
|
||||
}
|
||||
}"#
|
||||
.unindent(),
|
||||
|settings| {
|
||||
settings.languages.remove("JSON").unwrap();
|
||||
},
|
||||
r#"{
|
||||
"languages": {
|
||||
"Rust": {
|
||||
"language_setting_2": true
|
||||
}
|
||||
}
|
||||
}"#
|
||||
.unindent(),
|
||||
cx,
|
||||
);
|
||||
|
||||
check_settings_update::<LanguageSettings>(
|
||||
&mut store,
|
||||
r#"{
|
||||
"languages": {
|
||||
"Rust": {
|
||||
"language_setting_2": true
|
||||
},
|
||||
"JSON": {
|
||||
"language_setting_1": false
|
||||
}
|
||||
}
|
||||
}"#
|
||||
.unindent(),
|
||||
|settings| {
|
||||
settings.languages.remove("Rust").unwrap();
|
||||
},
|
||||
r#"{
|
||||
"languages": {
|
||||
"JSON": {
|
||||
"language_setting_1": false
|
||||
}
|
||||
}
|
||||
}"#
|
||||
.unindent(),
|
||||
cx,
|
||||
);
|
||||
|
||||
// weird formatting
|
||||
check_settings_update::<UserSettings>(
|
||||
&mut store,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue