Compare commits

...

5 Commits

Author SHA1 Message Date
Shawn Yuan (from Dev Box)
013a1763b5 update
Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2025-11-14 16:14:53 +08:00
Shawn Yuan (from Dev Box)
4668b16700 update
Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2025-11-14 16:08:10 +08:00
Shawn Yuan (from Dev Box)
ed12ba8f4d fix building issue
Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2025-11-14 15:47:52 +08:00
Shawn Yuan (from Dev Box)
d517730fd0 remove unused file
Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2025-11-14 15:08:08 +08:00
Shawn Yuan (from Dev Box)
8dfa3ae8fa remove unused property
Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2025-11-14 15:01:44 +08:00
5 changed files with 49 additions and 230 deletions

View File

@@ -168,6 +168,15 @@ namespace AdvancedPaste.Settings
}
var properties = settings.Properties;
bool legacyAdvancedAIConsumed = properties.TryConsumeLegacyAdvancedAIEnabled(out var advancedFlag);
bool legacyAdvancedAIEnabled = legacyAdvancedAIConsumed && advancedFlag;
PasswordCredential legacyCredential = TryGetLegacyOpenAICredential();
if (legacyCredential is null)
{
return legacyAdvancedAIConsumed;
}
var configuration = properties.PasteAIConfiguration;
if (configuration is null)
@@ -176,30 +185,11 @@ namespace AdvancedPaste.Settings
properties.PasteAIConfiguration = configuration;
}
bool hasLegacyProviders = configuration.LegacyProviderConfigurations is { Count: > 0 };
bool legacyAdvancedAIConsumed = properties.TryConsumeLegacyAdvancedAIEnabled(out var advancedFlag);
bool legacyAdvancedAIEnabled = legacyAdvancedAIConsumed && advancedFlag;
PasswordCredential legacyCredential = TryGetLegacyOpenAICredential();
if (!hasLegacyProviders && legacyCredential is null && !legacyAdvancedAIConsumed)
{
return false;
}
bool configurationUpdated = false;
if (hasLegacyProviders)
{
configurationUpdated |= AdvancedPasteMigrationHelper.MigrateLegacyProviderConfigurations(configuration);
}
PasteAIProviderDefinition openAIProvider = null;
if (legacyCredential is not null || hasLegacyProviders || legacyAdvancedAIConsumed)
{
var ensureResult = AdvancedPasteMigrationHelper.EnsureOpenAIProvider(configuration);
openAIProvider = ensureResult.Provider;
configurationUpdated |= ensureResult.Updated;
}
var ensureResult = AdvancedPasteMigrationHelper.EnsureOpenAIProvider(configuration);
PasteAIProviderDefinition openAIProvider = ensureResult.Provider;
configurationUpdated |= ensureResult.Updated;
if (legacyAdvancedAIConsumed && openAIProvider is not null && openAIProvider.EnableAdvancedAI != legacyAdvancedAIEnabled)
{
@@ -207,13 +197,13 @@ namespace AdvancedPaste.Settings
configurationUpdated = true;
}
if (legacyCredential is not null && openAIProvider is not null)
if (openAIProvider is not null)
{
StoreMigratedOpenAICredential(openAIProvider.Id, openAIProvider.ServiceType, legacyCredential.Password);
RemoveLegacyOpenAICredential();
}
bool shouldEnableAI = legacyCredential is not null;
const bool shouldEnableAI = true;
bool enabledUpdated = false;
if (properties.IsAIEnabled != shouldEnableAI)
{

View File

@@ -1,35 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
/// <summary>
/// Stores provider-specific configuration overrides so each AI service can keep distinct settings.
/// </summary>
public class AIProviderConfigurationSnapshot
{
[JsonPropertyName("model-name")]
public string ModelName { get; set; } = string.Empty;
[JsonPropertyName("endpoint-url")]
public string EndpointUrl { get; set; } = string.Empty;
[JsonPropertyName("api-version")]
public string ApiVersion { get; set; } = string.Empty;
[JsonPropertyName("deployment-name")]
public string DeploymentName { get; set; } = string.Empty;
[JsonPropertyName("model-path")]
public string ModelPath { get; set; } = string.Empty;
[JsonPropertyName("system-prompt")]
public string SystemPrompt { get; set; } = string.Empty;
[JsonPropertyName("moderation-enabled")]
public bool ModerationEnabled { get; set; } = true;
}
}

View File

@@ -13,56 +13,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
/// </summary>
public static class AdvancedPasteMigrationHelper
{
/// <summary>
/// Moves legacy provider configuration snapshots into the strongly-typed providers collection.
/// </summary>
/// <param name="configuration">The configuration instance to migrate.</param>
/// <returns>True if the configuration was modified.</returns>
public static bool MigrateLegacyProviderConfigurations(PasteAIConfiguration configuration)
{
if (configuration is null)
{
return false;
}
configuration.Providers ??= new ObservableCollection<PasteAIProviderDefinition>();
bool configurationUpdated = false;
if (configuration.LegacyProviderConfigurations is { Count: > 0 })
{
foreach (var entry in configuration.LegacyProviderConfigurations)
{
var result = EnsureProvider(configuration, entry.Key, entry.Value);
configurationUpdated |= result.Updated;
}
configuration.LegacyProviderConfigurations = null;
}
configurationUpdated |= EnsureActiveProviderIsValid(configuration);
return configurationUpdated;
}
/// <summary>
/// Ensures an OpenAI provider exists in the configuration, creating one if necessary.
/// </summary>
/// <param name="configuration">The configuration instance.</param>
/// <returns>The ensured provider and a flag indicating whether changes were made.</returns>
public static (PasteAIProviderDefinition Provider, bool Updated) EnsureOpenAIProvider(PasteAIConfiguration configuration)
{
return EnsureProvider(configuration, AIServiceType.OpenAI.ToConfigurationString(), null);
}
/// <summary>
/// Ensures a provider for the supplied service type exists, optionally applying a legacy snapshot.
/// </summary>
/// <param name="configuration">The configuration instance.</param>
/// <param name="serviceTypeKey">The persisted service type key.</param>
/// <param name="snapshot">An optional snapshot containing legacy values.</param>
/// <returns>The ensured provider and whether the configuration was updated.</returns>
public static (PasteAIProviderDefinition Provider, bool Updated) EnsureProvider(PasteAIConfiguration configuration, string serviceTypeKey, AIProviderConfigurationSnapshot snapshot)
{
if (configuration is null)
{
@@ -71,101 +27,45 @@ namespace Microsoft.PowerToys.Settings.UI.Library
configuration.Providers ??= new ObservableCollection<PasteAIProviderDefinition>();
var normalizedServiceType = NormalizeServiceType(serviceTypeKey);
var existingProvider = configuration.Providers.FirstOrDefault(provider => string.Equals(provider.ServiceType, normalizedServiceType, StringComparison.OrdinalIgnoreCase));
bool configurationUpdated = false;
const string serviceTypeKey = "OpenAI";
var existingProvider = configuration.Providers.FirstOrDefault(provider => string.Equals(provider.ServiceType, serviceTypeKey, StringComparison.OrdinalIgnoreCase));
bool updated = false;
if (existingProvider is null)
{
existingProvider = CreateProvider(normalizedServiceType, snapshot);
existingProvider = CreateProvider(serviceTypeKey);
configuration.Providers.Add(existingProvider);
configurationUpdated = true;
}
else if (snapshot is not null)
{
configurationUpdated |= ApplySnapshot(existingProvider, snapshot);
updated = true;
}
configurationUpdated |= EnsureActiveProviderIsValid(configuration, existingProvider);
updated |= EnsureActiveProviderIsValid(configuration, existingProvider);
return (existingProvider, configurationUpdated);
return (existingProvider, updated);
}
private static string NormalizeServiceType(string serviceTypeKey)
{
var serviceType = serviceTypeKey.ToAIServiceType();
return serviceType.ToConfigurationString();
}
private static PasteAIProviderDefinition CreateProvider(string serviceTypeKey, AIProviderConfigurationSnapshot snapshot)
/// <summary>
/// Creates a provider with default values for the requested service type.
/// </summary>
private static PasteAIProviderDefinition CreateProvider(string serviceTypeKey)
{
var serviceType = serviceTypeKey.ToAIServiceType();
var metadata = AIServiceTypeRegistry.GetMetadata(serviceType);
var provider = new PasteAIProviderDefinition
{
ServiceType = serviceTypeKey,
ModelName = !string.IsNullOrWhiteSpace(snapshot?.ModelName) ? snapshot.ModelName : PasteAIProviderDefaults.GetDefaultModelName(serviceType),
EndpointUrl = snapshot?.EndpointUrl ?? string.Empty,
ApiVersion = snapshot?.ApiVersion ?? string.Empty,
DeploymentName = snapshot?.DeploymentName ?? string.Empty,
ModelPath = snapshot?.ModelPath ?? string.Empty,
SystemPrompt = snapshot?.SystemPrompt ?? string.Empty,
ModerationEnabled = snapshot?.ModerationEnabled ?? true,
ModelName = PasteAIProviderDefaults.GetDefaultModelName(serviceType),
EndpointUrl = string.Empty,
ApiVersion = string.Empty,
DeploymentName = string.Empty,
ModelPath = string.Empty,
SystemPrompt = string.Empty,
ModerationEnabled = serviceType == AIServiceType.OpenAI,
IsLocalModel = metadata.IsLocalModel,
};
return provider;
}
private static bool ApplySnapshot(PasteAIProviderDefinition provider, AIProviderConfigurationSnapshot snapshot)
{
bool updated = false;
if (!string.IsNullOrWhiteSpace(snapshot.ModelName) && !string.Equals(provider.ModelName, snapshot.ModelName, StringComparison.Ordinal))
{
provider.ModelName = snapshot.ModelName;
updated = true;
}
if (!string.IsNullOrWhiteSpace(snapshot.EndpointUrl) && !string.Equals(provider.EndpointUrl, snapshot.EndpointUrl, StringComparison.Ordinal))
{
provider.EndpointUrl = snapshot.EndpointUrl;
updated = true;
}
if (!string.IsNullOrWhiteSpace(snapshot.ApiVersion) && !string.Equals(provider.ApiVersion, snapshot.ApiVersion, StringComparison.Ordinal))
{
provider.ApiVersion = snapshot.ApiVersion;
updated = true;
}
if (!string.IsNullOrWhiteSpace(snapshot.DeploymentName) && !string.Equals(provider.DeploymentName, snapshot.DeploymentName, StringComparison.Ordinal))
{
provider.DeploymentName = snapshot.DeploymentName;
updated = true;
}
if (!string.IsNullOrWhiteSpace(snapshot.ModelPath) && !string.Equals(provider.ModelPath, snapshot.ModelPath, StringComparison.Ordinal))
{
provider.ModelPath = snapshot.ModelPath;
updated = true;
}
if (!string.IsNullOrWhiteSpace(snapshot.SystemPrompt) && !string.Equals(provider.SystemPrompt, snapshot.SystemPrompt, StringComparison.Ordinal))
{
provider.SystemPrompt = snapshot.SystemPrompt;
updated = true;
}
if (provider.ModerationEnabled != snapshot.ModerationEnabled)
{
provider.ModerationEnabled = snapshot.ModerationEnabled;
updated = true;
}
return updated;
}
private static bool EnsureActiveProviderIsValid(PasteAIConfiguration configuration, PasteAIProviderDefinition preferredProvider = null)
{
if (configuration?.Providers is null || configuration.Providers.Count == 0)

View File

@@ -20,8 +20,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
private string _activeProviderId = string.Empty;
private ObservableCollection<PasteAIProviderDefinition> _providers = new();
private bool _useSharedCredentials = true;
private Dictionary<string, AIProviderConfigurationSnapshot> _legacyProviderConfigurations;
public event PropertyChangedEventHandler PropertyChanged;
@@ -39,21 +37,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library
set => SetProperty(ref _providers, value ?? new ObservableCollection<PasteAIProviderDefinition>());
}
[JsonPropertyName("use-shared-credentials")]
public bool UseSharedCredentials
{
get => _useSharedCredentials;
set => SetProperty(ref _useSharedCredentials, value);
}
[JsonPropertyName("provider-configurations")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Dictionary<string, AIProviderConfigurationSnapshot> LegacyProviderConfigurations
{
get => _legacyProviderConfigurations;
set => _legacyProviderConfigurations = value;
}
[JsonIgnore]
public PasteAIProviderDefinition ActiveProvider
{

View File

@@ -191,6 +191,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
return;
}
PasswordCredential legacyCredential = TryGetLegacyOpenAICredential();
if (legacyCredential is null)
{
if (legacyAdvancedAIConsumed)
{
SaveAndNotifySettings();
}
return;
}
var configuration = properties.PasteAIConfiguration;
if (configuration is null)
{
@@ -198,28 +210,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
properties.PasteAIConfiguration = configuration;
}
bool hasLegacyProviders = configuration.LegacyProviderConfigurations is { Count: > 0 };
PasswordCredential legacyCredential = TryGetLegacyOpenAICredential();
if (!hasLegacyProviders && legacyCredential is null && !legacyAdvancedAIConsumed)
{
return;
}
bool configurationUpdated = false;
if (hasLegacyProviders)
{
configurationUpdated |= AdvancedPasteMigrationHelper.MigrateLegacyProviderConfigurations(configuration);
}
PasteAIProviderDefinition openAIProvider = null;
if (legacyCredential is not null || hasLegacyProviders || legacyAdvancedAIConsumed)
{
var ensureResult = AdvancedPasteMigrationHelper.EnsureOpenAIProvider(configuration);
openAIProvider = ensureResult.Provider;
configurationUpdated |= ensureResult.Updated;
}
var ensureResult = AdvancedPasteMigrationHelper.EnsureOpenAIProvider(configuration);
PasteAIProviderDefinition openAIProvider = ensureResult.Provider;
configurationUpdated |= ensureResult.Updated;
if (legacyAdvancedAIConsumed && openAIProvider is not null && openAIProvider.EnableAdvancedAI != legacyAdvancedAIEnabled)
{
@@ -233,7 +228,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
RemoveLegacyOpenAICredential();
}
bool shouldEnableAI = legacyCredential is not null;
const bool shouldEnableAI = true;
bool enabledChanged = false;
if (properties.IsAIEnabled != shouldEnableAI)
{
@@ -1248,11 +1243,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
return true;
}
if (current.UseSharedCredentials != incoming.UseSharedCredentials)
{
return true;
}
var currentProviders = current.Providers ?? new ObservableCollection<PasteAIProviderDefinition>();
var incomingProviders = incoming.Providers ?? new ObservableCollection<PasteAIProviderDefinition>();
@@ -1408,8 +1398,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
return;
}
if (string.Equals(e.PropertyName, nameof(PasteAIConfiguration.ActiveProviderId), StringComparison.Ordinal)
|| string.Equals(e.PropertyName, nameof(PasteAIConfiguration.UseSharedCredentials), StringComparison.Ordinal))
if (string.Equals(e.PropertyName, nameof(PasteAIConfiguration.ActiveProviderId), StringComparison.Ordinal))
{
SaveAndNotifySettings();
}
@@ -1426,15 +1415,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
pasteConfig.Providers ??= new ObservableCollection<PasteAIProviderDefinition>();
bool configurationUpdated = AdvancedPasteMigrationHelper.MigrateLegacyProviderConfigurations(pasteConfig);
SubscribeToPasteAIProviders(pasteConfig);
if (configurationUpdated)
{
SaveAndNotifySettings();
OnPropertyChanged(nameof(PasteAIConfiguration));
}
}
private static string RetrieveCredentialValue(string credentialResource, string credentialUserName)