diff --git a/app/MindWork AI Studio/Settings/ConfigMetaBase.cs b/app/MindWork AI Studio/Settings/ConfigMetaBase.cs
index 43fb5c29..75a7ad6a 100644
--- a/app/MindWork AI Studio/Settings/ConfigMetaBase.cs
+++ b/app/MindWork AI Studio/Settings/ConfigMetaBase.cs
@@ -139,6 +139,29 @@ public abstract record ConfigMetaBase(string SettingName) : IConfig
this.EditableDefaultByConfigPluginId = Guid.Empty;
}
+ ///
+ /// Clears the editable-default state and hands the setting back to the user.
+ ///
+ ///
+ /// Without a snapshot of the user's value, the current value stays as it is. That is the
+ /// difference to a locked setting: the user was allowed to change an editable default all
+ /// along, so its value is a plausible choice of theirs. Resetting it to the app's default would
+ /// take away something nobody asked us to remove.
+ ///
+ ///
+ /// True when the user has changed the value in the meantime. Their decision outlives the
+ /// configuration plugin, so the snapshot is dropped instead of applied.
+ ///
+ public void ResetEditableDefaultConfiguration(bool keepCurrentValue)
+ {
+ this.ClearEditableDefaultConfiguration();
+
+ if (keepCurrentValue)
+ this.ClearUserValueSnapshot();
+ else
+ this.TryRestoreUserValueSnapshot();
+ }
+
///
/// Removes the contribution of one configuration plugin without changing the current value.
///
diff --git a/app/MindWork AI Studio/Settings/ManagedConfiguration.Parsing.cs b/app/MindWork AI Studio/Settings/ManagedConfiguration.Parsing.cs
index 41ac1d54..ebd3f284 100644
--- a/app/MindWork AI Studio/Settings/ManagedConfiguration.Parsing.cs
+++ b/app/MindWork AI Studio/Settings/ManagedConfiguration.Parsing.cs
@@ -1024,7 +1024,7 @@ public static partial class ManagedConfiguration
case false when configMeta.ManagedMode is ManagedConfigurationMode.EDITABLE_DEFAULT
&& TryGetEditableDefaultState(settingName, out var editableDefaultStateToRemove)
&& editableDefaultStateToRemove.ConfigPluginId == configPluginId:
- configMeta.ClearEditableDefaultConfiguration();
+ configMeta.ResetEditableDefaultConfiguration(HasUserChangedEditableDefault(configMeta, editableDefaultStateToRemove));
ClearEditableDefaultState(settingName);
break;
}
diff --git a/app/MindWork AI Studio/Settings/ManagedConfiguration.cs b/app/MindWork AI Studio/Settings/ManagedConfiguration.cs
index 64a33bed..417d48be 100644
--- a/app/MindWork AI Studio/Settings/ManagedConfiguration.cs
+++ b/app/MindWork AI Studio/Settings/ManagedConfiguration.cs
@@ -361,6 +361,19 @@ public static partial class ManagedConfiguration
configMeta.RemovePluginContribution(contributingConfigPluginId);
wasChanged = true;
}
+
+ //
+ // Finally, drop any snapshot of the user's value which nobody claims anymore. Without
+ // this, a setting which stopped being managed outside of the paths above would keep its
+ // snapshot in the settings file forever. The persisted editable default counts as a
+ // claim as well: it survives a configuration plugin which is deployed but could not be
+ // loaded, and that plugin is still in charge:
+ //
+ if (configMeta.ManagedMode is null && !TryGetEditableDefaultState(configMeta.SettingName, out _) && configMeta.ClearUserValueSnapshot())
+ {
+ Log.LogInformation($"Dropping the snapshot of the user's value for the setting '{configMeta.SettingName}': no configuration plugin manages it anymore.");
+ wasChanged = true;
+ }
}
// Remove persisted states which belong to settings that do not exist anymore:
@@ -405,6 +418,13 @@ public static partial class ManagedConfiguration
wasChanged = true;
}
+ foreach (var settingName in configurationData.ManagedUserValueSnapshots.Keys.Where(x => !registeredSettingNames.Contains(x)).ToList())
+ {
+ Log.LogInformation($"Removing the snapshot of the user's value for the setting '{settingName}': this setting does not exist anymore.");
+ configurationData.ManagedUserValueSnapshots.Remove(settingName);
+ wasChanged = true;
+ }
+
return wasChanged;
}
@@ -447,7 +467,7 @@ public static partial class ManagedConfiguration
if (configMeta.ManagedMode is not ManagedConfigurationMode.EDITABLE_DEFAULT)
return false;
- configMeta.ClearEditableDefaultConfiguration();
+ configMeta.ResetEditableDefaultConfiguration(keepCurrentValue: false);
return true;
}
@@ -455,7 +475,17 @@ public static partial class ManagedConfiguration
return false;
Log.LogInformation($"Clearing the editable default of the setting '{configMeta.SettingName}': the configuration plugin '{editableDefaultState.ConfigPluginId}' is not available anymore.");
- configMeta.ClearEditableDefaultConfiguration();
+ configMeta.ResetEditableDefaultConfiguration(HasUserChangedEditableDefault(configMeta, editableDefaultState));
return ClearEditableDefaultState(configMeta.SettingName);
}
+
+ ///
+ /// Checks whether the user has changed an editable default themselves.
+ ///
+ ///
+ /// The user may change an editable default at any time. When the current value is not the one
+ /// the configuration plugin applied last, the user decided against that value, and their
+ /// decision outlives the plugin.
+ ///
+ private static bool HasUserChangedEditableDefault(ConfigMetaBase configMeta, ManagedEditableDefaultState editableDefaultState) => !string.Equals(configMeta.SerializeCurrentValue(), editableDefaultState.LastAppliedValue, StringComparison.Ordinal);
}
\ No newline at end of file