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

@@ -172,7 +172,7 @@
@if (this.AllowProfiles && this.ShowProfileSelection)
{
<ProfileSelection MarginLeft="" @bind-CurrentProfile="@this.CurrentProfile"/>
<ProfileSelection MarginLeft="" @bind-SelectedProfileIds="@this.CurrentProfileIds"/>
}
@* No selection where the assistant's own rules already name the tools: *@
@@ -189,7 +189,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
this.MightPreselectValues();
this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(this.Component);
this.CurrentProfile = this.SettingsManager.GetPreselectedProfile(this.Component);
this.CurrentProfileIds = this.SettingsManager.GetPreselectedProfiles(this.Component).Select(profile => profile.Id).ToHashSet(StringComparer.OrdinalIgnoreCase);
this.CurrentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component);
this.SelectedToolIds = this.SettingsManager.GetDefaultToolIds(this.Component);
await this.OnDefaultsAppliedAsync();
@@ -362,7 +362,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
{
IncludeDateTime = false,
SelectedProvider = this.ProviderSettings.Id,
SelectedProfile = this.AllowProfiles ? this.CurrentProfile.Id : Profile.NO_PROFILE.Id,
SelectedProfileIds = this.AllowProfiles ? [..this.CurrentProfileIds] : [],
SystemPrompt = this.SystemPrompt,
WorkspaceId = Guid.Empty,
ChatId = Guid.NewGuid(),
@@ -379,7 +379,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
{
IncludeDateTime = false,
SelectedProvider = this.ProviderSettings.Id,
SelectedProfile = this.AllowProfiles ? this.CurrentProfile.Id : Profile.NO_PROFILE.Id,
SelectedProfileIds = this.AllowProfiles ? [..this.CurrentProfileIds] : [],
SystemPrompt = this.SystemPrompt,
WorkspaceId = workspaceId,
ChatId = chatId,
@@ -400,7 +400,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
protected virtual void ResetProviderAndProfileSelection()
{
this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(this.Component);
this.CurrentProfile = this.SettingsManager.GetPreselectedProfile(this.Component);
this.CurrentProfileIds = this.SettingsManager.GetPreselectedProfiles(this.Component).Select(profile => profile.Id).ToHashSet(StringComparer.OrdinalIgnoreCase);
this.CurrentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component);
this.SelectedToolIds = this.SettingsManager.GetDefaultToolIds(this.Component);
}
@@ -975,7 +975,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
var state = new AssistantSessionStateWriter();
state.Set(PROVIDER_SETTINGS_STATE_KEY, this.ProviderSettings);
state.Set(INPUT_IS_VALID_STATE_KEY, this.InputIsValid);
state.Set(CURRENT_PROFILE_STATE_KEY, this.CurrentProfile);
state.Set(CURRENT_PROFILE_IDS_STATE_KEY, this.CurrentProfileIds);
state.Set(CURRENT_CHAT_TEMPLATE_STATE_KEY, this.CurrentChatTemplate);
state.Set(CHAT_THREAD_STATE_KEY, this.ChatThread);
state.Set(LAST_USER_PROMPT_STATE_KEY, this.LastUserPrompt);
@@ -1003,7 +1003,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
var reader = new AssistantSessionStateReader(state, this.Title);
reader.Restore(PROVIDER_SETTINGS_STATE_KEY, value => this.ProviderSettings = value);
reader.Restore(INPUT_IS_VALID_STATE_KEY, value => this.InputIsValid = value);
reader.Restore(CURRENT_PROFILE_STATE_KEY, value => this.CurrentProfile = value);
reader.Restore(CURRENT_PROFILE_IDS_STATE_KEY, value => this.CurrentProfileIds = value);
reader.Restore(CURRENT_CHAT_TEMPLATE_STATE_KEY, value => this.CurrentChatTemplate = value);
reader.Restore(CHAT_THREAD_STATE_KEY, value => this.ChatThread = value);
reader.Restore(LAST_USER_PROMPT_STATE_KEY, value => this.LastUserPrompt = value);
@@ -15,7 +15,7 @@ public abstract class AssistantLowerBase : MSGComponentBase
protected static readonly AssistantSessionStateKey<AIStudio.Settings.Provider> PROVIDER_SETTINGS_STATE_KEY = new(nameof(ProviderSettings));
protected static readonly AssistantSessionStateKey<bool> INPUT_IS_VALID_STATE_KEY = new(nameof(InputIsValid));
protected static readonly AssistantSessionStateKey<Profile> CURRENT_PROFILE_STATE_KEY = new(nameof(CurrentProfile));
protected static readonly AssistantSessionStateKey<HashSet<string>> CURRENT_PROFILE_IDS_STATE_KEY = new(nameof(CurrentProfileIds));
protected static readonly AssistantSessionStateKey<ChatTemplate> CURRENT_CHAT_TEMPLATE_STATE_KEY = new(nameof(CurrentChatTemplate));
protected static readonly AssistantSessionStateKey<ChatThread?> CHAT_THREAD_STATE_KEY = new(nameof(ChatThread));
protected static readonly AssistantSessionStateKey<IContent?> LAST_USER_PROMPT_STATE_KEY = new(nameof(LastUserPrompt));
@@ -26,7 +26,7 @@ public abstract class AssistantLowerBase : MSGComponentBase
protected AIStudio.Settings.Provider ProviderSettings = Settings.Provider.NONE;
protected bool InputIsValid;
protected Profile CurrentProfile = Profile.NO_PROFILE;
protected HashSet<string> CurrentProfileIds = [];
protected ChatTemplate CurrentChatTemplate = ChatTemplate.NO_CHAT_TEMPLATE;
protected ChatThread? ChatThread;
protected IContent? LastUserPrompt;
@@ -102,7 +102,7 @@ public partial class AssistantBatchProcessing
{
IncludeDateTime = false,
SelectedProvider = this.ProviderSettings.Id,
SelectedProfile = Profile.NO_PROFILE.Id,
SelectedProfileIds = [],
SelectedToolIds = [..this.SelectedToolIds],
SystemPrompt = this.SystemPrompt,
WorkspaceId = Guid.Empty,
@@ -36,7 +36,7 @@
<DirectChatLauncherForm WorkspaceName="@this.launcherWorkspaceName"
WorkspaceNameChanged="@this.LauncherWorkspaceNameChanged"
@bind-ProviderId="@this.launcherProviderId"
@bind-ProfileId="@this.launcherProfileId"
@bind-ProfileIds="@this.launcherProfileIds"
@bind-ChatTemplateId="@this.launcherChatTemplateId"
@bind-DataSourceIds="@this.launcherDataSourceIds"
@bind-ToolIds="@this.launcherToolIds"
@@ -99,7 +99,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
private string descriptionSuggestion = string.Empty;
private string launcherWorkspaceName = string.Empty;
private string launcherProviderId = string.Empty;
private string launcherProfileId = string.Empty;
private HashSet<string>? launcherProfileIds;
private string launcherChatTemplateId = string.Empty;
private IEnumerable<string> launcherDataSourceIds = [];
private HashSet<string> launcherToolIds = [];
@@ -137,7 +137,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
private static readonly AssistantSessionStateKey<string> DESCRIPTION_SUGGESTION_STATE_KEY = new(nameof(descriptionSuggestion));
private static readonly AssistantSessionStateKey<string> LAUNCHER_WORKSPACE_NAME_STATE_KEY = new(nameof(launcherWorkspaceName));
private static readonly AssistantSessionStateKey<string> LAUNCHER_PROVIDER_ID_STATE_KEY = new(nameof(launcherProviderId));
private static readonly AssistantSessionStateKey<string> LAUNCHER_PROFILE_ID_STATE_KEY = new(nameof(launcherProfileId));
private static readonly AssistantSessionStateKey<HashSet<string>?> LAUNCHER_PROFILE_IDS_STATE_KEY = new(nameof(launcherProfileIds));
private static readonly AssistantSessionStateKey<string> LAUNCHER_CHAT_TEMPLATE_ID_STATE_KEY = new(nameof(launcherChatTemplateId));
private static readonly AssistantSessionStateKey<List<string>> LAUNCHER_DATA_SOURCE_IDS_STATE_KEY = new(nameof(launcherDataSourceIds));
private static readonly AssistantSessionStateKey<HashSet<string>> LAUNCHER_TOOL_IDS_STATE_KEY = new(nameof(launcherToolIds));
@@ -243,7 +243,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
this.descriptionSuggestion = string.Empty;
this.launcherWorkspaceName = string.Empty;
this.launcherProviderId = string.Empty;
this.launcherProfileId = string.Empty;
this.launcherProfileIds = null;
this.launcherChatTemplateId = string.Empty;
this.launcherDataSourceIds = [];
this.launcherToolIds = [];
@@ -280,7 +280,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
state.Set(DESCRIPTION_SUGGESTION_STATE_KEY, this.descriptionSuggestion);
state.Set(LAUNCHER_WORKSPACE_NAME_STATE_KEY, this.launcherWorkspaceName);
state.Set(LAUNCHER_PROVIDER_ID_STATE_KEY, this.launcherProviderId);
state.Set(LAUNCHER_PROFILE_ID_STATE_KEY, this.launcherProfileId);
state.Set(LAUNCHER_PROFILE_IDS_STATE_KEY, this.launcherProfileIds);
state.Set(LAUNCHER_CHAT_TEMPLATE_ID_STATE_KEY, this.launcherChatTemplateId);
state.SetList(LAUNCHER_DATA_SOURCE_IDS_STATE_KEY, this.launcherDataSourceIds);
state.SetHashSet(LAUNCHER_TOOL_IDS_STATE_KEY, this.launcherToolIds);
@@ -322,7 +322,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
state.Restore(DESCRIPTION_SUGGESTION_STATE_KEY, value => this.descriptionSuggestion = value);
state.Restore(LAUNCHER_WORKSPACE_NAME_STATE_KEY, value => this.launcherWorkspaceName = value);
state.Restore(LAUNCHER_PROVIDER_ID_STATE_KEY, value => this.launcherProviderId = value);
state.Restore(LAUNCHER_PROFILE_ID_STATE_KEY, value => this.launcherProfileId = value);
state.Restore(LAUNCHER_PROFILE_IDS_STATE_KEY, value => this.launcherProfileIds = value);
state.Restore(LAUNCHER_CHAT_TEMPLATE_ID_STATE_KEY, value => this.launcherChatTemplateId = value);
state.Restore(LAUNCHER_DATA_SOURCE_IDS_STATE_KEY, value => this.launcherDataSourceIds = value);
state.Restore(LAUNCHER_TOOL_IDS_STATE_KEY, value => this.launcherToolIds = ToolSelectionRules.NormalizeSelection(value));
@@ -553,7 +553,7 @@ public partial class AssistantBuilder : AssistantBaseCore<NoSettingsPanel>
return new(
this.launcherWorkspaceName.Trim(),
NullIfEmpty(this.launcherProviderId),
NullIfEmpty(this.launcherProfileId),
this.launcherProfileIds?.Order(StringComparer.OrdinalIgnoreCase).ToArray(),
NullIfEmpty(this.launcherChatTemplateId),
dataSourceIds.Length == 0 ? null : dataSourceIds,
toolIds.Length == 0 ? null : toolIds);
@@ -4,8 +4,8 @@ internal sealed class AssistantBuilderChatLaunchMetadata
{
public string WorkspaceName { get; init; } = string.Empty;
public string? ProviderId { get; init; }
public string? ProfileId { get; init; }
public string[]? ProfileIds { get; init; }
public string? ChatTemplateId { get; init; }
public string[]? DataSourceIds { get; init; }
public string[]? ToolIds { get; init; }
}
}
@@ -128,7 +128,7 @@ internal sealed partial class LuaResponse
return false;
if (!IsOptionalGuid(launch.ProviderId, allowEmpty: false) ||
!IsOptionalGuid(launch.ProfileId, allowEmpty: true) ||
!IsOptionalGuidList(launch.ProfileIds, allowEmptyList: true) ||
!IsOptionalGuid(launch.ChatTemplateId, allowEmpty: true))
return false;
@@ -154,6 +154,11 @@ internal sealed partial class LuaResponse
private static bool IsOptionalGuid(string? value, bool allowEmpty) => value is null ||
Guid.TryParse(value, out var parsed) && (allowEmpty || parsed != Guid.Empty);
private static bool IsOptionalGuidList(string[]? values, bool allowEmptyList) => values is null ||
(allowEmptyList || values.Length > 0) &&
values.All(value => Guid.TryParse(value, out var parsed) && parsed != Guid.Empty) &&
values.Distinct(StringComparer.OrdinalIgnoreCase).Count() == values.Length;
/// <summary>
/// Reads the first complete JSON object out of a model answer that may carry text around it.
/// </summary>
@@ -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
@@ -400,7 +400,7 @@ else
{
var selection = profileSelection;
<div class="@selection.Class" style="@GetOptionalStyle(selection.Style)">
<ProfileFormSelection Validation="@(profile => this.ValidateProfileSelection(selection, profile))" @bind-Profile="@this.CurrentProfile" />
<ProfileFormSelection Validation="@(profileIds => this.ValidateProfileSelection(selection, profileIds))" @bind-ProfileIds="@this.CurrentProfileIds" />
</div>
}
break;
@@ -422,15 +422,36 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
? this.assistantState.ToLuaTable(rootComponent.Children)
: new LuaTable();
var profile = new LuaTable
IReadOnlyList<Profile> selectedProfiles = this.AllowProfiles ? this.SettingsManager.ResolveProfiles(this.CurrentProfileIds) : [];
var profiles = new LuaTable();
for (var index = 0; index < selectedProfiles.Count; index++)
{
["Name"] = this.CurrentProfile.Name,
["NeedToKnow"] = this.CurrentProfile.NeedToKnow,
["Actions"] = this.CurrentProfile.Actions,
["Num"] = this.CurrentProfile.Num,
};
state["profile"] = profile;
var profile = selectedProfiles[index];
profiles[index + 1] = new LuaTable
{
["Id"] = profile.Id,
["Name"] = profile.Name,
["NeedToKnow"] = profile.NeedToKnow,
["Actions"] = profile.Actions,
["Num"] = profile.Num,
};
}
state["profiles"] = profiles;
if (profiles.ArrayLength == 1)
state["profile"] = profiles[1];
else if (profiles.ArrayLength == 0)
{
state["profile"] = new LuaTable
{
["Id"] = Profile.NO_PROFILE.Id,
["Name"] = Profile.NO_PROFILE.Name,
["NeedToKnow"] = Profile.NO_PROFILE.NeedToKnow,
["Actions"] = Profile.NO_PROFILE.Actions,
["Num"] = Profile.NO_PROFILE.Num,
};
}
return state;
}
@@ -642,9 +663,9 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
this.assistantState.MultiSelect[fieldName] = values;
});
private string? ValidateProfileSelection(AssistantProfileSelection profileSelection, Profile? profile)
private string? ValidateProfileSelection(AssistantProfileSelection profileSelection, HashSet<string> profileIds)
{
if (profile != null && profile != Profile.NO_PROFILE) return null;
if (this.SettingsManager.ResolveProfiles(profileIds).Count > 0) return null;
return !string.IsNullOrWhiteSpace(profileSelection.ValidationMessage) ? profileSelection.ValidationMessage : this.T("Please select one of your profiles.");
}
@@ -1081,6 +1081,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T
-- {0} - Document Analysis Session
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T108097007"] = "{0} - Document Analysis Session"
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1126291596"] = "Preselect profiles"
-- Use the analysis and output rules to define how the AI evaluates your documents and formats the results.
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1155482668"] = "Use the analysis and output rules to define how the AI evaluates your documents and formats the results."
@@ -1129,12 +1132,6 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
-- Load output rules from document
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2168201568"] = "Load output rules from document"
-- Choose whether the policy should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2214900121"] = "Choose whether the policy should use the app default profile, no profile, or a specific profile."
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2322771068"] = "Preselect a profile"
-- The analysis rules specify what the AI should pay particular attention to while reviewing the documents you provide, and which aspects it should highlight or save. For example, if you want to extract the potential of green hydrogen for agriculture from a variety of general publications, you can explicitly define this in the analysis rules.
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T238145218"] = "The analysis rules specify what the AI should pay particular attention to while reviewing the documents you provide, and which aspects it should highlight or save. For example, if you want to extract the potential of green hydrogen for agriculture from a variety of general publications, you can explicitly define this in the analysis rules."
@@ -1159,6 +1156,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA
-- Expand this section to view and edit the policy definition.
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T277813037"] = "Expand this section to view and edit the policy definition."
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- Policy name
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name"
@@ -3736,21 +3736,30 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCESELECTION::T86053874"] = "Avail
-- Tools (Optional)
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T1019749907"] = "Tools (Optional)"
-- Use a custom profile selection
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T110831829"] = "Use a custom profile selection"
-- {0} profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T1238255445"] = "{0} profiles"
-- 1 profile
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T1242468481"] = "1 profile"
-- These tools are preselected when the chat opens. Users can change the selection in the chat, and every tool has to meet the confidence requirements of the provider in use.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T1286170698"] = "These tools are preselected when the chat opens. Users can change the selection in the chat, and every tool has to meet the confidence requirements of the provider in use."
-- Chat provider
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T1648955896"] = "Chat provider"
-- Use no profile
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T2205839602"] = "Use no profile"
-- Use no profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T2059344659"] = "Use no profiles"
-- Use chat defaults
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T2283174672"] = "Use chat defaults"
-- Existing workspace (Optional)
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T2364306588"] = "Existing workspace (Optional)"
-- Chat profile
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T2412069346"] = "Chat profile"
-- {0} data source(s) selected
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T2777836629"] = "{0} data source(s) selected"
@@ -3766,12 +3775,21 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T295876489"] = "W
-- Data sources (Optional)
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T3259309302"] = "Data sources (Optional)"
-- Profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T3632612423"] = "Profiles"
-- Chat profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T3834001219"] = "Chat profiles"
-- Use the normal chat data source defaults
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T3898572329"] = "Use the normal chat data source defaults"
-- Use no chat template
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T4258819635"] = "Use no chat template"
-- No profiles selected
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T541000009"] = "No profiles selected"
-- Chat template
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DIRECTCHATLAUNCHERFORM::T923285303"] = "Chat template"
@@ -3976,21 +3994,48 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PREVIEWRELEASECANDIDATE::T3451939995"] =
-- Release candidates are the final step before a feature is proven to be stable.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PREVIEWRELEASECANDIDATE::T696585888"] = "Release candidates are the final step before a feature is proven to be stable."
-- Select one of your profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEFORMSELECTION::T2003449133"] = "Select one of your profiles"
-- {0} profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEFORMSELECTION::T1238255445"] = "{0} profiles"
-- Select your profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEFORMSELECTION::T1981865790"] = "Select your profiles"
-- Open Profile Options
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEFORMSELECTION::T3654011106"] = "Open Profile Options"
-- No profiles selected
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEFORMSELECTION::T541000009"] = "No profiles selected"
-- Use a custom profile selection
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEPRESELECTIONCONFIGURATION::T110831829"] = "Use a custom profile selection"
-- Use no profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEPRESELECTIONCONFIGURATION::T2059344659"] = "Use no profiles"
-- Profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEPRESELECTIONCONFIGURATION::T3632612423"] = "Profiles"
-- Use app default
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEPRESELECTIONCONFIGURATION::T3672477670"] = "Use app default"
-- No profiles selected
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILEPRESELECTIONCONFIGURATION::T541000009"] = "No profiles selected"
-- {0} profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T1238255445"] = "{0} profiles"
-- Clear all
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T2038076485"] = "Clear all"
-- You can select your profiles here
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T2330383897"] = "You can select your profiles here"
-- Manage your profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T3609533889"] = "Manage your profiles"
-- Open Profile Options
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T3654011106"] = "Open Profile Options"
-- You can switch between your profiles here
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can switch between your profiles here"
-- Audio input possible
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T1742581112"] = "Audio input possible"
@@ -4255,6 +4300,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1059411425"]
-- Do you want to show preview features in the app?
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1118505044"] = "Do you want to show preview features in the app?"
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1126291596"] = "Preselect profiles"
-- AI Studio cannot check for updates when running as a Flatpak. Updates are managed outside the app.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1190632518"] = "AI Studio cannot check for updates when running as a Flatpak. Updates are managed outside the app."
@@ -4285,15 +4333,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T14786838"] =
-- A dialog lists what was removed and explains the attack pattern
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T148008546"] = "A dialog lists what was removed and explains the attack pattern"
-- You have selected {0} profiles.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1497583345"] = "You have selected {0} profiles."
-- Select the desired behavior for the navigation bar.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1555038969"] = "Select the desired behavior for the navigation bar."
-- Color theme
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1599198973"] = "Color theme"
-- Would you like to set one of your profiles as the default for the entire app? When you configure a different profile for an assistant, it will always take precedence.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1666052109"] = "Would you like to set one of your profiles as the default for the entire app? When you configure a different profile for an assistant, it will always take precedence."
-- seconds
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T1723256298"] = "seconds"
@@ -4342,6 +4390,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2341504363"]
-- Update installation method
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T237706157"] = "Update installation method"
-- Choose the profiles used by default throughout the app. A component-specific selection replaces this set completely.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2548951489"] = "Choose the profiles used by default throughout the app. A component-specific selection replaces this set completely."
-- Language
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2591284123"] = "Language"
@@ -4363,6 +4414,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2918560776"]
-- Enter one host pattern per line. Exact hosts such as data.intra.example.org and one-label wildcards such as *.intra.example.org are supported. Cloud provider endpoints built into AI Studio, such as OpenAI, Google, etc., never use these additional root certificates.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T2960110864"] = "Enter one host pattern per line. Exact hosts such as data.intra.example.org and one-label wildcards such as *.intra.example.org are supported. Cloud provider endpoints built into AI Studio, such as OpenAI, Google, etc., never use these additional root certificates."
-- You have selected 1 profile.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3060815309"] = "You have selected 1 profile."
-- Save energy?
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3100928009"] = "Save energy?"
@@ -4408,9 +4462,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3914529369"]
-- Additional root certificates are disabled
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T3985928190"] = "Additional root certificates are disabled"
-- Preselect one of your profiles?
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T4004501229"] = "Preselect one of your profiles?"
-- When enabled, spellchecking will be active in all input fields. Depending on your operating system, errors may not be visually highlighted, but right-clicking may still offer possible corrections.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T4067492921"] = "When enabled, spellchecking will be active in all input fields. Depending on your operating system, errors may not be visually highlighted, but right-clicking may still offer possible corrections."
@@ -4444,6 +4495,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T602293588"]
-- Choose the color theme that best suits for you.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T654667432"] = "Choose the color theme that best suits for you."
-- No profiles selected.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T707736869"] = "No profiles selected."
-- Should updates be installed automatically or manually?
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELAPP::T707880477"] = "Should updates be installed automatically or manually?"
@@ -6856,6 +6910,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T3909191077"] = "Yo
-- Remove this attachment.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T3933470258"] = "Remove this attachment."
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T1126291596"] = "Preselect profiles"
-- There is no social event
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T1222800281"] = "There is no social event"
@@ -6877,9 +6934,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T1471770981"
-- Preselect whether participants needs to arrive and depart
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T1648427207"] = "Preselect whether participants needs to arrive and depart"
-- Choose whether the assistant should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T1766361623"] = "Choose whether the assistant should use the app default profile, no profile, or a specific profile."
-- Preselect a start time?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T1901151023"] = "Preselect a start time?"
@@ -6892,9 +6946,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T1998244307"
-- Preselect whether the meeting is virtual
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T2084951012"] = "Preselect whether the meeting is virtual"
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T2322771068"] = "Preselect a profile"
-- When enabled, you can preselect most agenda options. This is might be useful when you need to create similar agendas often.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T2373110543"] = "When enabled, you can preselect most agenda options. This is might be useful when you need to create similar agendas often."
@@ -6904,6 +6955,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T2519703500"
-- Which agenda language should be preselected?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T2801220321"] = "Which agenda language should be preselected?"
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- Preselect another agenda language
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T2915422331"] = "Preselect another agenda language"
@@ -6976,24 +7030,21 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T816053055"]
-- Preselect whether the participants should actively involved
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGAGENDA::T817726429"] = "Preselect whether the participants should actively involved"
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T1126291596"] = "Preselect profiles"
-- Restrict to one bias a day?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T1608129203"] = "Restrict to one bias a day?"
-- Yes, you can only retrieve one bias per day
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T1765683725"] = "Yes, you can only retrieve one bias per day"
-- Choose whether the assistant should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T1766361623"] = "Choose whether the assistant should use the app default profile, no profile, or a specific profile."
-- Reset
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T180921696"] = "Reset"
-- No restriction. You can retrieve as many biases as you want per day.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T2305356277"] = "No restriction. You can retrieve as many biases as you want per day."
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T2322771068"] = "Preselect a profile"
-- Which language should be preselected?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T2345162613"] = "Which language should be preselected?"
@@ -7006,6 +7057,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T2382
-- Preselect the language
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T2571465005"] = "Preselect the language"
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- Close
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGASSISTANTBIAS::T3448155331"] = "Close"
@@ -7186,6 +7240,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGBATCHPROCESSING::T74
-- Leave empty when an input folder should be selected for every batch run.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGBATCHPROCESSING::T762890100"] = "Leave empty when an input folder should be selected for every batch run."
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T1126291596"] = "Preselect profiles"
-- Preselect one of your chat templates?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T1402022556"] = "Preselect one of your chat templates?"
@@ -7201,12 +7258,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T1773585398"]
-- Provider selection when creating new chats
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T189306836"] = "Provider selection when creating new chats"
-- Choose whether chats should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T1915793195"] = "Choose whether chats should use the app default profile, no profile, or a specific profile."
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T2322771068"] = "Preselect a profile"
-- Apply default data source option when sending assistant results to chat
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T2510376349"] = "Apply default data source option when sending assistant results to chat"
@@ -7216,6 +7267,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T263621180"] =
-- Provider selection when loading a chat and sending assistant results to chat
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T2868379953"] = "Provider selection when loading a chat and sending assistant results to chat"
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- Show the latest message after loading?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHAT::T2913693228"] = "Show the latest message after loading?"
@@ -7321,15 +7375,15 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T97542
-- Compiler messages are preselected
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCODING::T1110902070"] = "Compiler messages are preselected"
-- Choose whether the assistant should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCODING::T1766361623"] = "Choose whether the assistant should use the app default profile, no profile, or a specific profile."
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCODING::T2322771068"] = "Preselect a profile"
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCODING::T1126291596"] = "Preselect profiles"
-- Preselect coding options?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCODING::T2790579667"] = "Preselect coding options?"
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCODING::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- Preselect compiler messages?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCODING::T2970689954"] = "Preselect compiler messages?"
@@ -7456,23 +7510,23 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T782820
-- Local Directory
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory"
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1126291596"] = "Preselect profiles"
-- When enabled, you can preselect some ERI server options.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options."
-- Preselect ERI server options?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1664055662"] = "Preselect ERI server options?"
-- Choose whether the assistant should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1766361623"] = "Choose whether the assistant should use the app default profile, no profile, or a specific profile."
-- No ERI server options are preselected
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1793785587"] = "No ERI server options are preselected"
-- Most ERI server options can be customized and saved directly in the ERI server assistant. For this, the ERI server assistant has an auto-save function.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T2093534613"] = "Most ERI server options can be customized and saved directly in the ERI server assistant. For this, the ERI server assistant has an auto-save function."
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T2322771068"] = "Preselect a profile"
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- Close
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T3448155331"] = "Close"
@@ -7612,6 +7666,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T1013787
-- Web content reader is shown
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T1030372436"] = "Web content reader is shown"
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T1126291596"] = "Preselect profiles"
-- When enabled, the web content reader is preselected. This is might be useful when you prefer to load legal content from the web very often.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T1507288278"] = "When enabled, the web content reader is preselected. This is might be useful when you prefer to load legal content from the web very often."
@@ -7627,9 +7684,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T1633101
-- Web content reader is not preselected
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T1701127912"] = "Web content reader is not preselected"
-- Choose whether the assistant should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T1766361623"] = "Choose whether the assistant should use the app default profile, no profile, or a specific profile."
-- Content cleaner agent is not preselected
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T1969816694"] = "Content cleaner agent is not preselected"
@@ -7639,9 +7693,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T2090693
-- When enabled, you can preselect some legal check options. This is might be useful when you prefer a specific LLM model.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T2164667361"] = "When enabled, you can preselect some legal check options. This is might be useful when you prefer a specific LLM model."
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T2322771068"] = "Preselect a profile"
-- Legal check options are preselected
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T252916114"] = "Legal check options are preselected"
@@ -7651,6 +7702,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T2746583
-- Web content reader is hidden
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T2799795311"] = "Web content reader is hidden"
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- Close
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T3448155331"] = "Close"
@@ -7666,11 +7720,8 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T4033382
-- Preselect the web content reader?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGLEGALCHECK::T629158142"] = "Preselect the web content reader?"
-- Choose whether the assistant should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGMYTASKS::T1766361623"] = "Choose whether the assistant should use the app default profile, no profile, or a specific profile."
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGMYTASKS::T2322771068"] = "Preselect a profile"
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGMYTASKS::T1126291596"] = "Preselect profiles"
-- Which language should be preselected?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGMYTASKS::T2345162613"] = "Which language should be preselected?"
@@ -7681,6 +7732,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGMYTASKS::T2382415529
-- Preselect the language
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGMYTASKS::T2571465005"] = "Preselect the language"
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGMYTASKS::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- Close
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGMYTASKS::T3448155331"] = "Close"
@@ -7822,6 +7876,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGREWRITE::T553954963"
-- Preselect the audience expertise
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1017131030"] = "Preselect the audience expertise"
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1126291596"] = "Preselect profiles"
-- When enabled, you can preselect slide builder options. This is might be useful when you prefer a specific language or LLM model.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1393378753"] = "When enabled, you can preselect slide builder options. This is might be useful when you prefer a specific language or LLM model."
@@ -7834,18 +7891,12 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T15493
-- No Slide Planner Assistant options are preselected
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1694374279"] = "No Slide Planner Assistant options are preselected"
-- Choose whether the assistant should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T1766361623"] = "Choose whether the assistant should use the app default profile, no profile, or a specific profile."
-- Preselect the audience organizational level
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2014662371"] = "Preselect the audience organizational level"
-- Which audience organizational level should be preselected?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T216511105"] = "Which audience organizational level should be preselected?"
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2322771068"] = "Preselect a profile"
-- Which language should be preselected?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2345162613"] = "Which language should be preselected?"
@@ -7858,6 +7909,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T25714
-- Preselect the audience age group
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2645589441"] = "Preselect the audience age group"
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- Assistant: Slide Planner Assistant Options
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGSLIDEBUILDER::T3226042276"] = "Assistant: Slide Planner Assistant Options"
@@ -8068,6 +8122,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGTRANSLATION::T918172
-- Source references are hidden
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGVISUALBRIEFING::T1087183156"] = "Source references are hidden"
-- Default profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGVISUALBRIEFING::T1577807404"] = "Default profiles"
-- Default target language
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGVISUALBRIEFING::T1807183063"] = "Default target language"
@@ -8104,9 +8161,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGVISUALBRIEFING::T428
-- Source references are visible
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGVISUALBRIEFING::T864087250"] = "Source references are visible"
-- Default profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGVISUALBRIEFING::T956261591"] = "Default profile"
-- Default audience profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGVISUALBRIEFING::T963676741"] = "Default audience profile"
@@ -8134,6 +8188,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWORKSPACES::T4048028
-- Workspace maintenance
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWORKSPACES::T49653413"] = "Workspace maintenance"
-- Preselect profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T1126291596"] = "Preselect profiles"
-- Which writing style should be preselected?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T1173034744"] = "Which writing style should be preselected?"
@@ -8146,9 +8203,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T1417
-- Preselect another target language
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T1462295644"] = "Preselect another target language"
-- Choose whether the assistant should use the app default profile, no profile, or a specific profile.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T1766361623"] = "Choose whether the assistant should use the app default profile, no profile, or a specific profile."
-- Assistant: Writing E-Mails Options
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T2021226503"] = "Assistant: Writing E-Mails Options"
@@ -8158,12 +8212,12 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T2116
-- Preselect your name for the closing salutation?
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T221974240"] = "Preselect your name for the closing salutation?"
-- Preselect a profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T2322771068"] = "Preselect a profile"
-- Preselect a writing style
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T28456020"] = "Preselect a writing style"
-- Use the app default profiles, no profiles, or a custom selection that completely replaces the app default.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T2872550582"] = "Use the app default profiles, no profiles, or a custom selection that completely replaces the app default."
-- E-Mail options are preselected
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGWRITINGEMAILS::T2985974420"] = "E-Mail options are preselected"
@@ -9805,9 +9859,6 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::CONFIGURATIONSELECTDATAFACTORY::T3491430707
-- Install updates automatically
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::CONFIGURATIONSELECTDATAFACTORY::T3569059463"] = "Install updates automatically"
-- Use app default profile
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::CONFIGURATIONSELECTDATAFACTORY::T3587225583"] = "Use app default profile"
-- Disable workspaces
UI_TEXT_CONTENT["AISTUDIO::SETTINGS::CONFIGURATIONSELECTDATAFACTORY::T3612390107"] = "Disable workspaces"
@@ -10528,9 +10579,15 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T1
-- The provided ASSISTANT lua table does not contain a valid UI table.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T1841068402"] = "The provided ASSISTANT lua table does not contain a valid UI table."
-- The ASSISTANT table contains invalid ProfileIds. Expected a list of unique, non-empty GUIDs.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T2303567771"] = "The ASSISTANT table contains invalid ProfileIds. Expected a list of unique, non-empty GUIDs."
-- The provided ASSISTANT lua table does not contain a valid description.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T2514141654"] = "The provided ASSISTANT lua table does not contain a valid description."
-- The ASSISTANT table contains both ProfileId and ProfileIds. Use only one of them.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T2567419456"] = "The ASSISTANT table contains both ProfileId and ProfileIds. Use only one of them."
-- The provided ASSISTANT lua table does not contain a valid title.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T2814605990"] = "The provided ASSISTANT lua table does not contain a valid title."
@@ -10822,9 +10879,21 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINCATEGORYEXTENSIONS::T91464
-- The SETTINGS table does not exist or is not a valid table.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINCONFIGURATION::T1148682011"] = "The SETTINGS table does not exist or is not a valid table."
-- The configured visual briefing profile preselection is invalid.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINCONFIGURATION::T1806426557"] = "The configured visual briefing profile preselection is invalid."
-- The configured app profile preselection is invalid.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINCONFIGURATION::T2768414424"] = "The configured app profile preselection is invalid."
-- The CONFIG table does not exist or is not a valid table.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINCONFIGURATION::T3331620576"] = "The CONFIG table does not exist or is not a valid table."
-- The SETTINGS table contains both '{0}' and '{1}'. Use only one of them.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINCONFIGURATION::T4104310827"] = "The SETTINGS table contains both '{0}' and '{1}'. Use only one of them."
-- The configured chat profile preselection is invalid.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINCONFIGURATION::T4292017635"] = "The configured chat profile preselection is invalid."
-- The field IETF_TAG does not exist or is not a valid string.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINLANGUAGE::T1796010240"] = "The field IETF_TAG does not exist or is not a valid string."
@@ -11170,8 +11239,8 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T6
-- The following data sources selected by the assistant chat launcher are currently unavailable or not permitted for the selected provider: {0}
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::DIRECTCHATSERVICE::T103791004"] = "The following data sources selected by the assistant chat launcher are currently unavailable or not permitted for the selected provider: {0}"
-- The assistant chat launcher references profile '{0}', but that profile does not exist.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::DIRECTCHATSERVICE::T2466659933"] = "The assistant chat launcher references profile '{0}', but that profile does not exist."
-- The assistant chat launcher references one or more profiles that do not exist.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::DIRECTCHATSERVICE::T2271819418"] = "The assistant chat launcher references one or more profiles that do not exist."
-- The assistant chat launcher references data source '{0}', but that data source does not exist.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::DIRECTCHATSERVICE::T289191545"] = "The assistant chat launcher references data source '{0}', but that data source does not exist."
@@ -1,7 +1,7 @@
@attribute [Route(Routes.ASSISTANT_MY_TASKS)]
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogMyTasks>
<ProfileFormSelection Validation="@this.ValidateProfile" @bind-Profile="@this.CurrentProfile"/>
<ProfileFormSelection Validation="@this.ValidateProfiles" @bind-ProfileIds="@this.CurrentProfileIds"/>
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Text or email")" Variant="Variant.Outlined" Lines="12" AutoGrow="@true" MaxLines="24" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudText Typo="Typo.h6" Class="mb-1 mt-1">@T("Attach documents")</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2">
@@ -164,9 +164,9 @@ public partial class AssistantMyTasks : AssistantBaseCore<SettingsDialogMyTasks>
await this.Form.Validate();
}
private string? ValidateProfile(Profile profile)
private string? ValidateProfiles(HashSet<string> profileIds)
{
if(profile == Profile.NO_PROFILE)
if(this.SettingsManager.ResolveProfiles(profileIds).Count == 0)
return T("Please select one of your profiles.");
return null;
@@ -88,7 +88,8 @@ public partial class SlideAssistant : AssistantBaseCore<SettingsDialogSlideBuild
{
return new ChatThread
{
SystemPrompt = SystemPrompts.DEFAULT
SystemPrompt = SystemPrompts.DEFAULT,
SelectedProfileIds = [..this.CurrentProfileIds],
};
}
@@ -97,6 +98,7 @@ public partial class SlideAssistant : AssistantBaseCore<SettingsDialogSlideBuild
ChatId = Guid.NewGuid(),
Name = string.Format(T("{0} - Slide Builder Session"), this.inputTitle),
SystemPrompt = SystemPrompts.DEFAULT,
SelectedProfileIds = [..this.CurrentProfileIds],
Blocks =
[
// Visible user block:
@@ -18,7 +18,7 @@ internal sealed class StructuredLlmStageRunner(
/// </summary>
/// <typeparam name="T">The strict response type.</typeparam>
/// <param name="provider">The selected provider configuration.</param>
/// <param name="profile">The selected user profile.</param>
/// <param name="profiles">The selected user profiles.</param>
/// <param name="systemContract">The stage-specific system contract.</param>
/// <param name="prompt">The user prompt containing stage inputs.</param>
/// <param name="attachments">The first-turn attachments.</param>
@@ -30,7 +30,7 @@ internal sealed class StructuredLlmStageRunner(
/// <returns>The validated stage result.</returns>
public async Task<StructuredLlmStageResult<T>> RunAsync<T>(
ProviderSettings provider,
Profile profile,
IReadOnlyList<Profile> profiles,
string systemContract,
string prompt,
IReadOnlyList<FileAttachment> attachments,
@@ -54,8 +54,7 @@ internal sealed class StructuredLlmStageRunner(
Before sending, silently verify that the root object is closed and every property conforms to the grammar.
Answer with the bare JSON object and nothing else: no explanation, no Markdown, and no code fence.
User profile:
{profile.ToSystemPrompt()}
{Profile.ToSystemPrompt(profiles)}
""";
var time = DateTimeOffset.UtcNow;
@@ -286,4 +285,4 @@ internal sealed class StructuredLlmStageRunner(
/// <param name="eventId">The stable event identifier.</param>
/// <returns>The logging event.</returns>
private static EventId Event(VisualBriefingLogEventId eventId) => new((int)eventId, eventId.ToString());
}
}
@@ -294,9 +294,9 @@ public sealed partial class VisualBriefingArtifactService
var sensitiveValues = new[]
{
manifest.Settings.ProviderId,
manifest.Settings.ProfileId,
manifest.Settings.ModelId,
}
.Concat(manifest.Settings.ProfileIds)
.Where(candidate => !string.IsNullOrWhiteSpace(candidate));
return sensitiveValues.Any(candidate => text.Contains(candidate, StringComparison.Ordinal));
}
@@ -531,4 +531,4 @@ public sealed partial class VisualBriefingArtifactService
[GeneratedRegex("""\[\s*(?<name>[A-Za-z_:][A-Za-z0-9_:.-]*)\s*(?:(?<operator>[~|^$*]?=)\s*(?:"(?<double>[^"]*)"|'(?<single>[^']*)'|(?<unquoted>[^\]\s]+))\s*(?<modifier>[iIsS])?\s*)?\]""", RegexOptions.CultureInvariant)]
private static partial Regex AttributeSelectorRegex();
}
}
@@ -211,7 +211,7 @@
}
</MudStack>
<ProfileFormSelection @bind-Profile="@this.editor.Profile" Disabled="@this.IsCurrentBusy"/>
<ProfileFormSelection @bind-ProfileIds="@this.editor.ProfileIds" Disabled="@this.IsCurrentBusy"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name())" @bind-Value="@this.editor.TargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="true" @bind-OtherInput="@this.editor.CustomTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="@T("Custom target language")" ValidateOther="@this.ValidateCustomTargetLanguage" SelectionUpdated="@(_ => this.ScheduleFormValidation())" Disabled="@this.IsCurrentBusy"/>
<EnumSelection T="AudienceProfile" NameFunc="@(value => value.Name())" @bind-Value="@this.editor.AudienceProfile" Label="@T("Audience profile")" Disabled="@this.IsCurrentBusy"/>
<EnumSelection T="AudienceAgeGroup" NameFunc="@(value => value.Name())" @bind-Value="@this.editor.AudienceAgeGroup" Label="@T("Audience age group")" Disabled="@this.IsCurrentBusy"/>
@@ -337,4 +337,4 @@
</main>
</div>
</CascadingValue>
</CascadingValue>
</CascadingValue>
@@ -163,10 +163,10 @@ public partial class VisualBriefingAssistant
var generationBriefing = this.selectedBriefing;
var parentRevisionId = parentRevisionOverride ?? (generationBriefing.Versions.Count == 0 ? null : this.selectedRevisionId);
var generationProvider = this.editor.Provider;
var generationProfile = this.editor.Profile;
var generationProfiles = this.SettingsManager.ResolveProfiles(this.editor.ProfileIds);
await this.RunBriefingOperationAsync(generationBriefing, mode, token => this.BuildOrchestrator.BuildAsync(generationBriefing, mode,
parentRevisionId, generationProvider, generationProfile, reusableBuildId, token),
parentRevisionId, generationProvider, generationProfiles, reusableBuildId, token),
T("A new visual briefing version was created."),
T("The visual briefing generation was canceled."),
T("The visual briefing operation failed unexpectedly. Copy the technical details for support."));
@@ -314,4 +314,4 @@ public partial class VisualBriefingAssistant
/// Creates the assistant-session key used by a visual briefing build.
/// </summary>
private static AssistantSessionKey CreateBuildSessionKey(Guid briefingId) => new(ComponentKind.VISUAL_BRIEFING_ASSISTANT, briefingId.ToString("D"));
}
}
@@ -62,13 +62,13 @@ public partial class VisualBriefingAssistant
{
var defaults = this.SettingsManager.ConfigurationData.VisualBriefing;
var defaultProvider = this.SettingsManager.GetPreselectedProvider(ComponentKind.VISUAL_BRIEFING_ASSISTANT);
var defaultProfile = this.SettingsManager.GetPreselectedProfile(ComponentKind.VISUAL_BRIEFING_ASSISTANT);
var defaultProfiles = this.SettingsManager.GetPreselectedProfiles(ComponentKind.VISUAL_BRIEFING_ASSISTANT);
var suggestedName = string.Format(T("Briefing {0}"), DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm"));
var settings = new VisualBriefingLocalSettings
{
ProviderId = defaultProvider.Id,
ModelId = defaultProvider.Model.Id,
ProfileId = defaultProfile.Id,
ProfileIds = defaultProfiles.Select(profile => profile.Id).ToHashSet(StringComparer.OrdinalIgnoreCase),
TargetLanguage = defaults.PreselectedTargetLanguage,
CustomTargetLanguage = defaults.PreselectedOtherLanguage,
AudienceProfile = defaults.PreselectedAudienceProfile,
@@ -386,4 +386,4 @@ public partial class VisualBriefingAssistant
Settings = this.editor.ToSettings(),
Sources = this.editor.ToSources().Select(source => new { source.Path, source.Kind }).ToArray(),
}, VisualBriefingJson.Canonical);
}
}
@@ -189,7 +189,7 @@ internal sealed partial class VisualBriefingBuildOrchestrator
VisualBriefingEditMode mode,
Guid? parentRevisionId,
ProviderSettings provider,
Profile profile,
IReadOnlyList<Profile> profiles,
string sourceFingerprint,
string? reusedContentHash) =>
VisualBriefingHashing.ComputeSections(
@@ -197,7 +197,7 @@ internal sealed partial class VisualBriefingBuildOrchestrator
parentRevisionId?.ToString("D"),
provider.Id,
provider.Model.Id,
profile.Id,
string.Join(";", profiles.Select(profile => profile.Id)),
sourceFingerprint,
VisualBriefingHashing.Compute(manifest.Settings.Instruction),
manifest.Settings.TargetLanguage.ToString(),
@@ -85,11 +85,11 @@ internal sealed partial class VisualBriefingBuildOrchestrator
/// <param name="mode">The edit mode.</param>
/// <param name="parentRevisionId">The selected parent revision.</param>
/// <param name="provider">The selected provider.</param>
/// <param name="profile">The selected profile.</param>
/// <param name="profiles">The selected profiles.</param>
/// <param name="reusableContentBuildId">An incompatible update build whose content should be reused as a rebuild.</param>
/// <param name="token">The cancellation token.</param>
/// <returns>The terminal build result.</returns>
public async Task<VisualBriefingBuildResult> BuildAsync(VisualBriefingManifest manifest, VisualBriefingEditMode mode, Guid? parentRevisionId, ProviderSettings provider, Profile profile, Guid? reusableContentBuildId = null, CancellationToken token = default)
public async Task<VisualBriefingBuildResult> BuildAsync(VisualBriefingManifest manifest, VisualBriefingEditMode mode, Guid? parentRevisionId, ProviderSettings provider, IReadOnlyList<Profile> profiles, Guid? reusableContentBuildId = null, CancellationToken token = default)
{
var operationId = Guid.NewGuid();
var proposedBuildId = Guid.NewGuid();
@@ -142,7 +142,7 @@ internal sealed partial class VisualBriefingBuildOrchestrator
VisualBriefingEvidenceStage.ComputeInputFingerprint(
manifest,
provider,
profile,
profiles,
sourceFingerprint),
reusableEvidenceInputFingerprint,
StringComparison.Ordinal)))
@@ -152,7 +152,7 @@ internal sealed partial class VisualBriefingBuildOrchestrator
"The sources or evidence settings changed after the evidence was validated. Start a full rebuild.",
$"EvidenceArtifactId={reusableEvidence.ArtifactId:D}; Rule={VisualBriefingValidationRule.REFERENCE_INVALID}.");
var inputFingerprint = ComputeBuildInputFingerprint(manifest, mode, parentRevisionId, provider, profile, sourceFingerprint, reusableEvidence?.PayloadHash);
var inputFingerprint = ComputeBuildInputFingerprint(manifest, mode, parentRevisionId, provider, profiles, sourceFingerprint, reusableEvidence?.PayloadHash);
var now = DateTimeOffset.UtcNow;
var candidate = new VisualBriefingBuildRecord
{
@@ -247,7 +247,7 @@ internal sealed partial class VisualBriefingBuildOrchestrator
else
{
diagnostics.Stage = VisualBriefingBuildStage.EVIDENCE;
evidence = await this.evidenceStage.ExecuteAsync(manifest, provider, profile, prepared!, build, token);
evidence = await this.evidenceStage.ExecuteAsync(manifest, provider, profiles, prepared!, build, token);
}
diagnostics.ContentHashes["evidence"] = evidence.PayloadHash;
@@ -265,7 +265,7 @@ internal sealed partial class VisualBriefingBuildOrchestrator
else
{
diagnostics.Stage = VisualBriefingBuildStage.PLAN;
plan = await this.planStage.ExecuteAsync(manifest, provider, profile, evidence, build, token);
plan = await this.planStage.ExecuteAsync(manifest, provider, profiles, evidence, build, token);
}
diagnostics.ContentHashes["plan"] = plan.PayloadHash;
@@ -286,7 +286,7 @@ internal sealed partial class VisualBriefingBuildOrchestrator
try
{
content = await this.contentStage.ExecuteAsync(manifest, provider, profile, evidence, plan, build, token);
content = await this.contentStage.ExecuteAsync(manifest, provider, profiles, evidence, plan, build, token);
}
catch (VisualBriefingBuildException exception) when (mode is VisualBriefingEditMode.UPDATE_CONTENT && exception.Code is VisualBriefingFailureCode.RESPONSE_CONTRACT_INVALID && build.Failure?.ValidationRule is VisualBriefingValidationRule.SLOT_FULFILLMENT_INVALID)
{
@@ -330,7 +330,7 @@ internal sealed partial class VisualBriefingBuildOrchestrator
else
{
diagnostics.Stage = VisualBriefingBuildStage.DESIGN;
presentation = await this.presentationStage.ExecuteAsync(manifest, provider, profile, plan, content, mode is VisualBriefingEditMode.CHANGE_DESIGN ? parentContext.Presentation : null, build, token);
presentation = await this.presentationStage.ExecuteAsync(manifest, provider, profiles, plan, content, mode is VisualBriefingEditMode.CHANGE_DESIGN ? parentContext.Presentation : null, build, token);
}
diagnostics.ContentHashes["design"] = presentation.PayloadHash;
@@ -502,4 +502,4 @@ internal sealed partial class VisualBriefingBuildOrchestrator
/// <returns>A value task representing cleanup.</returns>
public async ValueTask DisposeAsync() => await dispose();
}
}
}
@@ -16,7 +16,7 @@ internal sealed class VisualBriefingContentStage(StructuredLlmStageRunner stageR
/// </summary>
private const string SHOW_ALL_VALUE = "*";
public async Task<VisualBriefingContentArtifact> ExecuteAsync(VisualBriefingManifest manifest, ProviderSettings provider, Profile profile, VisualBriefingEvidenceArtifact evidence, VisualBriefingPlanArtifact plan, VisualBriefingBuildRecord build, CancellationToken token)
public async Task<VisualBriefingContentArtifact> ExecuteAsync(VisualBriefingManifest manifest, ProviderSettings provider, IReadOnlyList<Profile> profiles, VisualBriefingEvidenceArtifact evidence, VisualBriefingPlanArtifact plan, VisualBriefingBuildRecord build, CancellationToken token)
{
if (build.ContentArtifactId is { } completedId)
{
@@ -29,7 +29,7 @@ internal sealed class VisualBriefingContentStage(StructuredLlmStageRunner stageR
manifest.Settings.TargetLanguage.ToString(), manifest.Settings.CustomTargetLanguage, manifest.Settings.AudienceProfile.ToString(),
manifest.Settings.AudienceAgeGroup.ToString(), manifest.Settings.AudienceOrganizationalLevel.ToString(), manifest.Settings.AudienceExpertise.ToString(),
manifest.Settings.ShowSourceReferences.ToString(), SourceReferenceFingerprint(manifest), manifest.Settings.ProtectionLevel.ToString(),
manifest.Settings.CustomProtectionLevel, provider.Id, provider.Model.Id, profile.Id, VisualBriefingHashing.Compute(profile.ToSystemPrompt()),
manifest.Settings.CustomProtectionLevel, provider.Id, provider.Model.Id, string.Join(";", profiles.Select(profile => profile.Id)), VisualBriefingHashing.Compute(Profile.ToSystemPrompt(profiles)),
VisualBriefingVersions.CONTENT_CONTRACT.ToString());
var stage = VisualBriefingEvidenceStage.Start(build, VisualBriefingBuildStage.CONTENT, computedHash);
@@ -37,7 +37,7 @@ internal sealed class VisualBriefingContentStage(StructuredLlmStageRunner stageR
await store.SaveBuildAsync(build, token);
progressService.Publish(build);
var run = await stageRunner.RunAsync<VisualBriefingContentResponse>(provider, profile, BuildSystemContract(),
var run = await stageRunner.RunAsync<VisualBriefingContentResponse>(provider, profiles, BuildSystemContract(),
BuildPrompt(manifest, evidence, plan), [], VisualBriefingBuildStage.CONTENT, build.OperationId, build.BuildId,
response => this.ValidateResponseAndProject(manifest, plan, evidence, response), token);
@@ -399,4 +399,4 @@ internal sealed class VisualBriefingContentStage(StructuredLlmStageRunner stageR
/// <see cref="RESET_LABEL"/>.
/// </summary>
private const string SHOW_ALL_LABEL = "Show all";
}
}
@@ -13,8 +13,7 @@ namespace AIStudio.Assistants.VisualBriefing;
/// <remarks>
/// This is the single source of truth for the briefing editor. It exists because the editor cannot
/// bind to <see cref="VisualBriefingLocalSettings"/> directly: that type stores the provider, model,
/// and profile as identifiers, while the UI binds whole <see cref="ProviderSettings"/> and
/// <see cref="Profile"/> objects. Keeping one draft object means saving, restoring, and change
/// and profiles as identifiers, while the UI binds the resolved provider and profile IDs. Keeping one draft object means saving, restoring, and change
/// detection all read the same fields instead of three hand-maintained lists.
/// </remarks>
public sealed class VisualBriefingEditorState
@@ -28,8 +27,8 @@ public sealed class VisualBriefingEditorState
/// <summary>Gets or sets the selected provider and model.</summary>
public ProviderSettings Provider { get; set; } = ProviderSettings.NONE;
/// <summary>Gets or sets the selected profile.</summary>
public Profile Profile { get; set; } = Profile.NO_PROFILE;
/// <summary>Gets or sets the selected profile IDs.</summary>
public HashSet<string> ProfileIds { get; set; } = [];
/// <summary>Gets or sets the current scope or change instruction.</summary>
public string Instruction { get; set; } = string.Empty;
@@ -93,7 +92,7 @@ public sealed class VisualBriefingEditorState
CustomProtectionLevel = briefing.Settings.CustomProtectionLevel,
Provider = ResolveProvider(briefing, settingsManager),
Profile = settingsManager.GetProfileById(briefing.Settings.ProfileId),
ProfileIds = settingsManager.ResolveProfiles(briefing.Settings.ProfileIds).Select(profile => profile.Id).ToHashSet(StringComparer.OrdinalIgnoreCase),
SourceMaterial =
[
@@ -155,7 +154,7 @@ public sealed class VisualBriefingEditorState
{
ProviderId = this.Provider.Id,
ModelId = this.Provider.Model.Id,
ProfileId = this.Profile.Id,
ProfileIds = [..this.ProfileIds],
TargetLanguage = this.TargetLanguage,
CustomTargetLanguage = this.CustomTargetLanguage,
AudienceProfile = this.AudienceProfile,
@@ -193,4 +192,4 @@ public sealed class VisualBriefingEditorState
.Select(attachment => attachment.FilePath)
.Order(StringComparer.Ordinal)
.Select(path => (path, kind));
}
}
@@ -19,12 +19,12 @@ internal sealed class VisualBriefingEvidenceStage(StructuredLlmStageRunner stage
/// </summary>
/// <param name="manifest">The briefing manifest.</param>
/// <param name="provider">The selected provider and model.</param>
/// <param name="profile">The selected prompt profile.</param>
/// <param name="profiles">The selected prompt profiles.</param>
/// <param name="preparedSources">The validated prepared sources.</param>
/// <param name="build">The persistent build record.</param>
/// <param name="token">The cancellation token.</param>
/// <returns>The validated immutable evidence artifact.</returns>
public async Task<VisualBriefingEvidenceArtifact> ExecuteAsync(VisualBriefingManifest manifest, ProviderSettings provider, Profile profile, VisualBriefingPreparedSources preparedSources, VisualBriefingBuildRecord build, CancellationToken token)
public async Task<VisualBriefingEvidenceArtifact> ExecuteAsync(VisualBriefingManifest manifest, ProviderSettings provider, IReadOnlyList<Profile> profiles, VisualBriefingPreparedSources preparedSources, VisualBriefingBuildRecord build, CancellationToken token)
{
if (build.EvidenceArtifactId is { } completedId)
{
@@ -33,12 +33,12 @@ internal sealed class VisualBriefingEvidenceStage(StructuredLlmStageRunner stage
return completed;
}
var stage = Start(build, VisualBriefingBuildStage.EVIDENCE, ComputeInputFingerprint(manifest, provider, profile, preparedSources.SourceFingerprint));
var stage = Start(build, VisualBriefingBuildStage.EVIDENCE, ComputeInputFingerprint(manifest, provider, profiles, preparedSources.SourceFingerprint));
await store.SaveBuildAsync(build, token);
progressService.Publish(build);
var run = await stageRunner.RunAsync<VisualBriefingEvidenceResponse>(
provider, profile, BuildSystemContract(), BuildPrompt(manifest, preparedSources), preparedSources.Attachments, VisualBriefingBuildStage.EVIDENCE,
provider, profiles, BuildSystemContract(), BuildPrompt(manifest, preparedSources), preparedSources.Attachments, VisualBriefingBuildStage.EVIDENCE,
build.OperationId, build.BuildId, response => VisualBriefingValidation.ValidateEvidence(manifest, response), token);
stage.Attempts = run.Attempts;
@@ -71,10 +71,10 @@ internal sealed class VisualBriefingEvidenceStage(StructuredLlmStageRunner stage
return artifact;
}
internal static string ComputeInputFingerprint(VisualBriefingManifest manifest, ProviderSettings provider, Profile profile, string sourceFingerprint) =>
internal static string ComputeInputFingerprint(VisualBriefingManifest manifest, ProviderSettings provider, IReadOnlyList<Profile> profiles, string sourceFingerprint) =>
VisualBriefingHashing.ComputeSections(sourceFingerprint, VisualBriefingHashing.Compute(manifest.Settings.Instruction),
manifest.Settings.TargetLanguage.ToString(), manifest.Settings.CustomTargetLanguage, provider.Id,
provider.Model.Id, profile.Id, VisualBriefingHashing.Compute(profile.ToSystemPrompt()),
provider.Model.Id, string.Join(";", profiles.Select(profile => profile.Id)), VisualBriefingHashing.Compute(Profile.ToSystemPrompt(profiles)),
VisualBriefingVersions.EVIDENCE_CONTRACT.ToString());
private static string BuildSystemContract() =>
@@ -192,4 +192,4 @@ internal sealed class VisualBriefingEvidenceStage(StructuredLlmStageRunner stage
? $"{details}."
: $"{details}; {diagnostic.ToTechnicalDetails()}.";
}
}
}
@@ -1,4 +1,7 @@
using AIStudio.Assistants.SlideBuilder;
using AIStudio.Settings;
using System.Text.Json.Serialization;
namespace AIStudio.Assistants.VisualBriefing;
@@ -18,9 +21,23 @@ public sealed class VisualBriefingLocalSettings
public string ModelId { get; set; } = string.Empty;
/// <summary>
/// Defines <c>ProfileId</c> for the visual briefing feature.
/// Defines <c>ProfileIds</c> for the visual briefing feature.
/// </summary>
public string ProfileId { get; set; } = string.Empty;
public HashSet<string> ProfileIds { get; set; } = [];
[JsonPropertyName("ProfileId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? LegacyProfileId
{
get => null;
set
{
if (this.ProfileIds.Count == 0 &&
!string.IsNullOrWhiteSpace(value) &&
!value.Equals(Profile.NO_PROFILE.Id, StringComparison.OrdinalIgnoreCase))
this.ProfileIds.Add(value);
}
}
/// <summary>
/// Defines <c>TargetLanguage</c> for the visual briefing feature.
@@ -76,4 +93,4 @@ public sealed class VisualBriefingLocalSettings
/// Defines <c>CustomProtectionLevel</c> for the visual briefing feature.
/// </summary>
public string CustomProtectionLevel { get; set; } = string.Empty;
}
}
@@ -19,12 +19,12 @@ internal sealed class VisualBriefingPlanStage(StructuredLlmStageRunner stageRunn
/// </summary>
/// <param name="manifest">The briefing manifest.</param>
/// <param name="provider">The selected provider and model.</param>
/// <param name="profile">The selected prompt profile.</param>
/// <param name="profiles">The selected prompt profiles.</param>
/// <param name="evidence">The validated evidence artifact.</param>
/// <param name="build">The persistent build record.</param>
/// <param name="token">The cancellation token.</param>
/// <returns>The validated immutable plan artifact.</returns>
public async Task<VisualBriefingPlanArtifact> ExecuteAsync(VisualBriefingManifest manifest, ProviderSettings provider, Profile profile, VisualBriefingEvidenceArtifact evidence, VisualBriefingBuildRecord build, CancellationToken token)
public async Task<VisualBriefingPlanArtifact> ExecuteAsync(VisualBriefingManifest manifest, ProviderSettings provider, IReadOnlyList<Profile> profiles, VisualBriefingEvidenceArtifact evidence, VisualBriefingBuildRecord build, CancellationToken token)
{
if (build.PlanArtifactId is { } completedId)
{
@@ -36,13 +36,13 @@ internal sealed class VisualBriefingPlanStage(StructuredLlmStageRunner stageRunn
var stage = VisualBriefingEvidenceStage.Start(build, VisualBriefingBuildStage.PLAN, VisualBriefingHashing.ComputeSections(evidence.PayloadHash,
VisualBriefingHashing.Compute(manifest.Settings.Instruction), manifest.Settings.AudienceProfile.ToString(),
manifest.Settings.AudienceAgeGroup.ToString(), manifest.Settings.AudienceOrganizationalLevel.ToString(),
manifest.Settings.AudienceExpertise.ToString(), provider.Id, provider.Model.Id, profile.Id,
VisualBriefingHashing.Compute(profile.ToSystemPrompt()), VisualBriefingVersions.PLAN_CONTRACT.ToString()));
manifest.Settings.AudienceExpertise.ToString(), provider.Id, provider.Model.Id, string.Join(";", profiles.Select(profile => profile.Id)),
VisualBriefingHashing.Compute(Profile.ToSystemPrompt(profiles)), VisualBriefingVersions.PLAN_CONTRACT.ToString()));
await store.SaveBuildAsync(build, token);
progressService.Publish(build);
var run = await stageRunner.RunAsync<VisualBriefingPlanResponse>(provider, profile, BuildSystemContract(), BuildPrompt(manifest, evidence),
var run = await stageRunner.RunAsync<VisualBriefingPlanResponse>(provider, profiles, BuildSystemContract(), BuildPrompt(manifest, evidence),
[], VisualBriefingBuildStage.PLAN, build.OperationId, build.BuildId, response => VisualBriefingValidation.ValidatePlan(evidence, response), token);
stage.Attempts = run.Attempts;
@@ -113,4 +113,4 @@ internal sealed class VisualBriefingPlanStage(StructuredLlmStageRunner stageRunn
Scope instruction: {manifest.Settings.Instruction}
Evidence: {JsonSerializer.Serialize(new { evidence.Facts, evidence.Metrics, evidence.Tables, evidence.AssetPlan }, VisualBriefingJson.Canonical)}
""";
}
}
@@ -11,7 +11,7 @@ namespace AIStudio.Assistants.VisualBriefing;
/// </summary>
internal sealed class VisualBriefingPresentationStage(StructuredLlmStageRunner stageRunner, VisualBriefingStore store, VisualBriefingBuildProgressService progressService, ILogger<VisualBriefingPresentationStage> logger)
{
public async Task<VisualBriefingPresentationArtifact> ExecuteAsync(VisualBriefingManifest manifest, ProviderSettings provider, Profile profile,
public async Task<VisualBriefingPresentationArtifact> ExecuteAsync(VisualBriefingManifest manifest, ProviderSettings provider, IReadOnlyList<Profile> profiles,
VisualBriefingPlanArtifact plan, VisualBriefingContentArtifact content, VisualBriefingPresentationArtifact? parentPresentation,
VisualBriefingBuildRecord build, CancellationToken token)
{
@@ -34,15 +34,15 @@ internal sealed class VisualBriefingPresentationStage(StructuredLlmStageRunner s
parentPresentation?.PayloadHash ?? string.Empty,
provider.Id,
provider.Model.Id,
profile.Id,
VisualBriefingHashing.Compute(profile.ToSystemPrompt()),
string.Join(";", profiles.Select(profile => profile.Id)),
VisualBriefingHashing.Compute(Profile.ToSystemPrompt(profiles)),
VisualBriefingVersions.DESIGN_CONTRACT.ToString());
build.UpdatedAtUtc = DateTimeOffset.UtcNow;
await store.SaveBuildAsync(build, token);
progressService.Publish(build);
var run = await stageRunner.RunAsync<VisualBriefingDesignResponse>(provider, profile, BuildSystemContract(),
var run = await stageRunner.RunAsync<VisualBriefingDesignResponse>(provider, profiles, BuildSystemContract(),
BuildPrompt(manifest, plan, parentPresentation), [], VisualBriefingBuildStage.DESIGN, build.OperationId, build.BuildId,
response => ValidateDesign(manifest, plan, content, response), token);
@@ -205,4 +205,4 @@ internal sealed class VisualBriefingPresentationStage(StructuredLlmStageRunner s
return record;
}
}
}