mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-24 04:00:02 +01:00
Init and added simple ui change.
Signed-off-by: Shuai Yuan <shuai.yuan.zju@gmail.com>
This commit is contained in:
committed by
Shawn Yuan (from Dev Box)
parent
8a7c944ec9
commit
4e5a2db985
@@ -0,0 +1,16 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
public class AdvancedPasteAIServiceOption
|
||||
{
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
public class AdvancedPasteAIServiceParameter : INotifyPropertyChanged
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
public object Value { get; set; }
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
@@ -26,6 +27,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
IsAdvancedAIEnabled = false;
|
||||
ShowCustomPreview = true;
|
||||
CloseAfterLosingFocus = false;
|
||||
AIServiceConfiguration = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(BoolPropertyJsonConverter))]
|
||||
@@ -57,6 +59,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
[CmdConfigureIgnoreAttribute]
|
||||
public AdvancedPasteAdditionalActions AdditionalActions { get; init; }
|
||||
|
||||
[JsonPropertyName("ai-service-configuration")]
|
||||
[CmdConfigureIgnoreAttribute]
|
||||
public Dictionary<string, object> AIServiceConfiguration { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
=> JsonSerializer.Serialize(this);
|
||||
}
|
||||
|
||||
@@ -106,6 +106,51 @@
|
||||
IsEnabled="{x:Bind ViewModel.IsOpenAIEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.IsAdvancedAIEnabled, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsExpander
|
||||
Name="AdvancedPasteAIConfigurationCard"
|
||||
IsEnabled="{x:Bind ViewModel.IsOpenAIEnabled, Mode=OneWay}"
|
||||
IsExpanded="False" >
|
||||
<tkcontrols:SettingsExpander.HeaderIcon>
|
||||
<PathIcon Data="M128 766q0-42 24-77t65-48l178-57q32-11 61-30t52-42q50-50 71-114l58-179q13-40 48-65t78-26q42 0 77 24t50 65l58 177q21 66 72 117 49 50 117 72l176 58q43 14 69 48t26 80q0 41-25 76t-64 49l-178 58q-66 21-117 72-32 32-51 73t-33 84-26 83-30 73-45 51-71 20q-42 0-77-24t-49-65l-58-178q-8-25-19-47t-28-43q-34-43-77-68t-89-41-89-27-78-29-55-45-21-75zm1149 7q-76-29-145-53t-129-60-104-88-73-138l-57-176-67 176q-18 48-42 89t-60 78q-34 34-76 61t-89 43l-177 57q75 29 144 53t127 60 103 89 73 137l57 176 67-176q37-97 103-168t168-103l177-57zm-125 759q0-31 20-57t49-36l99-32q34-11 53-34t30-51 20-59 20-54 33-41 58-16q32 0 59 19t38 50q6 20 11 40t13 40 17 38 25 34q16 17 39 26t48 18 49 16 44 20 31 32 12 50q0 33-18 60t-51 38q-19 6-39 11t-41 13-39 17-34 25q-24 25-35 62t-24 73-35 61-68 25q-32 0-59-19t-38-50q-6-18-11-39t-13-41-17-40-24-33q-18-17-41-27t-47-17-49-15-43-20-30-33-12-54zm583 4q-43-13-74-30t-55-41-40-55-32-74q-12 41-29 72t-42 55-55 42-71 31q81 23 128 71t71 129q15-43 31-74t40-54 53-40 75-32z" />
|
||||
</tkcontrols:SettingsExpander.HeaderIcon>
|
||||
<ComboBox
|
||||
x:Name="AIServiceComboBox"
|
||||
ItemsSource="{x:Bind ViewModel.AIServiceOptions, Mode=OneWay}"
|
||||
DisplayMemberPath="DisplayName"
|
||||
SelectedItem="{x:Bind ViewModel.SelectedAIService, Mode=TwoWay}"
|
||||
IsEnabled="{x:Bind ViewModel.IsOnlineAIModelsDisallowedByGPO, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
MinWidth="220" />
|
||||
<tkcontrols:SettingsExpander.Description>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock x:Uid="AdvancedPaste_EnableAISettingsCardDescription" />
|
||||
<HyperlinkButton x:Uid="AdvancedPaste_EnableAISettingsCardDescriptionLearnMore" NavigateUri="https://learn.microsoft.com/windows/powertoys/advanced-paste" />
|
||||
</StackPanel>
|
||||
</tkcontrols:SettingsExpander.Description>
|
||||
<tkcontrols:SettingsExpander.Items>
|
||||
<ItemsControl ItemsSource="{x:Bind ViewModel.CurrentAIServiceParameters, Mode=OneWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
|
||||
<TextBlock Text="{Binding DisplayName}" Width="120"/>
|
||||
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="200"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<tkcontrols:SettingsCard
|
||||
Margin="0,8,0,0"
|
||||
Visibility="{x:Bind ViewModel.IsAIServiceEnabled, Mode=OneWay}">
|
||||
<Button
|
||||
x:Name="SaveAIConfigButton"
|
||||
x:Uid="AdvancedPaste_SaveAIConfigButton"
|
||||
Content="Save Configuration"
|
||||
Click="SaveAIConfigButton_Click"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
HorizontalAlignment="Left" />
|
||||
</tkcontrols:SettingsCard>
|
||||
</tkcontrols:SettingsExpander.Items>
|
||||
</tkcontrols:SettingsExpander>
|
||||
</controls:SettingsGroup>
|
||||
<controls:SettingsGroup x:Uid="AdvancedPaste_BehaviorSettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
|
||||
<tkcontrols:SettingsCard
|
||||
|
||||
@@ -60,6 +60,12 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
await ShowEnableDialogAsync();
|
||||
}
|
||||
|
||||
private void SaveAIConfigButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Force save the current AI service configuration
|
||||
ViewModel.SaveAIConfiguration();
|
||||
}
|
||||
|
||||
private async Task ShowEnableDialogAsync()
|
||||
{
|
||||
await EnableAIDialog.ShowAsync();
|
||||
|
||||
@@ -49,6 +49,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
private GpoRuleConfigured _onlineAIModelsGpoRuleConfiguration;
|
||||
private bool _onlineAIModelsDisallowedByGPO;
|
||||
private bool _isEnabled;
|
||||
private ObservableCollection<AdvancedPasteAIServiceOption> _aiServiceOptions;
|
||||
private AdvancedPasteAIServiceOption _selectedAIService;
|
||||
private ObservableCollection<AdvancedPasteAIServiceParameter> _currentAIServiceParameters;
|
||||
|
||||
private Func<string, int> SendConfigMSG { get; }
|
||||
|
||||
@@ -77,6 +80,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
InitializeEnabledValue();
|
||||
|
||||
LoadAIServiceOptionsAndDefaults();
|
||||
|
||||
// set the callback functions value to handle outgoing IPC message.
|
||||
SendConfigMSG = ipcMSGCallBackFunc;
|
||||
|
||||
@@ -184,6 +189,457 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
public AdvancedPasteAdditionalActions AdditionalActions => _additionalActions;
|
||||
|
||||
public bool IsAIServiceEnabled => SelectedAIService?.Id != "Disabled";
|
||||
|
||||
public ObservableCollection<AdvancedPasteAIServiceOption> AIServiceOptions
|
||||
{
|
||||
get => _aiServiceOptions;
|
||||
set
|
||||
{
|
||||
if (_aiServiceOptions != value)
|
||||
{
|
||||
_aiServiceOptions = value;
|
||||
OnPropertyChanged(nameof(AIServiceOptions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AdvancedPasteAIServiceOption SelectedAIService
|
||||
{
|
||||
get => _selectedAIService;
|
||||
set
|
||||
{
|
||||
if (_selectedAIService != value)
|
||||
{
|
||||
_selectedAIService = value;
|
||||
OnPropertyChanged(nameof(SelectedAIService));
|
||||
OnPropertyChanged(nameof(IsAIServiceEnabled));
|
||||
UpdateCurrentAIServiceParameters();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<AdvancedPasteAIServiceParameter> CurrentAIServiceParameters
|
||||
{
|
||||
get => _currentAIServiceParameters;
|
||||
set
|
||||
{
|
||||
if (_currentAIServiceParameters != value)
|
||||
{
|
||||
_currentAIServiceParameters = value;
|
||||
OnPropertyChanged(nameof(CurrentAIServiceParameters));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadAIServiceOptionsAndDefaults()
|
||||
{
|
||||
AIServiceOptions = new ObservableCollection<AdvancedPasteAIServiceOption>
|
||||
{
|
||||
new AdvancedPasteAIServiceOption { Id = "AzureOpenAI", DisplayName = "Azure OpenAI" },
|
||||
new AdvancedPasteAIServiceOption { Id = "OpenAI", DisplayName = "OpenAI" },
|
||||
new AdvancedPasteAIServiceOption { Id = "Mistral", DisplayName = "Mistral" },
|
||||
new AdvancedPasteAIServiceOption { Id = "GoogleGemini", DisplayName = "Google Gemini" },
|
||||
new AdvancedPasteAIServiceOption { Id = "HuggingFace", DisplayName = "Hugging Face" },
|
||||
new AdvancedPasteAIServiceOption { Id = "AzureAIInference", DisplayName = "Azure AI Inference" },
|
||||
new AdvancedPasteAIServiceOption { Id = "Ollama", DisplayName = "Ollama" },
|
||||
new AdvancedPasteAIServiceOption { Id = "Anthropic", DisplayName = "Anthropic Claude" },
|
||||
new AdvancedPasteAIServiceOption { Id = "AmazonBedrock", DisplayName = "Amazon Bedrock" },
|
||||
new AdvancedPasteAIServiceOption { Id = "ONNX", DisplayName = "Hugging Face" },
|
||||
new AdvancedPasteAIServiceOption { Id = "Other", DisplayName = "Other" },
|
||||
};
|
||||
SelectedAIService = AIServiceOptions.First();
|
||||
UpdateCurrentAIServiceParameters();
|
||||
}
|
||||
|
||||
private void UpdateCurrentAIServiceParameters()
|
||||
{
|
||||
var parameters = new ObservableCollection<AdvancedPasteAIServiceParameter>();
|
||||
switch (SelectedAIService?.Id)
|
||||
{
|
||||
case "Disabled":
|
||||
// No parameters needed for disabled state
|
||||
break;
|
||||
|
||||
case "OpenAI":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "apiKey",
|
||||
DisplayName = "API Key",
|
||||
Type = "password",
|
||||
Description = "Your OpenAI API key from https://platform.openai.com/api-keys",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model",
|
||||
Type = "text",
|
||||
Description = "OpenAI model (e.g., gpt-4o, gpt-4-turbo, gpt-3.5-turbo)",
|
||||
});
|
||||
break;
|
||||
|
||||
case "AzureOpenAI":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "endpoint",
|
||||
DisplayName = "Endpoint",
|
||||
Type = "text",
|
||||
Description = "Azure OpenAI endpoint URL (e.g., https://your-resource.openai.azure.com/)",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "apiKey",
|
||||
DisplayName = "API Key",
|
||||
Type = "password",
|
||||
Description = "Azure OpenAI API key",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "deploymentName",
|
||||
DisplayName = "Deployment Name",
|
||||
Type = "text",
|
||||
Description = "Azure OpenAI deployment name",
|
||||
});
|
||||
break;
|
||||
|
||||
case "AzureAIInference":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "apiKey",
|
||||
DisplayName = "API Key",
|
||||
Type = "password",
|
||||
Description = "Azure AI Inference API key",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model ID",
|
||||
Type = "text",
|
||||
Description = "Model identifier",
|
||||
});
|
||||
break;
|
||||
|
||||
case "Anthropic":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model",
|
||||
Type = "text",
|
||||
Description = "Claude model (e.g., claude-3-5-sonnet-20241022, claude-3-haiku-20240307)",
|
||||
});
|
||||
break;
|
||||
|
||||
case "GoogleGemini":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "apiKey",
|
||||
DisplayName = "API Key",
|
||||
Type = "password",
|
||||
Description = "Google AI Studio API key",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model",
|
||||
Type = "text",
|
||||
Description = "Gemini model (e.g., gemini-1.5-pro, gemini-1.5-flash)",
|
||||
});
|
||||
break;
|
||||
|
||||
case "Mistral":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "apiKey",
|
||||
DisplayName = "API Key",
|
||||
Type = "password",
|
||||
Description = "Mistral AI API key from https://console.mistral.ai/",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model",
|
||||
Type = "text",
|
||||
Description = "Mistral model (e.g., mistral-large-latest, mistral-small-latest)",
|
||||
});
|
||||
break;
|
||||
|
||||
case "HuggingFace":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "apiKey",
|
||||
DisplayName = "API Key",
|
||||
Type = "password",
|
||||
Description = "Hugging Face API token",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model ID",
|
||||
Type = "text",
|
||||
Description = "Hugging Face model identifier",
|
||||
});
|
||||
break;
|
||||
|
||||
case "Ollama":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "endpoint",
|
||||
DisplayName = "Endpoint",
|
||||
Type = "text",
|
||||
Description = "Ollama server endpoint",
|
||||
Value = "http://localhost:11434",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model",
|
||||
Type = "text",
|
||||
Description = "Ollama model name (e.g., llama3.2, mistral, codellama)",
|
||||
});
|
||||
break;
|
||||
|
||||
case "AmazonBedrock":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model ID",
|
||||
Type = "text",
|
||||
Description = "Bedrock model identifier",
|
||||
});
|
||||
break;
|
||||
|
||||
case "ONNX":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelPath",
|
||||
DisplayName = "Model Path",
|
||||
Type = "text",
|
||||
Description = "Path to ONNX model file",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model ID",
|
||||
Type = "text",
|
||||
Description = "Bedrock model identifier",
|
||||
});
|
||||
break;
|
||||
|
||||
case "Other":
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "endpoint",
|
||||
DisplayName = "Endpoint",
|
||||
Type = "text",
|
||||
Description = "Custom API endpoint URL",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "apiKey",
|
||||
DisplayName = "API Key",
|
||||
Type = "password",
|
||||
Description = "API key for authentication",
|
||||
});
|
||||
parameters.Add(new AdvancedPasteAIServiceParameter
|
||||
{
|
||||
Name = "modelId",
|
||||
DisplayName = "Model ID",
|
||||
Type = "text",
|
||||
Description = "Model identifier",
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
CurrentAIServiceParameters = parameters;
|
||||
}
|
||||
|
||||
public void SaveAIConfiguration()
|
||||
{
|
||||
if (SelectedAIService == null || CurrentAIServiceParameters == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var sensitiveParameters = new HashSet<string> { "endpoint", "apiKey" };
|
||||
var serviceId = SelectedAIService.Id;
|
||||
|
||||
var credentialParameters = new Dictionary<string, object>();
|
||||
var settingsParameters = new Dictionary<string, object>();
|
||||
|
||||
foreach (var param in CurrentAIServiceParameters)
|
||||
{
|
||||
var value = param.Value ?? string.Empty;
|
||||
|
||||
if (sensitiveParameters.Contains(param.Name))
|
||||
{
|
||||
credentialParameters[param.Name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
settingsParameters[param.Name] = value;
|
||||
}
|
||||
}
|
||||
|
||||
SaveCredentialParameters(serviceId, credentialParameters);
|
||||
|
||||
var aiConfiguration = new Dictionary<string, object>
|
||||
{
|
||||
["ServiceId"] = serviceId,
|
||||
["ServiceDisplayName"] = SelectedAIService.DisplayName,
|
||||
["Parameters"] = settingsParameters,
|
||||
};
|
||||
|
||||
_advancedPasteSettings.Properties.AIServiceConfiguration = aiConfiguration;
|
||||
|
||||
SaveAndNotifySettings();
|
||||
}
|
||||
|
||||
private void SaveCredentialParameters(string serviceId, Dictionary<string, object> credentialParameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
PasswordVault vault = new PasswordVault();
|
||||
|
||||
foreach (var parameter in credentialParameters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(parameter.Value?.ToString()))
|
||||
{
|
||||
RemoveCredential(vault, serviceId, parameter.Key);
|
||||
continue;
|
||||
}
|
||||
|
||||
var resourceName = $"PowerToys.AdvancedPaste.{serviceId}";
|
||||
var userName = $"{serviceId}_{parameter.Key}";
|
||||
var password = parameter.Value.ToString();
|
||||
|
||||
RemoveCredential(vault, resourceName, userName);
|
||||
|
||||
var credential = new PasswordCredential(resourceName, userName, password);
|
||||
vault.Add(credential);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Failed to save credentials: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveCredential(PasswordVault vault, string resourceName, string userName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var existingCredential = vault.Retrieve(resourceName, userName);
|
||||
if (existingCredential != null)
|
||||
{
|
||||
vault.Remove(existingCredential);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, string> LoadCredentialParameters(string serviceId)
|
||||
{
|
||||
var credentials = new Dictionary<string, string>();
|
||||
var sensitiveParameters = new HashSet<string> { "endpoint", "apiKey" };
|
||||
|
||||
try
|
||||
{
|
||||
PasswordVault vault = new PasswordVault();
|
||||
var resourceName = $"PowerToys.AdvancedPaste.{serviceId}";
|
||||
|
||||
foreach (var parameterName in sensitiveParameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
var userName = $"{serviceId}_{parameterName}";
|
||||
var credential = vault.Retrieve(resourceName, userName);
|
||||
if (credential != null)
|
||||
{
|
||||
credential.RetrievePassword();
|
||||
credentials[parameterName] = credential.Password;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Failed to load credentials: {ex.Message}");
|
||||
}
|
||||
|
||||
return credentials;
|
||||
}
|
||||
|
||||
private void LoadAIConfigurationFromSettings()
|
||||
{
|
||||
if (_advancedPasteSettings.Properties.AIServiceConfiguration != null)
|
||||
{
|
||||
var config = _advancedPasteSettings.Properties.AIServiceConfiguration;
|
||||
|
||||
if (config.TryGetValue("ServiceId", out var serviceId))
|
||||
{
|
||||
var savedService = AIServiceOptions.FirstOrDefault(s => s.Id == serviceId?.ToString());
|
||||
if (savedService != null)
|
||||
{
|
||||
SelectedAIService = savedService;
|
||||
|
||||
LoadParameterValues(config, serviceId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadParameterValues(Dictionary<string, object> config, string serviceId)
|
||||
{
|
||||
var settingsParameters = new Dictionary<string, object>();
|
||||
if (config.TryGetValue("Parameters", out var parameters) &&
|
||||
parameters is Dictionary<string, object> paramDict)
|
||||
{
|
||||
settingsParameters = paramDict;
|
||||
}
|
||||
|
||||
var credentialParameters = LoadCredentialParameters(serviceId);
|
||||
|
||||
foreach (var parameter in CurrentAIServiceParameters)
|
||||
{
|
||||
if (credentialParameters.TryGetValue(parameter.Name, out var credentialValue))
|
||||
{
|
||||
parameter.Value = credentialValue;
|
||||
}
|
||||
else if (settingsParameters.TryGetValue(parameter.Name, out var settingsValue))
|
||||
{
|
||||
parameter.Value = settingsValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearServiceCredentials(string serviceId)
|
||||
{
|
||||
try
|
||||
{
|
||||
PasswordVault vault = new PasswordVault();
|
||||
var resourceName = $"PowerToys.AdvancedPaste.{serviceId}";
|
||||
var sensitiveParameters = new HashSet<string> { "endpoint", "apiKey" };
|
||||
|
||||
foreach (var parameterName in sensitiveParameters)
|
||||
{
|
||||
var userName = $"{serviceId}_{parameterName}";
|
||||
RemoveCredential(vault, resourceName, userName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Failed to clear service credentials: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private bool OpenAIKeyExists()
|
||||
{
|
||||
PasswordVault vault = new PasswordVault();
|
||||
|
||||
Reference in New Issue
Block a user