From d0d2f3cd9c2a188dd54ee95596f7df65af7e157e Mon Sep 17 00:00:00 2001 From: Stefan Markovic <57057282+stefansjfw@users.noreply.github.com> Date: Sun, 26 May 2024 13:22:50 +0200 Subject: [PATCH] [GPO][AdvPaste]Online AI models GPO (#33045) * [Advanced Paste] AI gpo * address PR comments * XAML format * Fix showing Enable Paste with AI with module disabled * Rename variable in ViewModel for clarity * Update adml revision * Move policy registry key around * Update src/modules/AdvancedPaste/AdvancedPaste/Strings/en-us/Resources.resw Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> --------- Co-authored-by: Jaime Bernardo Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> --- src/common/GPOWrapper/GPOWrapper.cpp | 4 ++ src/common/GPOWrapper/GPOWrapper.h | 1 + src/common/GPOWrapper/GPOWrapper.idl | 1 + src/common/utils/gpo.h | 7 ++- src/gpo/assets/PowerToys.admx | 18 +++++- src/gpo/assets/en-US/PowerToys.adml | 11 +++- .../Strings/en-us/Resources.resw | 3 + .../ViewModels/OptionsViewModel.cs | 59 +++++++++++-------- .../SettingsXAML/Views/AdvancedPaste.xaml | 8 ++- .../ViewModels/AdvancedPasteViewModel.cs | 51 +++++++++++++--- .../BugReportTool/ReportGPOValues.cpp | 1 + 11 files changed, 126 insertions(+), 38 deletions(-) diff --git a/src/common/GPOWrapper/GPOWrapper.cpp b/src/common/GPOWrapper/GPOWrapper.cpp index 61e9bd3e84e..ee75ae71f5c 100644 --- a/src/common/GPOWrapper/GPOWrapper.cpp +++ b/src/common/GPOWrapper/GPOWrapper.cpp @@ -172,4 +172,8 @@ namespace winrt::PowerToys::GPOWrapper::implementation { return static_cast(powertoys_gpo::getConfiguredQoiThumbnailsEnabledValue()); } + GpoRuleConfigured GPOWrapper::GetAllowedAdvancedPasteOnlineAIModelsValue() + { + return static_cast(powertoys_gpo::getAllowedAdvancedPasteOnlineAIModelsValue()); + } } diff --git a/src/common/GPOWrapper/GPOWrapper.h b/src/common/GPOWrapper/GPOWrapper.h index e4d5b8185ce..e6e231c3c10 100644 --- a/src/common/GPOWrapper/GPOWrapper.h +++ b/src/common/GPOWrapper/GPOWrapper.h @@ -49,6 +49,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation static GpoRuleConfigured GetConfiguredEnvironmentVariablesEnabledValue(); static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue(); static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue(); + static GpoRuleConfigured GetAllowedAdvancedPasteOnlineAIModelsValue(); }; } diff --git a/src/common/GPOWrapper/GPOWrapper.idl b/src/common/GPOWrapper/GPOWrapper.idl index 9b4054dee72..6bd22d8c31b 100644 --- a/src/common/GPOWrapper/GPOWrapper.idl +++ b/src/common/GPOWrapper/GPOWrapper.idl @@ -53,6 +53,7 @@ namespace PowerToys static GpoRuleConfigured GetConfiguredEnvironmentVariablesEnabledValue(); static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue(); static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue(); + static GpoRuleConfigured GetAllowedAdvancedPasteOnlineAIModelsValue(); } } } diff --git a/src/common/utils/gpo.h b/src/common/utils/gpo.h index adb8ff57dc1..9c852bae58e 100644 --- a/src/common/utils/gpo.h +++ b/src/common/utils/gpo.h @@ -70,7 +70,7 @@ namespace powertoys_gpo { // The registry value names for other PowerToys policies. const std::wstring POLICY_ALLOW_EXPERIMENTATION = L"AllowExperimentation"; const std::wstring POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER_ALL_PLUGINS = L"PowerLauncherAllPluginsEnabledState"; - + const std::wstring POLICY_ALLOW_ADVANCED_PASTE_ONLINE_AI_MODELS = L"AllowPowerToysAdvancedPasteOnlineAIModels"; inline std::optional readRegistryStringValue(HKEY hRootKey, const std::wstring& subKey, const std::wstring& value_name) { @@ -470,4 +470,9 @@ namespace powertoys_gpo { { return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_QOI_THUMBNAILS); } + + inline gpo_rule_configured_t getAllowedAdvancedPasteOnlineAIModelsValue() + { + return getUtilityEnabledValue(POLICY_ALLOW_ADVANCED_PASTE_ONLINE_AI_MODELS); + } } diff --git a/src/gpo/assets/PowerToys.admx b/src/gpo/assets/PowerToys.admx index c54809c35e5..316254ff3e3 100644 --- a/src/gpo/assets/PowerToys.admx +++ b/src/gpo/assets/PowerToys.admx @@ -1,11 +1,11 @@ - + - + @@ -18,6 +18,7 @@ + @@ -28,6 +29,9 @@ + + + @@ -489,5 +493,15 @@ + + + + + + + + + + diff --git a/src/gpo/assets/en-US/PowerToys.adml b/src/gpo/assets/en-US/PowerToys.adml index e917fc11756..9e26fbde74e 100644 --- a/src/gpo/assets/en-US/PowerToys.adml +++ b/src/gpo/assets/en-US/PowerToys.adml @@ -1,7 +1,7 @@ - + PowerToys PowerToys @@ -9,6 +9,7 @@ Microsoft PowerToys Installer and Updates PowerToys Run + Advanced Paste PowerToys version 0.64.0 or later PowerToys version 0.68.0 or later @@ -20,6 +21,7 @@ PowerToys version 0.77.0 or later PowerToys version 0.78.0 or later PowerToys version 0.81.0 or later + PowerToys version 0.81.1 or later This policy configures the enabled state for all PowerToys utilities. @@ -118,6 +120,12 @@ If you disable or don't configure this policy, either the user or the policy "Co You can set the enabled state for all plugins not configured by this policy using the policy "Configure enabled state for all plugins". Note: Changes require a restart of PowerToys Run. + + This policy configures the enabled disable state for using Advanced Paste online AI models. + +If you enable or don't configure this policy, the user takes control over the enabled state of the Enable paste with AI Advanced Paste setting. + +If you disable this policy, the user won't be able to enable Enable paste with AI Advanced Paste setting and use Advanced Paste AI prompt nor set up the Open AI key in PowerToys Settings. Configure global utility enabled state Advanced Paste: Configure enabled state @@ -165,6 +173,7 @@ Note: Changes require a restart of PowerToys Run. Configure enabled state for individual plugins QOI file preview: Configure enabled state QOI file thumbnail: Configure enabled state + Advanced Paste: Allow using online AI models diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Strings/en-us/Resources.resw b/src/modules/AdvancedPaste/AdvancedPaste/Strings/en-us/Resources.resw index 618a54332ca..990310f240c 100644 --- a/src/modules/AdvancedPaste/AdvancedPaste/Strings/en-us/Resources.resw +++ b/src/modules/AdvancedPaste/AdvancedPaste/Strings/en-us/Resources.resw @@ -225,4 +225,7 @@ OpenAI Terms + + To custom with AI is disabled by your organization + \ No newline at end of file diff --git a/src/modules/AdvancedPaste/AdvancedPaste/ViewModels/OptionsViewModel.cs b/src/modules/AdvancedPaste/AdvancedPaste/ViewModels/OptionsViewModel.cs index a3accbe3444..1ba2625e79c 100644 --- a/src/modules/AdvancedPaste/AdvancedPaste/ViewModels/OptionsViewModel.cs +++ b/src/modules/AdvancedPaste/AdvancedPaste/ViewModels/OptionsViewModel.cs @@ -16,7 +16,6 @@ using ManagedCommon; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI.Dispatching; -using Microsoft.UI.Xaml; using Microsoft.Win32; using Windows.ApplicationModel.DataTransfer; using WinUIEx; @@ -81,32 +80,40 @@ public void OnShow() { GetClipboardData(); - var openAIKey = AICompletionsHelper.LoadOpenAIKey(); - var currentKey = aiHelper.GetKey(); - bool keyChanged = openAIKey != currentKey; - - if (keyChanged) + if (PowerToys.GPOWrapper.GPOWrapper.GetAllowedAdvancedPasteOnlineAIModelsValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled) { - app.GetMainWindow().StartLoading(); - - Task.Run(() => - { - aiHelper.SetOpenAIKey(openAIKey); - }).ContinueWith( - (t) => - { - _dispatcherQueue.TryEnqueue(() => - { - app.GetMainWindow().FinishLoading(aiHelper.IsAIEnabled); - OnPropertyChanged(nameof(InputTxtBoxPlaceholderText)); - IsCustomAIEnabled = IsClipboardDataText && aiHelper.IsAIEnabled; - }); - }, - TaskScheduler.Default); + IsCustomAIEnabled = false; + OnPropertyChanged(nameof(InputTxtBoxPlaceholderText)); } else { - IsCustomAIEnabled = IsClipboardDataText && aiHelper.IsAIEnabled; + var openAIKey = AICompletionsHelper.LoadOpenAIKey(); + var currentKey = aiHelper.GetKey(); + bool keyChanged = openAIKey != currentKey; + + if (keyChanged) + { + app.GetMainWindow().StartLoading(); + + Task.Run(() => + { + aiHelper.SetOpenAIKey(openAIKey); + }).ContinueWith( + (t) => + { + _dispatcherQueue.TryEnqueue(() => + { + app.GetMainWindow().FinishLoading(aiHelper.IsAIEnabled); + OnPropertyChanged(nameof(InputTxtBoxPlaceholderText)); + IsCustomAIEnabled = IsClipboardDataText && aiHelper.IsAIEnabled; + }); + }, + TaskScheduler.Default); + } + else + { + IsCustomAIEnabled = IsClipboardDataText && aiHelper.IsAIEnabled; + } } ClipboardHistoryEnabled = IsClipboardHistoryEnabled(); @@ -146,7 +153,11 @@ public string InputTxtBoxPlaceholderText { app.GetMainWindow().ClearInputText(); - if (!aiHelper.IsAIEnabled) + if (PowerToys.GPOWrapper.GPOWrapper.GetAllowedAdvancedPasteOnlineAIModelsValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled) + { + return ResourceLoaderInstance.ResourceLoader.GetString("OpenAIGpoDisabled"); + } + else if (!aiHelper.IsAIEnabled) { return ResourceLoaderInstance.ResourceLoader.GetString("OpenAINotConfigured"); } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPaste.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPaste.xaml index b483dd99181..b79d6e6e59b 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPaste.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPaste.xaml @@ -45,7 +45,7 @@ Severity="Informational" /> - + @@ -73,6 +73,12 @@ IsEnabled="{x:Bind ViewModel.IsOpenAIEnabled, Mode=OneWay}"> + diff --git a/src/settings-ui/Settings.UI/ViewModels/AdvancedPasteViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/AdvancedPasteViewModel.cs index fa0288e09b0..28b27d95fb9 100644 --- a/src/settings-ui/Settings.UI/ViewModels/AdvancedPasteViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/AdvancedPasteViewModel.cs @@ -32,6 +32,8 @@ public class AdvancedPasteViewModel : Observable, IDisposable private GpoRuleConfigured _enabledGpoRuleConfiguration; private bool _enabledStateIsGPOConfigured; + private GpoRuleConfigured _onlineAIModelsGpoRuleConfiguration; + private bool _onlineAIModelsDisallowedByGPO; private bool _isEnabled; private Func SendConfigMSG { get; } @@ -80,6 +82,15 @@ private void InitializeEnabledValue() { _isEnabled = GeneralSettingsConfig.Enabled.AdvancedPaste; } + + _onlineAIModelsGpoRuleConfiguration = GPOWrapper.GetAllowedAdvancedPasteOnlineAIModelsValue(); + if (_onlineAIModelsGpoRuleConfiguration == GpoRuleConfigured.Disabled) + { + _onlineAIModelsDisallowedByGPO = true; + + // disable AI if it was enabled + DisableAI(); + } } public bool IsEnabled @@ -124,13 +135,23 @@ private bool OpenAIKeyExists() return cred is not null; } - public bool IsOpenAIEnabled => OpenAIKeyExists(); + public bool IsOpenAIEnabled => OpenAIKeyExists() && !IsOnlineAIModelsDisallowedByGPO; public bool IsEnabledGpoConfigured { get => _enabledStateIsGPOConfigured; } + public bool IsOnlineAIModelsDisallowedByGPO + { + get => _onlineAIModelsDisallowedByGPO || _enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled; + } + + public bool ShowOnlineAIModelsGpoConfiguredInfoBar + { + get => _onlineAIModelsDisallowedByGPO && _enabledGpoRuleConfiguration != GpoRuleConfigured.Disabled; + } + private bool IsClipboardHistoryEnabled() { string registryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Clipboard\"; @@ -334,18 +355,30 @@ public void Dispose() internal void DisableAI() { - PasswordVault vault = new PasswordVault(); - PasswordCredential cred = vault.Retrieve("https://platform.openai.com/api-keys", "PowerToys_AdvancedPaste_OpenAIKey"); - vault.Remove(cred); - OnPropertyChanged(nameof(IsOpenAIEnabled)); + try + { + PasswordVault vault = new PasswordVault(); + PasswordCredential cred = vault.Retrieve("https://platform.openai.com/api-keys", "PowerToys_AdvancedPaste_OpenAIKey"); + vault.Remove(cred); + OnPropertyChanged(nameof(IsOpenAIEnabled)); + } + catch (Exception) + { + } } internal void EnableAI(string password) { - PasswordVault vault = new PasswordVault(); - PasswordCredential cred = new PasswordCredential("https://platform.openai.com/api-keys", "PowerToys_AdvancedPaste_OpenAIKey", password); - vault.Add(cred); - OnPropertyChanged(nameof(IsOpenAIEnabled)); + try + { + PasswordVault vault = new PasswordVault(); + PasswordCredential cred = new PasswordCredential("https://platform.openai.com/api-keys", "PowerToys_AdvancedPaste_OpenAIKey", password); + vault.Add(cred); + OnPropertyChanged(nameof(IsOpenAIEnabled)); + } + catch (Exception) + { + } } } } diff --git a/tools/BugReportTool/BugReportTool/ReportGPOValues.cpp b/tools/BugReportTool/BugReportTool/ReportGPOValues.cpp index b4cf7a0a875..3aa19a80eb7 100644 --- a/tools/BugReportTool/BugReportTool/ReportGPOValues.cpp +++ b/tools/BugReportTool/BugReportTool/ReportGPOValues.cpp @@ -67,4 +67,5 @@ void ReportGPOValues(const std::filesystem::path& tmpDir) report << "getAllowExperimentationValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowExperimentationValue()) << std::endl; report << "getConfiguredQoiPreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredQoiPreviewEnabledValue()) << std::endl; report << "getConfiguredQoiThumbnailsEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredQoiThumbnailsEnabledValue()) << std::endl; + report << "getAllowedAdvancedPasteOnlineAIModelsValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowedAdvancedPasteOnlineAIModelsValue()) << std::endl; }