Multiple Profiles can now be selected

This commit is contained in:
Peer Hogeterp committed 2026-09-07 16:09:00 +02:00
1 parent d043fbc8f0
commit cefc5464d5
89 files changed
+1360 -503

No files matched your search

@@ -110,7 +110,7 @@ else
<ConfigurationProviderSelection Component="Components.DOCUMENT_ANALYSIS_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => this.IsNoPolicySelectedOrProtected)" SelectedValue="@(() => this.policyPreselectedProviderId)" SelectionUpdate="@this.PolicyPreselectedProviderWasChanged" ExplicitMinimumConfidence="@this.GetPolicyMinimumConfidenceLevel()"/>
<ConfigurationSelect OptionDescription="@T("Preselect a profile")" Disabled="@(() => this.IsNoPolicySelected)" SelectedValue="@(() => this.policyPreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetComponentProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdateAsync="@(async selection => await this.PolicyPreselectedProfileWasChangedAsync(selection))" OptionHelp="@T("Choose whether the policy should use the app default profile, no profile, or a specific profile.")"/>
<ProfilePreselectionConfiguration OptionDescription="@T("Preselect profiles")" Disabled="@(() => this.IsNoPolicySelected)" SelectedProfileIds="@(() => this.policyPreselectedProfileIds)" SelectionUpdateAsync="@this.PolicyPreselectedProfilesWereChangedAsync" OptionHelp="@T("Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.")"/>
<MudTextSwitch Disabled="@(this.IsNoPolicySelected || (this.selectedPolicy?.IsEnterpriseConfiguration ?? true))" Label="@T("Would you like to protect this policy so that you cannot accidentally edit or delete it?")" Value="@this.policyIsProtected" ValueChanged="async state => await this.PolicyProtectionWasChanged(state)" LabelOn="@T("Yes, protect this policy")" LabelOff="@T("No, the policy can be edited")" />
@@ -143,7 +143,8 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
{
return new ChatThread
{
SystemPrompt = SystemPrompts.DEFAULT
SystemPrompt = SystemPrompts.DEFAULT,
SelectedProfileIds = [..this.CurrentProfileIds],
};
}
@@ -152,6 +153,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
ChatId = Guid.NewGuid(),
Name = string.Format(T("{0} - Document Analysis Session"), this.selectedPolicy?.PolicyName ?? T("Empty")),
SystemPrompt = SystemPrompts.DEFAULT,
SelectedProfileIds = [..this.CurrentProfileIds],
Blocks =
[
// Replace the first "user block" (here, it was/is the block generated by the assistant) with a new one
@@ -191,7 +193,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
this.policyMinimumProviderConfidence = ConfidenceLevel.NONE;
this.policyAllowedToolIds = [];
this.policyPreselectedProviderId = string.Empty;
this.policyPreselectedProfile = ProfilePreselection.NoProfile;
this.policyPreselectedProfileIds = [];
}
}
@@ -219,7 +221,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
this.policyMinimumProviderConfidence = this.selectedPolicy.MinimumProviderConfidence;
this.policyAllowedToolIds = [..this.selectedPolicy.AllowedToolIds];
this.policyPreselectedProviderId = this.selectedPolicy.PreselectedProvider;
this.policyPreselectedProfile = ProfilePreselection.FromStoredValue(this.selectedPolicy.PreselectedProfile);
this.policyPreselectedProfileIds = this.selectedPolicy.PreselectedProfileIds is null ? null : [..this.selectedPolicy.PreselectedProfileIds];
return true;
}
@@ -258,7 +260,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
return;
// The preselected profile is always user-adjustable, even for protected policies and enterprise configurations:
this.selectedPolicy.PreselectedProfile = this.policyPreselectedProfile;
this.selectedPolicy.PreselectedProfileIds = this.policyPreselectedProfileIds is null ? null : [..this.policyPreselectedProfileIds];
// Enterprise configurations cannot be modified at all:
if(this.selectedPolicy.IsEnterpriseConfiguration)
@@ -292,7 +294,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
private ConfidenceLevel policyMinimumProviderConfidence = ConfidenceLevel.NONE;
private HashSet<string> policyAllowedToolIds = [];
private string policyPreselectedProviderId = string.Empty;
private ProfilePreselection policyPreselectedProfile = ProfilePreselection.NoProfile;
private HashSet<string>? policyPreselectedProfileIds = [];
private HashSet<FileAttachment> loadedDocumentPaths = [];
private readonly List<ConfigurationSelectData<string>> availableLLMProviders = new();
private static readonly AssistantSessionStateKey<DataDocumentAnalysisPolicy?> SELECTED_POLICY_STATE_KEY = new(nameof(selectedPolicy));
@@ -305,7 +307,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
private static readonly AssistantSessionStateKey<string> POLICY_OUTPUT_RULES_STATE_KEY = new(nameof(policyOutputRules));
private static readonly AssistantSessionStateKey<ConfidenceLevel> POLICY_MINIMUM_PROVIDER_CONFIDENCE_STATE_KEY = new(nameof(policyMinimumProviderConfidence));
private static readonly AssistantSessionStateKey<string> POLICY_PRESELECTED_PROVIDER_ID_STATE_KEY = new(nameof(policyPreselectedProviderId));
private static readonly AssistantSessionStateKey<ProfilePreselection> POLICY_PRESELECTED_PROFILE_STATE_KEY = new(nameof(policyPreselectedProfile));
private static readonly AssistantSessionStateKey<HashSet<string>?> POLICY_PRESELECTED_PROFILE_IDS_STATE_KEY = new(nameof(policyPreselectedProfileIds));
private static readonly AssistantSessionStateKey<HashSet<FileAttachment>> LOADED_DOCUMENT_PATHS_STATE_KEY = new(nameof(loadedDocumentPaths));
private static readonly AssistantSessionStateKey<List<ConfigurationSelectData<string>>> AVAILABLE_LLM_PROVIDERS_STATE_KEY = new(nameof(availableLLMProviders));
@@ -322,7 +324,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
state.Set(POLICY_OUTPUT_RULES_STATE_KEY, this.policyOutputRules);
state.Set(POLICY_MINIMUM_PROVIDER_CONFIDENCE_STATE_KEY, this.policyMinimumProviderConfidence);
state.Set(POLICY_PRESELECTED_PROVIDER_ID_STATE_KEY, this.policyPreselectedProviderId);
state.Set(POLICY_PRESELECTED_PROFILE_STATE_KEY, this.policyPreselectedProfile);
state.Set(POLICY_PRESELECTED_PROFILE_IDS_STATE_KEY, this.policyPreselectedProfileIds);
state.SetHashSet(LOADED_DOCUMENT_PATHS_STATE_KEY, this.loadedDocumentPaths);
state.SetList(AVAILABLE_LLM_PROVIDERS_STATE_KEY, this.availableLLMProviders);
}
@@ -340,7 +342,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
state.Restore(POLICY_OUTPUT_RULES_STATE_KEY, value => this.policyOutputRules = value);
state.Restore(POLICY_MINIMUM_PROVIDER_CONFIDENCE_STATE_KEY, value => this.policyMinimumProviderConfidence = value);
state.Restore(POLICY_PRESELECTED_PROVIDER_ID_STATE_KEY, value => this.policyPreselectedProviderId = value);
state.Restore(POLICY_PRESELECTED_PROFILE_STATE_KEY, value => this.policyPreselectedProfile = value);
state.Restore(POLICY_PRESELECTED_PROFILE_IDS_STATE_KEY, value => this.policyPreselectedProfileIds = value);
state.RestoreHashSet(LOADED_DOCUMENT_PATHS_STATE_KEY, this.loadedDocumentPaths);
state.RestoreList(AVAILABLE_LLM_PROVIDERS_STATE_KEY, this.availableLLMProviders);
}
@@ -487,7 +489,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
if (this.ProviderSettings != Settings.Provider.NONE &&
this.ProviderSettings.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel)
{
this.CurrentProfile = this.ResolveProfileSelection();
this.CurrentProfileIds = this.ResolveProfileSelection();
return;
}
}
@@ -497,7 +499,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
if (policyProvider != Settings.Provider.NONE && policyProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level >= minimumLevel)
{
this.ProviderSettings = policyProvider;
this.CurrentProfile = this.ResolveProfileSelection();
this.CurrentProfileIds = this.ResolveProfileSelection();
return;
}
@@ -507,7 +509,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
fallbackProvider = Settings.Provider.NONE;
this.ProviderSettings = fallbackProvider;
this.CurrentProfile = this.ResolveProfileSelection();
this.CurrentProfileIds = this.ResolveProfileSelection();
}
private ConfidenceLevel GetPolicyMinimumConfidenceLevel()
@@ -524,23 +526,19 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
return minimumLevel;
}
private Profile ResolveProfileSelection()
private HashSet<string> ResolveProfileSelection()
{
if (this.selectedPolicy is null)
return this.SettingsManager.GetPreselectedProfile(this.Component);
return this.SettingsManager.GetPreselectedProfiles(this.Component).Select(profile => profile.Id).ToHashSet(StringComparer.OrdinalIgnoreCase);
var policyProfilePreselection = ProfilePreselection.FromStoredValue(this.selectedPolicy.PreselectedProfile);
if (policyProfilePreselection.DoNotPreselectProfile)
return Profile.NO_PROFILE;
var policyProfilePreselection = ProfilePreselection.FromStoredValue(this.selectedPolicy.PreselectedProfileIds);
if (policyProfilePreselection.DoNotPreselectProfiles)
return [];
if (policyProfilePreselection.UseSpecificProfile)
{
var policyProfile = this.SettingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == policyProfilePreselection.SpecificProfileId);
if (policyProfile is not null)
return policyProfile;
}
if (policyProfilePreselection.UseSpecificProfiles)
return this.SettingsManager.ResolveProfiles(policyProfilePreselection.SpecificProfileIds).Select(profile => profile.Id).ToHashSet(StringComparer.OrdinalIgnoreCase);
return this.SettingsManager.GetAppPreselectedProfile();
return this.SettingsManager.GetAppPreselectedProfiles().Select(profile => profile.Id).ToHashSet(StringComparer.OrdinalIgnoreCase);
}
/// <summary>
@@ -571,13 +569,13 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
this.ApplyPolicyPreselection();
}
private async Task PolicyPreselectedProfileWasChangedAsync(ProfilePreselection selection)
private async Task PolicyPreselectedProfilesWereChangedAsync(HashSet<string>? selection)
{
this.policyPreselectedProfile = selection;
this.policyPreselectedProfileIds = selection is null ? null : [..selection];
if (this.selectedPolicy is not null)
this.selectedPolicy.PreselectedProfile = this.policyPreselectedProfile;
this.selectedPolicy.PreselectedProfileIds = this.policyPreselectedProfileIds is null ? null : [..this.policyPreselectedProfileIds];
this.CurrentProfile = this.ResolveProfileSelection();
this.CurrentProfileIds = this.ResolveProfileSelection();
await this.AutoSave();
}
@@ -891,7 +889,9 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
return string.Empty;
var preselectedProvider = string.IsNullOrWhiteSpace(this.selectedPolicy.PreselectedProvider) ? string.Empty : this.selectedPolicy.PreselectedProvider;
var preselectedProfile = string.IsNullOrWhiteSpace(this.selectedPolicy.PreselectedProfile) ? string.Empty : this.selectedPolicy.PreselectedProfile;
var preselectedProfiles = this.selectedPolicy.PreselectedProfileIds is null
? string.Empty
: $"[\"PreselectedProfileIds\"] = {{ {string.Join(", ", this.selectedPolicy.PreselectedProfileIds.Select(profileId => LuaTools.ToLuaStringLiteral(profileId)))} }},";
var id = string.IsNullOrWhiteSpace(this.selectedPolicy.Id) ? Guid.NewGuid().ToString() : this.selectedPolicy.Id;
var allowedToolIds = string.Join(", ", this.selectedPolicy.AllowedToolIds.OrderBy(x => x, StringComparer.Ordinal).Select(x => LuaTools.ToLuaStringLiteral(x)));
@@ -915,10 +915,10 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
-- still meet the confidence requirements of the provider in use.
["AllowedToolIds"] = { {{allowedToolIds}} },
-- Optional: preselect a provider or profile by ID.
-- Optional: preselect a provider or profiles by ID.
-- The IDs must exist in CONFIG["LLM_PROVIDERS"] or CONFIG["PROFILES"].
["PreselectedProvider"] = "{{preselectedProvider}}",
["PreselectedProfile"] = "{{preselectedProfile}}",
{{preselectedProfiles}}
-- Optional: hide the policy definition section in the UI.
-- When set to true, users will only see the document selection interface