using System.Text.Json; using AIStudio.Settings.DataModel; using AIStudio.Settings.DataModel.PreviousModels; using Host = AIStudio.Provider.SelfHosted.Host; namespace AIStudio.Settings; public static class SettingsMigrations { public static Data Migrate(ILogger logger, Version previousVersion, string configData, JsonSerializerOptions jsonOptions) { switch (previousVersion) { case Version.V1: var configV1 = JsonSerializer.Deserialize(configData, jsonOptions); if (configV1 is null) { logger.LogError("Failed to parse the v1 configuration. Using default values."); return new(); } configV1 = MigrateV1ToV2(logger, configV1); configV1 = MigrateV2ToV3(logger, configV1); var configV14 = MigrateV3ToV4(logger, configV1); return MigrateV4ToV5(logger, configV14); case Version.V2: var configV2 = JsonSerializer.Deserialize(configData, jsonOptions); if (configV2 is null) { logger.LogError("Failed to parse the v2 configuration. Using default values."); return new(); } configV2 = MigrateV2ToV3(logger, configV2); var configV24 = MigrateV3ToV4(logger, configV2); return MigrateV4ToV5(logger, configV24); case Version.V3: var configV3 = JsonSerializer.Deserialize(configData, jsonOptions); if (configV3 is null) { logger.LogError("Failed to parse the v3 configuration. Using default values."); return new(); } var configV34 = MigrateV3ToV4(logger, configV3); return MigrateV4ToV5(logger, configV34); case Version.V4: var configV4 = JsonSerializer.Deserialize(configData, jsonOptions); if (configV4 is null) { logger.LogError("Failed to parse the v4 configuration. Using default values."); return new(); } return MigrateV4ToV5(logger, configV4); default: logger.LogInformation("No configuration migration is needed."); var configV5 = JsonSerializer.Deserialize(configData, jsonOptions); if (configV5 is null) { logger.LogError("Failed to parse the v4 configuration. Using default values."); return new(); } return configV5; } } private static DataV1V3 MigrateV1ToV2(ILogger logger, DataV1V3 previousData) { // // Summary: // In v1 we had no self-hosted providers. Thus, we had no hostnames. // logger.LogInformation("Migrating from v1 to v2..."); return new() { Version = Version.V2, Providers = previousData.Providers.Select(provider => provider with { IsSelfHosted = false, Hostname = "" }).ToList(), EnableSpellchecking = previousData.EnableSpellchecking, IsSavingEnergy = previousData.IsSavingEnergy, NextProviderNum = previousData.NextProviderNum, ShortcutSendBehavior = previousData.ShortcutSendBehavior, UpdateBehavior = previousData.UpdateBehavior, }; } private static DataV1V3 MigrateV2ToV3(ILogger logger, DataV1V3 previousData) { // // Summary: // In v2, self-hosted providers had no host (LM Studio, llama.cpp, ollama, etc.) // logger.LogInformation("Migrating from v2 to v3..."); return new() { Version = Version.V3, Providers = previousData.Providers.Select(provider => { if(provider.IsSelfHosted) return provider with { Host = Host.LM_STUDIO }; return provider with { Host = Host.NONE }; }).ToList(), EnableSpellchecking = previousData.EnableSpellchecking, IsSavingEnergy = previousData.IsSavingEnergy, NextProviderNum = previousData.NextProviderNum, ShortcutSendBehavior = previousData.ShortcutSendBehavior, UpdateBehavior = previousData.UpdateBehavior, WorkspaceStorageBehavior = previousData.WorkspaceStorageBehavior, WorkspaceStorageTemporaryMaintenancePolicy = previousData.WorkspaceStorageTemporaryMaintenancePolicy, }; } private static DataV4 MigrateV3ToV4(ILogger logger, DataV1V3 previousConfig) { // // Summary: // We grouped the settings into different categories. // logger.LogInformation("Migrating from v3 to v4..."); return new() { Version = Version.V4, Providers = previousConfig.Providers, NextProviderNum = previousConfig.NextProviderNum, App = new() { EnableSpellchecking = previousConfig.EnableSpellchecking, IsSavingEnergy = previousConfig.IsSavingEnergy, UpdateBehavior = previousConfig.UpdateBehavior, NavigationBehavior = previousConfig.NavigationBehavior, }, Chat = new() { ShortcutSendBehavior = previousConfig.ShortcutSendBehavior, PreselectOptions = previousConfig.PreselectChatOptions, PreselectedProvider = previousConfig.PreselectedChatProvider, }, Workspace = new() { StorageBehavior = previousConfig.WorkspaceStorageBehavior, StorageTemporaryMaintenancePolicy = previousConfig.WorkspaceStorageTemporaryMaintenancePolicy, }, IconFinder = new() { PreselectOptions = previousConfig.PreselectIconOptions, PreselectedProvider = previousConfig.PreselectedIconProvider, PreselectedSource = previousConfig.PreselectedIconSource, }, Translation = new() { PreselectLiveTranslation = previousConfig.PreselectLiveTranslation, DebounceIntervalMilliseconds = previousConfig.LiveTranslationDebounceIntervalMilliseconds, PreselectOptions = previousConfig.PreselectTranslationOptions, PreselectedProvider = previousConfig.PreselectedTranslationProvider, PreselectedTargetLanguage = previousConfig.PreselectedTranslationTargetLanguage, PreselectOtherLanguage = previousConfig.PreselectTranslationOtherLanguage, HideWebContentReader = previousConfig.HideWebContentReaderForTranslation, PreselectContentCleanerAgent = previousConfig.PreselectContentCleanerAgentForTranslation, PreselectWebContentReader = previousConfig.PreselectWebContentReaderForTranslation, }, Coding = new() { PreselectOptions = previousConfig.PreselectCodingOptions, PreselectedProvider = previousConfig.PreselectedCodingProvider, PreselectedProgrammingLanguage = previousConfig.PreselectedCodingLanguage, PreselectedOtherProgrammingLanguage = previousConfig.PreselectedCodingOtherLanguage, PreselectCompilerMessages = previousConfig.PreselectCodingCompilerMessages, }, TextSummarizer = new() { PreselectOptions = previousConfig.PreselectTextSummarizerOptions, PreselectedComplexity = previousConfig.PreselectedTextSummarizerComplexity, PreselectedProvider = previousConfig.PreselectedTextSummarizerProvider, PreselectedTargetLanguage = previousConfig.PreselectedTextSummarizerTargetLanguage, PreselectedOtherLanguage = previousConfig.PreselectedTextSummarizerOtherLanguage, PreselectedExpertInField = previousConfig.PreselectedTextSummarizerExpertInField, HideWebContentReader = previousConfig.HideWebContentReaderForTextSummarizer, PreselectContentCleanerAgent = previousConfig.PreselectContentCleanerAgentForTextSummarizer, PreselectWebContentReader = previousConfig.PreselectWebContentReaderForTextSummarizer, }, TextContentCleaner = new() { PreselectAgentOptions = previousConfig.PreselectAgentTextContentCleanerOptions, PreselectedAgentProvider = previousConfig.PreselectedAgentTextContentCleanerProvider, }, }; } private static Data MigrateV4ToV5(ILogger logger, DataV4 previousConfig) { // // Summary: // We renamed the LLM provider enum. // logger.LogInformation("Migrating from v4 to v5..."); return new() { Version = Version.V5, Providers = previousConfig.Providers.MigrateFromV4ToV5(), LLMProviders = previousConfig.LLMProviders, Profiles = previousConfig.Profiles, NextProviderNum = previousConfig.NextProviderNum, NextProfileNum = previousConfig.NextProfileNum, App = previousConfig.App, Chat = previousConfig.Chat, Workspace = previousConfig.Workspace, IconFinder = previousConfig.IconFinder, Translation = previousConfig.Translation, Coding = previousConfig.Coding, TextSummarizer = previousConfig.TextSummarizer, TextContentCleaner = previousConfig.TextContentCleaner, Agenda = previousConfig.Agenda, GrammarSpelling = previousConfig.GrammarSpelling, RewriteImprove = previousConfig.RewriteImprove, EMail = previousConfig.EMail, LegalCheck = previousConfig.LegalCheck, Synonyms = previousConfig.Synonyms, MyTasks = previousConfig.MyTasks, }; } }