Turned getter-like extension methods into extension properties (#1157)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-11-04 13:00:56 +01:00
1 parent 0375318b1b
commit f649febf88
286 files changed
+1223 -953

No files matched your search

+1 -1
View File
@@ -28,7 +28,7 @@ Key structure:
## Important Development Notes ## Important Development Notes
- **Naming conventions** - Constants, enum members, and `static readonly` fields use `UPPER_SNAKE_CASE` such as `MY_CONSTANT`. - **Naming conventions** - Constants, enum members, and `static readonly` fields use `UPPER_SNAKE_CASE` such as `MY_CONSTANT`.
- **Extension members** - Declare extension methods in an `extension` block of their static class, one block per receiver, never with a `this` parameter: MWAIS0016 refuses the classic form. The `<param>` of the receiver, and of a generic block its `<typeparam>`, belongs on the block, not on its members. - **Extension members** - Declare extension methods in an `extension` block of their static class, one block per receiver, never with a `this` parameter: MWAIS0016 refuses the classic form. The `<param>` of the receiver, and of a generic block its `<typeparam>`, belongs on the block, not on its members. A member which only looks something up about its receiver, such as a name, an icon, a flag, a prompt, or an address, is an extension property, named without `Get` or `To`: `format.FileExtension`, `host.IsChatSupported`. It stays a method when it takes parameters, builds something new such as a list or a model profile, parses, scans a collection, or converts into another type, as `GetModelProfile`, `CompactCount`, and `ToSources` do. Check first that the receiver has no instance member of the same name, which would hide the extension. A helper which belongs to the type rather than to one of its values is a static member of the block and is reached through the type: `RID.Current`, `FileExportFormat.TryFromCodeFenceLanguage`. Never name one `Parse` or `TryParse`: C# finds those of `Enum` first.
- **Message Bus** - Singleton event bus for cross-component communication inside the .NET app - **Message Bus** - Singleton event bus for cross-component communication inside the .NET app
- **Prompt injection reports** - The user hears once per action about what the filter removed, as soon as that action ends. Content which belongs to an action carries its scope from `PromptInjectionGuardService.BeginAction` down to where it is read or filtered; whatever is filtered without a scope is reported right away. Pass the scope as a parameter, never through a field or an `AsyncLocal`: the service serves the whole app, and the message bus delivers to other receivers in the execution context of whoever sends. - **Prompt injection reports** - The user hears once per action about what the filter removed, as soon as that action ends. Content which belongs to an action carries its scope from `PromptInjectionGuardService.BeginAction` down to where it is read or filtered; whatever is filtered without a scope is reported right away. Pass the scope as a parameter, never through a field or an `AsyncLocal`: the service serves the whole app, and the message bus delivers to other receivers in the execution context of whoever sends.
- **Paths in stored data** - A stored path to a file which AI Studio keeps below the data directory, such as a transcript or a tokenizer copy, is relative to that directory, so that a backup or a copy of the data directory works on another computer, under another user name, or on another OS. Mark such a property with `[JsonConverter(typeof(DataDirectoryRelativePathConverter))]`, for a positional record parameter with `[property: ...]`; in memory, the path stays absolute. Better still, derive the path from IDs and store none, as `VisualBriefingStore` does. Paths to files of the user stay absolute. Chats stored before v26.10.1 are migrated by a compatibility shim, see `documentation/compatibility-shims/2026-10-relative-data-paths.md`. - **Paths in stored data** - A stored path to a file which AI Studio keeps below the data directory, such as a transcript or a tokenizer copy, is relative to that directory, so that a backup or a copy of the data directory works on another computer, under another user name, or on another OS. Mark such a property with `[JsonConverter(typeof(DataDirectoryRelativePathConverter))]`, for a positional record parameter with `[property: ...]`; in memory, the path stays absolute. Better still, derive the path from IDs and store none, as `VisualBriefingStore` does. Paths to files of the user stay absolute. Chats stored before v26.10.1 are migrated by a compatibility shim, see `documentation/compatibility-shims/2026-10-relative-data-paths.md`.
+3 -3
View File
@@ -14,7 +14,7 @@ public static class Pdfium
public static async Task InstallAsync(RID rid, string version, bool offline) public static async Task InstallAsync(RID rid, string version, bool offline)
{ {
Console.Write($"- Installing Pdfium {version} for {rid.ToUserFriendlyName()} ..."); Console.Write($"- Installing Pdfium {version} for {rid.UserFriendlyName} ...");
var cwd = Environment.GetRustRuntimeDirectory(); var cwd = Environment.GetRustRuntimeDirectory();
var pdfiumUrl = GetPdfiumDownloadUrl(rid, version); var pdfiumUrl = GetPdfiumDownloadUrl(rid, version);
@@ -35,7 +35,7 @@ public static class Pdfium
if (string.IsNullOrWhiteSpace(library.Path)) if (string.IsNullOrWhiteSpace(library.Path))
{ {
Console.WriteLine($" failed to find the library path for {rid.ToUserFriendlyName()}"); Console.WriteLine($" failed to find the library path for {rid.UserFriendlyName}");
return; return;
} }
@@ -50,7 +50,7 @@ public static class Pdfium
using var response = await CLIENT.GetAsync(pdfiumUrl, HttpCompletionOption.ResponseHeadersRead); using var response = await CLIENT.GetAsync(pdfiumUrl, HttpCompletionOption.ResponseHeadersRead);
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{ {
Console.WriteLine($" failed to download Pdfium {version} for {rid.ToUserFriendlyName()} from {pdfiumUrl}"); Console.WriteLine($" failed to download Pdfium {version} for {rid.UserFriendlyName} from {pdfiumUrl}");
return; return;
} }
+5 -5
View File
@@ -266,9 +266,9 @@ public sealed partial class UpdateMetadataCommands
var pdfiumVersion = await this.ReadPdfiumVersion(); var pdfiumVersion = await this.ReadPdfiumVersion();
await Pdfium.InstallAsync(rid, pdfiumVersion, Environment.IsOfflineBuildRequested(offline)); await Pdfium.InstallAsync(rid, pdfiumVersion, Environment.IsOfflineBuildRequested(offline));
Console.Write($"- Start .NET build for {rid.ToUserFriendlyName()} ..."); Console.Write($"- Start .NET build for {rid.UserFriendlyName} ...");
await this.ReadCommandOutput(pathApp, "dotnet", $"clean --configuration release --runtime {rid.AsMicrosoftRid()}"); await this.ReadCommandOutput(pathApp, "dotnet", $"clean --configuration release --runtime {rid.MicrosoftRid}");
var dotnetBuildOutput = await this.ReadCommandOutput(pathApp, "dotnet", $"publish --configuration release --runtime {rid.AsMicrosoftRid()} --disable-build-servers --force"); var dotnetBuildOutput = await this.ReadCommandOutput(pathApp, "dotnet", $"publish --configuration release --runtime {rid.MicrosoftRid} --disable-build-servers --force");
var dotnetBuildOutputLines = dotnetBuildOutput.Text.Split([global::System.Environment.NewLine], StringSplitOptions.RemoveEmptyEntries); var dotnetBuildOutputLines = dotnetBuildOutput.Text.Split([global::System.Environment.NewLine], StringSplitOptions.RemoveEmptyEntries);
var foundIssue = false; var foundIssue = false;
foreach (var buildOutputLine in dotnetBuildOutputLines) foreach (var buildOutputLine in dotnetBuildOutputLines)
@@ -327,7 +327,7 @@ public sealed partial class UpdateMetadataCommands
if (string.IsNullOrWhiteSpace(tauriSidecarArtifactName)) if (string.IsNullOrWhiteSpace(tauriSidecarArtifactName))
{ {
Console.WriteLine($"- Error: Unsupported rid '{rid.AsMicrosoftRid()}'."); Console.WriteLine($"- Error: Unsupported rid '{rid.MicrosoftRid}'.");
throw new CommandExitedException(1); throw new CommandExitedException(1);
} }
@@ -341,7 +341,7 @@ public sealed partial class UpdateMetadataCommands
_ => "mindworkAIStudio", _ => "mindworkAIStudio",
}; };
var dotnetPublishedPath = Path.Combine(pathApp, "bin", "release", Environment.DOTNET_VERSION, rid.AsMicrosoftRid(), "publish", dotnetArtifactFilename); var dotnetPublishedPath = Path.Combine(pathApp, "bin", "release", Environment.DOTNET_VERSION, rid.MicrosoftRid, "publish", dotnetArtifactFilename);
var finalDestination = Path.Combine(dotnetArtifactPath, tauriSidecarArtifactName); var finalDestination = Path.Combine(dotnetArtifactPath, tauriSidecarArtifactName);
if(File.Exists(dotnetPublishedPath)) if(File.Exists(dotnetPublishedPath))
+1 -1
View File
@@ -25,7 +25,7 @@ public sealed class UpdateWebAssetsCommand
var rid = Environment.GetCurrentRid(); var rid = Environment.GetCurrentRid();
var cwd = Environment.GetAIStudioDirectory(); var cwd = Environment.GetAIStudioDirectory();
var contentPath = Path.Join(cwd, "bin", "release", Environment.DOTNET_VERSION, rid.AsMicrosoftRid(), "publish", "wwwroot", "_content"); var contentPath = Path.Join(cwd, "bin", "release", Environment.DOTNET_VERSION, rid.MicrosoftRid, "publish", "wwwroot", "_content");
var isMudBlazorDirectoryPresent = Directory.Exists(Path.Join(contentPath, "MudBlazor")); var isMudBlazorDirectoryPresent = Directory.Exists(Path.Join(contentPath, "MudBlazor"));
if (!isMudBlazorDirectoryPresent) if (!isMudBlazorDirectoryPresent)
+1 -1
View File
@@ -103,7 +103,7 @@ public sealed class VerifyCommand
if (Directory.Exists(publishDirectory)) if (Directory.Exists(publishDirectory))
Directory.Delete(publishDirectory, recursive: true); Directory.Delete(publishDirectory, recursive: true);
var publishExitCode = await CommandRunner.RunAsync(directory, "dotnet", $"publish --configuration release --runtime {rid.AsMicrosoftRid()} --output \"{publishDirectory}\" --nologo"); var publishExitCode = await CommandRunner.RunAsync(directory, "dotnet", $"publish --configuration release --runtime {rid.MicrosoftRid} --output \"{publishDirectory}\" --nologo");
if (publishExitCode is not 0) if (publishExitCode is not 0)
return publishExitCode; return publishExitCode;
+1 -1
View File
@@ -10,7 +10,7 @@ public static class Environment
public const string BUILD_OFFLINE_ENVIRONMENT_VARIABLE = "AI_STUDIO_BUILD_OFFLINE"; public const string BUILD_OFFLINE_ENVIRONMENT_VARIABLE = "AI_STUDIO_BUILD_OFFLINE";
public static readonly Encoding UTF8_NO_BOM = new UTF8Encoding(false); public static readonly Encoding UTF8_NO_BOM = new UTF8Encoding(false);
private static readonly Dictionary<RID, string> ALL_RIDS = Enum.GetValues<RID>().Select(rid => new KeyValuePair<RID, string>(rid, rid.AsMicrosoftRid())).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); private static readonly Dictionary<RID, string> ALL_RIDS = Enum.GetValues<RID>().Select(rid => new KeyValuePair<RID, string>(rid, rid.MicrosoftRid)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
public static bool IsWorkingDirectoryValid() public static bool IsWorkingDirectoryValid()
{ {
@@ -153,12 +153,12 @@ public sealed class AgentDataSourceSelection (ILogger<AgentDataSourceSelection>
if (!agentProvider.AllowsDataSourceAccess(this.SettingsManager, requiredDataSecurity, requiredConfidenceLevel)) if (!agentProvider.AllowsDataSourceAccess(this.SettingsManager, requiredDataSecurity, requiredConfidenceLevel))
{ {
logger.LogWarning($"The agent for data source selection uses provider '{agentProvider.InstanceName}' with confidence '{agentProvider.GetConfidenceLevel(this.SettingsManager).GetName()}', but the available data sources require data security '{requiredDataSecurity}' and provider confidence '{requiredConfidenceLevel.GetName()}'. The agent cannot select data sources."); logger.LogWarning($"The agent for data source selection uses provider '{agentProvider.InstanceName}' with confidence '{agentProvider.GetConfidenceLevel(this.SettingsManager).Name}', but the available data sources require data security '{requiredDataSecurity}' and provider confidence '{requiredConfidenceLevel.Name}'. The agent cannot select data sources.");
return []; return [];
} }
// Assign the provider settings to the agent: // Assign the provider settings to the agent:
logger.LogInformation($"The agent for the data source selection uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.ToName()}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()})."); logger.LogInformation($"The agent for the data source selection uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.Name}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.Name}).");
this.ProviderSettings = agentProvider; this.ProviderSettings = agentProvider;
// //
@@ -148,13 +148,13 @@ public sealed class AgentRetrievalContextValidation (ILogger<AgentRetrievalConte
if (!agentProvider.AllowsDataSourceAccess(this.SettingsManager, requiredDataSecurity, requiredConfidenceLevel)) if (!agentProvider.AllowsDataSourceAccess(this.SettingsManager, requiredDataSecurity, requiredConfidenceLevel))
{ {
logger.LogWarning($"The agent for retrieval context validation uses provider '{agentProvider.InstanceName}' with confidence '{agentProvider.GetConfidenceLevel(this.SettingsManager).GetName()}', but the retrieved data requires data security '{requiredDataSecurity}' and provider confidence '{requiredConfidenceLevel.GetName()}'. The agent cannot validate retrieval contexts."); logger.LogWarning($"The agent for retrieval context validation uses provider '{agentProvider.InstanceName}' with confidence '{agentProvider.GetConfidenceLevel(this.SettingsManager).Name}', but the retrieved data requires data security '{requiredDataSecurity}' and provider confidence '{requiredConfidenceLevel.Name}'. The agent cannot validate retrieval contexts.");
this.ProviderSettings = Settings.Provider.NONE; this.ProviderSettings = Settings.Provider.NONE;
return false; return false;
} }
// Assign the provider settings to the agent: // Assign the provider settings to the agent:
logger.LogInformation($"The agent for the retrieval context validation uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.ToName()}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()})."); logger.LogInformation($"The agent for the retrieval context validation uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.Name}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.Name}).");
this.ProviderSettings = agentProvider; this.ProviderSettings = agentProvider;
return true; return true;
} }
@@ -179,7 +179,7 @@ public sealed class AssistantAuditAgent(ILogger<AssistantAuditAgent> logger, ILo
}; };
} }
logger.LogInformation($"The assistant plugin audit agent uses the provider '{provider.InstanceName}' ({provider.UsedLLMProvider.ToName()}, confidence={provider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()})."); logger.LogInformation($"The assistant plugin audit agent uses the provider '{provider.InstanceName}' ({provider.UsedLLMProvider.Name}, confidence={provider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.Name}).");
var promptPreview = await plugin.BuildAuditPromptPreviewAsync(token); var promptPreview = await plugin.BuildAuditPromptPreviewAsync(token);
var promptFallbackPreview = plugin.BuildAuditPromptFallbackPreview(); var promptFallbackPreview = plugin.BuildAuditPromptFallbackPreview();
@@ -288,7 +288,7 @@ public sealed class AssistantAuditAgent(ILogger<AssistantAuditAgent> logger, ILo
private static AssistantAuditResult NormalizeResult(AssistantAuditResult result) private static AssistantAuditResult NormalizeResult(AssistantAuditResult result)
{ {
var normalizedFindings = result.Findings; var normalizedFindings = result.Findings;
var parsedLevel = AssistantAuditLevelExtensions.Parse(result.Level); var parsedLevel = AssistantAuditLevel.ParseOrUnknown(result.Level);
var lowestFindingLevel = GetMostSevereFindingLevel(normalizedFindings); var lowestFindingLevel = GetMostSevereFindingLevel(normalizedFindings);
if (lowestFindingLevel != AssistantAuditLevel.UNKNOWN && (parsedLevel == AssistantAuditLevel.UNKNOWN || lowestFindingLevel < parsedLevel)) if (lowestFindingLevel != AssistantAuditLevel.UNKNOWN && (parsedLevel == AssistantAuditLevel.UNKNOWN || lowestFindingLevel < parsedLevel))
parsedLevel = lowestFindingLevel; parsedLevel = lowestFindingLevel;
@@ -8,7 +8,7 @@ public static class AssistantAuditLevelExtensions
extension(AssistantAuditLevel level) extension(AssistantAuditLevel level)
{ {
public string GetName() => level switch public string Name => level switch
{ {
AssistantAuditLevel.DANGEROUS => TB("Dangerous"), AssistantAuditLevel.DANGEROUS => TB("Dangerous"),
AssistantAuditLevel.CAUTION => TB("Concerning"), AssistantAuditLevel.CAUTION => TB("Concerning"),
@@ -16,7 +16,7 @@ public static class AssistantAuditLevelExtensions
_ => TB("Unknown"), _ => TB("Unknown"),
}; };
public Severity GetSeverity() => level switch public Severity Severity => level switch
{ {
AssistantAuditLevel.DANGEROUS => Severity.Error, AssistantAuditLevel.DANGEROUS => Severity.Error,
AssistantAuditLevel.CAUTION => Severity.Warning, AssistantAuditLevel.CAUTION => Severity.Warning,
@@ -24,7 +24,7 @@ public static class AssistantAuditLevelExtensions
_ => Severity.Info, _ => Severity.Info,
}; };
public Color GetColor() => level switch public Color Color => level switch
{ {
AssistantAuditLevel.DANGEROUS => Color.Error, AssistantAuditLevel.DANGEROUS => Color.Error,
AssistantAuditLevel.CAUTION => Color.Warning, AssistantAuditLevel.CAUTION => Color.Warning,
@@ -32,19 +32,19 @@ public static class AssistantAuditLevelExtensions
_ => Color.Default, _ => Color.Default,
}; };
public string GetIcon() => level switch public string Icon => level switch
{ {
AssistantAuditLevel.DANGEROUS => Icons.Material.Filled.Dangerous, AssistantAuditLevel.DANGEROUS => Icons.Material.Filled.Dangerous,
AssistantAuditLevel.CAUTION => Icons.Material.Filled.Warning, AssistantAuditLevel.CAUTION => Icons.Material.Filled.Warning,
AssistantAuditLevel.SAFE => Icons.Material.Filled.Verified, AssistantAuditLevel.SAFE => Icons.Material.Filled.Verified,
_ => Icons.Material.Filled.HelpOutline, _ => Icons.Material.Filled.HelpOutline,
}; };
}
/// <summary> /// <summary>
/// Parses an audit level string and falls back to <see cref="AssistantAuditLevel.UNKNOWN"/> when parsing fails. /// Parses an audit level string and falls back to <see cref="AssistantAuditLevel.UNKNOWN"/> when parsing fails.
/// </summary> /// </summary>
/// <param name="value">The audit level text to parse.</param> /// <param name="value">The audit level text to parse.</param>
/// <returns>The parsed audit level, or <see cref="AssistantAuditLevel.UNKNOWN"/> for null, empty, or invalid values.</returns> /// <returns>The parsed audit level, or <see cref="AssistantAuditLevel.UNKNOWN"/> for null, empty, or invalid values.</returns>
public static AssistantAuditLevel Parse(string? value) => Enum.TryParse<AssistantAuditLevel>(value, true, out var level) ? level : AssistantAuditLevel.UNKNOWN; public static AssistantAuditLevel ParseOrUnknown(string? value) => Enum.TryParse<AssistantAuditLevel>(value, true, out var parsedLevel) ? parsedLevel : AssistantAuditLevel.UNKNOWN;
}
} }
@@ -35,7 +35,7 @@
<MudTextField T="string" @bind-Text="@this.inputStartTime" Validation="@this.ValidateStartTime" Label="Start time" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Schedule" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("When will the meeting, seminar, etc. start? E.g., '9:00 AM', or '9:00 AM (CET)', etc. When the meeting is a multi-day event, specify the start time for each day.")" Placeholder="@T("9:00 AM")" Class="mb-3"/> <MudTextField T="string" @bind-Text="@this.inputStartTime" Validation="@this.ValidateStartTime" Label="Start time" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Schedule" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("When will the meeting, seminar, etc. start? E.g., '9:00 AM', or '9:00 AM (CET)', etc. When the meeting is a multi-day event, specify the start time for each day.")" Placeholder="@T("9:00 AM")" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputWhoIsPresenting" Label="@T("(Optional) Who is presenting?")" Variant="Variant.Outlined" Lines="6" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("(Optional) List the persons who will present at the meeting, seminar, etc. Use dashes (-) to separate the items.")" Placeholder="@PLACEHOLDER_WHO_IS_PRESENTING" Class="mb-3"/> <MudTextField T="string" @bind-Text="@this.inputWhoIsPresenting" Label="@T("(Optional) Who is presenting?")" Variant="Variant.Outlined" Lines="6" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("(Optional) List the persons who will present at the meeting, seminar, etc. Use dashes (-) to separate the items.")" Placeholder="@PLACEHOLDER_WHO_IS_PRESENTING" Class="mb-3"/>
<MudTextSwitch Label="@T("Do the participants need to get to know each other first?")" @bind-Value="@this.introduceParticipants" LabelOn="@T("Yes, introduce participants")" LabelOff="@T("No, participants know each other")" /> <MudTextSwitch Label="@T("Do the participants need to get to know each other first?")" @bind-Value="@this.introduceParticipants" LabelOn="@T("Yes, introduce participants")" LabelOff="@T("No, participants know each other")" />
<EnumSelection T="NumberParticipants" @bind-Value="@this.numberParticipants" NameFunc="@(participants => participants.Name())" Icon="@Icons.Material.Filled.Group" Label="@T("Number of participants")" ValidateSelection="@this.ValidateNumberParticipants"/> <EnumSelection T="NumberParticipants" @bind-Value="@this.numberParticipants" NameFunc="@(participants => participants.Name)" Icon="@Icons.Material.Filled.Group" Label="@T("Number of participants")" ValidateSelection="@this.ValidateNumberParticipants"/>
<MudTextSwitch Label="@T("Should the participants be involved passively or actively?")" @bind-Value="@this.activeParticipation" LabelOn="@T("Active participation, like world café, discussions, etc.")" LabelOff="@T("Passive participation, like presentations, lectures, etc.")" /> <MudTextSwitch Label="@T("Should the participants be involved passively or actively?")" @bind-Value="@this.activeParticipation" LabelOn="@T("Active participation, like world café, discussions, etc.")" LabelOff="@T("Passive participation, like presentations, lectures, etc.")" />
<MudTextSwitch Label="@T("Is this a virtual event, e.g., a call or webinar?")" @bind-Value="@this.isMeetingVirtual" LabelOn="@T("Yes, this is a virtual event")" LabelOff="@T("No, this is a physical event")" /> <MudTextSwitch Label="@T("Is this a virtual event, e.g., a call or webinar?")" @bind-Value="@this.isMeetingVirtual" LabelOn="@T("Yes, this is a virtual event")" LabelOff="@T("No, this is a physical event")" />
@if (!this.isMeetingVirtual) @if (!this.isMeetingVirtual)
@@ -52,5 +52,5 @@
</MudPaper> </MudPaper>
} }
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting)" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -426,7 +426,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
- The planned duration is '{this.inputDuration}'. - The planned duration is '{this.inputDuration}'.
- The planned start time is '{this.inputStartTime}'. - The planned start time is '{this.inputStartTime}'.
{this.PromptGettingToKnowEachOther()} {this.PromptGettingToKnowEachOther()}
- The number of participants is '{this.numberParticipants.Name()}'. - The number of participants is '{this.numberParticipants.Name}'.
{this.PromptActiveParticipation()} {this.PromptActiveParticipation()}
{this.PromptVirtualMeeting()} {this.PromptVirtualMeeting()}
{this.PromptPhysicalMeeting()} {this.PromptPhysicalMeeting()}
@@ -451,7 +451,7 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
if(this.selectedTargetLanguage is CommonLanguages.OTHER) if(this.selectedTargetLanguage is CommonLanguages.OTHER)
return this.customTargetLanguage; return this.customTargetLanguage;
return this.selectedTargetLanguage.Name(); return this.selectedTargetLanguage.Name;
} }
private string PromptPhysicalMeeting() private string PromptPhysicalMeeting()
@@ -6,7 +6,7 @@ public static class NumberParticipantsExtensions
extension(NumberParticipants numberParticipants) extension(NumberParticipants numberParticipants)
{ {
public string Name() => numberParticipants switch public string Name => numberParticipants switch
{ {
NumberParticipants.NOT_SPECIFIED => TB("Please select how many participants are expected"), NumberParticipants.NOT_SPECIFIED => TB("Please select how many participants are expected"),
@@ -131,7 +131,7 @@
@foreach (var assistant in this.VisibleSendToAssistants) @foreach (var assistant in this.VisibleSendToAssistants)
{ {
<MudMenuItem OnClick="@(async () => await this.SendToAssistant(assistant, new()))"> <MudMenuItem OnClick="@(async () => await this.SendToAssistant(assistant, new()))">
@assistant.Name() @assistant.Name
</MudMenuItem> </MudMenuItem>
} }
</MudMenu> </MudMenu>
@@ -163,7 +163,7 @@
@foreach (var assistant in this.VisibleSendToAssistants) @foreach (var assistant in this.VisibleSendToAssistants)
{ {
<MudMenuItem OnClick="@(async () => await this.SendToAssistant(assistant, sendToButton))"> <MudMenuItem OnClick="@(async () => await this.SendToAssistant(assistant, sendToButton))">
@assistant.Name() @assistant.Name
</MudMenuItem> </MudMenuItem>
} }
</MudMenu> </MudMenu>
@@ -63,7 +63,7 @@
@foreach (var source in Enum.GetValues<BatchProcessingPromptSource>()) @foreach (var source in Enum.GetValues<BatchProcessingPromptSource>())
{ {
<MudSelectItem Value="@source"> <MudSelectItem Value="@source">
@source.Name() @source.Name
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
@@ -149,7 +149,7 @@ else
@foreach (var mode in Enum.GetValues<BatchProcessingOutputMode>()) @foreach (var mode in Enum.GetValues<BatchProcessingOutputMode>())
{ {
<MudSelectItem Value="@mode"> <MudSelectItem Value="@mode">
@mode.Name() @mode.Name
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
@@ -157,16 +157,16 @@ else
@if (this.outputMode is BatchProcessingOutputMode.INDIVIDUAL_FILES) @if (this.outputMode is BatchProcessingOutputMode.INDIVIDUAL_FILES)
{ {
<MudSelect T="FileExportFormat" @bind-Value="@this.resultFileFormat" Disabled="@this.isProcessingBatch" AdornmentIcon="@Icons.Material.Filled.Description" Adornment="Adornment.Start" Label="@T("File format")" HelperText="@T("Choose the format of the result files. Everything except Markdown is converted by Pandoc, which AI Studio offers to install when it is missing.")" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3"> <MudSelect T="FileExportFormat" @bind-Value="@this.resultFileFormat" Disabled="@this.isProcessingBatch" AdornmentIcon="@Icons.Material.Filled.Description" Adornment="Adornment.Start" Label="@T("File format")" HelperText="@T("Choose the format of the result files. Everything except Markdown is converted by Pandoc, which AI Studio offers to install when it is missing.")" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3">
@foreach (var format in FileExportFormatExtensions.ANSWER_FORMATS) @foreach (var format in FileExportFormat.AnswerFormats)
{ {
<MudSelectItem Value="@format"> <MudSelectItem Value="@format">
@format.ToName() @format.Name
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudJustifiedText Typo="Typo.body2" Class="mb-3"> <MudJustifiedText Typo="Typo.body2" Class="mb-3">
@(string.Format(T("Each answer is stored as its own file. Those files are named after the document, e.g., the answer for report.pdf is stored as report_result{0}."), this.resultFileFormat.ToFileExtension())) @(string.Format(T("Each answer is stored as its own file. Those files are named after the document, e.g., the answer for report.pdf is stored as report_result{0}."), this.resultFileFormat.FileExtension))
</MudJustifiedText> </MudJustifiedText>
} }
else else
@@ -179,7 +179,7 @@ else
@foreach (var separator in Enum.GetValues<BatchProcessingCsvSeparator>()) @foreach (var separator in Enum.GetValues<BatchProcessingCsvSeparator>())
{ {
<MudSelectItem Value="@separator"> <MudSelectItem Value="@separator">
@separator.Name() @separator.Name
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
@@ -244,7 +244,7 @@ public partial class AssistantBatchProcessing
/// </remarks> /// </remarks>
private string CreateResultFileName(string sourceFileName) private string CreateResultFileName(string sourceFileName)
{ {
var extension = this.resultFileFormat.ToFileExtension(); var extension = this.resultFileFormat.FileExtension;
var stem = Path.GetFileNameWithoutExtension(sourceFileName); var stem = Path.GetFileNameWithoutExtension(sourceFileName);
var candidate = $"{stem}{RESULT_FILE_SUFFIX}{extension}"; var candidate = $"{stem}{RESULT_FILE_SUFFIX}{extension}";
@@ -21,7 +21,7 @@ public partial class AssistantBatchProcessing
// hundreds of times, and starting without it would spend time and tokens on answers we // hundreds of times, and starting without it would spend time and tokens on answers we
// cannot write anywhere: // cannot write anywhere:
// //
if (this.outputMode is BatchProcessingOutputMode.INDIVIDUAL_FILES && this.resultFileFormat.UsesPandoc()) if (this.outputMode is BatchProcessingOutputMode.INDIVIDUAL_FILES && this.resultFileFormat.UsesPandoc)
{ {
var pandocState = await this.PandocAvailability.EnsureAvailabilityAsync(showSuccessMessage: false, showDialog: true); var pandocState = await this.PandocAvailability.EnsureAvailabilityAsync(showSuccessMessage: false, showDialog: true);
if (!pandocState.IsAvailable) if (!pandocState.IsAvailable)
@@ -270,7 +270,7 @@ public partial class AssistantBatchProcessing
// //
var resultText = this.DisclosureService.AddDisclosureToMarkdown(aiAnswer); var resultText = this.DisclosureService.AddDisclosureToMarkdown(aiAnswer);
var resultFilePath = Path.Join(resolvedOutputDirectory, this.CreateResultFileName(fileResult.FileName)); var resultFilePath = Path.Join(resolvedOutputDirectory, this.CreateResultFileName(fileResult.FileName));
if (this.resultFileFormat.UsesPandoc()) if (this.resultFileFormat.UsesPandoc)
{ {
// //
// Pandoc reports a failure instead of throwing, because one document which // Pandoc reports a failure instead of throwing, because one document which
@@ -283,7 +283,7 @@ public partial class AssistantBatchProcessing
} }
} }
else else
await File.WriteAllTextAsync(resultFilePath, resultText, this.resultFileFormat.ToFileEncoding(), CancellationToken.None); await File.WriteAllTextAsync(resultFilePath, resultText, this.resultFileFormat.FileEncoding, CancellationToken.None);
this.FinishFileResult(fileResult, BatchProcessingFileStatus.DONE, Path.GetFileName(resultFilePath)); this.FinishFileResult(fileResult, BatchProcessingFileStatus.DONE, Path.GetFileName(resultFilePath));
} }
@@ -35,7 +35,7 @@ public partial class AssistantBatchProcessing
|| this.csvSeparator is not BatchProcessingCsvSeparator.CUSTOM) || this.csvSeparator is not BatchProcessingCsvSeparator.CUSTOM)
return null; return null;
if (!BatchProcessingCsvSeparatorExtensions.IsValidCustomSeparator(separator)) if (!BatchProcessingCsvSeparator.IsValidCustomSeparator(separator))
return T("Please enter exactly one punctuation or symbol character. Letters, numbers, spaces, quotation marks, and line breaks cannot be used as CSV separators."); return T("Please enter exactly one punctuation or symbol character. Letters, numbers, spaces, quotation marks, and line breaks cannot be used as CSV separators.");
return null; return null;
@@ -8,7 +8,7 @@ public static class BatchProcessingCsvSeparatorExtensions
extension(BatchProcessingCsvSeparator separator) extension(BatchProcessingCsvSeparator separator)
{ {
public string Name() => separator switch public string Name => separator switch
{ {
BatchProcessingCsvSeparator.COMMA => TB("Comma (,)"), BatchProcessingCsvSeparator.COMMA => TB("Comma (,)"),
BatchProcessingCsvSeparator.SEMICOLON => TB("Semicolon (;)"), BatchProcessingCsvSeparator.SEMICOLON => TB("Semicolon (;)"),
@@ -25,20 +25,20 @@ public static class BatchProcessingCsvSeparatorExtensions
BatchProcessingCsvSeparator.SEMICOLON => ';', BatchProcessingCsvSeparator.SEMICOLON => ';',
BatchProcessingCsvSeparator.PIPE => '|', BatchProcessingCsvSeparator.PIPE => '|',
BatchProcessingCsvSeparator.TAB => '\t', BatchProcessingCsvSeparator.TAB => '\t',
BatchProcessingCsvSeparator.CUSTOM when IsValidCustomSeparator(customSeparator) => customSeparator[0], BatchProcessingCsvSeparator.CUSTOM when BatchProcessingCsvSeparator.IsValidCustomSeparator(customSeparator) => customSeparator[0],
_ => DEFAULT_SEPARATOR, _ => DEFAULT_SEPARATOR,
}; };
}
internal static bool IsValidCustomSeparator(string separator) internal static bool IsValidCustomSeparator(string customSeparator)
{ {
if (string.IsNullOrEmpty(separator) || separator.Length is not 1) if (string.IsNullOrEmpty(customSeparator) || customSeparator.Length is not 1)
return false; return false;
var character = separator[0]; var character = customSeparator[0];
return !char.IsLetterOrDigit(character) return !char.IsLetterOrDigit(character)
&& !char.IsWhiteSpace(character) && !char.IsWhiteSpace(character)
&& character is not '"' and not '\r' and not '\n'; && character is not '"' and not '\r' and not '\n';
} }
} }
}
@@ -6,7 +6,7 @@ public static class BatchProcessingOutputModeExtensions
extension(BatchProcessingOutputMode outputMode) extension(BatchProcessingOutputMode outputMode)
{ {
public string Name() => outputMode switch public string Name => outputMode switch
{ {
BatchProcessingOutputMode.INDIVIDUAL_FILES => TB("One file per document"), BatchProcessingOutputMode.INDIVIDUAL_FILES => TB("One file per document"),
BatchProcessingOutputMode.TABLE_ONLY => TB("One CSV results table, where each answer becomes one row"), BatchProcessingOutputMode.TABLE_ONLY => TB("One CSV results table, where each answer becomes one row"),
@@ -6,7 +6,7 @@ public static class BatchProcessingPromptSourceExtensions
extension(BatchProcessingPromptSource promptSource) extension(BatchProcessingPromptSource promptSource)
{ {
public string Name() => promptSource switch public string Name => promptSource switch
{ {
BatchProcessingPromptSource.FREE_PROMPT => TB("Use a free prompt"), BatchProcessingPromptSource.FREE_PROMPT => TB("Use a free prompt"),
BatchProcessingPromptSource.POLICY => TB("Use a document analysis policy"), BatchProcessingPromptSource.POLICY => TB("Use a document analysis policy"),
@@ -10,5 +10,5 @@
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://betterhumans.pub/cognitive-bias-cheat-sheet-55a472476b18">@T("Blog post of Buster Benson:") "Cognitive bias cheat sheet"</MudListItem> <MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="https://betterhumans.pub/cognitive-bias-cheat-sheet-55a472476b18">@T("Blog post of Buster Benson:") "Cognitive bias cheat sheet"</MudListItem>
</MudList> </MudList>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting)" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -18,10 +18,10 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAss
protected override string SystemPrompt => $""" protected override string SystemPrompt => $"""
You are a friendly, helpful expert on cognitive bias. You studied psychology and You are a friendly, helpful expert on cognitive bias. You studied psychology and
have a lot of experience. You explain a bias every day. Today's bias belongs to have a lot of experience. You explain a bias every day. Today's bias belongs to
the category: "{this.biasOfTheDay.Category.ToName()}". We have the following the category: "{this.biasOfTheDay.Category.Name}". We have the following
thoughts on this category: thoughts on this category:
{this.biasOfTheDay.Category.GetThoughts()} {this.biasOfTheDay.Category.Thoughts}
Today's bias is: Today's bias is:
{this.biasOfTheDay.Description} {this.biasOfTheDay.Description}
@@ -124,7 +124,7 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAss
if(this.selectedTargetLanguage is CommonLanguages.OTHER) if(this.selectedTargetLanguage is CommonLanguages.OTHER)
return this.customTargetLanguage; return this.customTargetLanguage;
return this.selectedTargetLanguage.Name(); return this.selectedTargetLanguage.Name;
} }
private async Task TellBias() private async Task TellBias()
@@ -50,7 +50,7 @@
{ {
<MudTextField T="string" @bind-Text="@this.assistantName" AdornmentIcon="@Icons.Material.Filled.Assistant" Adornment="Adornment.Start" IconSize="Size.Small" Label="@T("Display Name (Optional)")" Placeholder="@T("Meeting Task Extractor")" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" @bind-Text="@this.assistantName" AdornmentIcon="@Icons.Material.Filled.Assistant" Adornment="Adornment.Start" IconSize="Size.Small" Label="@T("Display Name (Optional)")" Placeholder="@T("Meeting Task Extractor")" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
} }
<EnumSelection T="AssistantCategory" NameFunc="@(category => category.NameSelecting())" @bind-Value="@this.selectedCategory" ValidateSelection="@this.ValidatingCategory" Icon="@Icons.Material.Filled.Category" IconSize="Size.Small" Label="@T("Category (Optional)")" AllowOther="@true" OtherValue="AssistantCategory.OTHER" @bind-OtherInput="@this.customCategory" ValidateOther="@this.ValidateCustomCategory" LabelOther="@T("Custom assistant category")" /> <EnumSelection T="AssistantCategory" NameFunc="@(category => category.NameSelecting)" @bind-Value="@this.selectedCategory" ValidateSelection="@this.ValidatingCategory" Icon="@Icons.Material.Filled.Category" IconSize="Size.Small" Label="@T("Category (Optional)")" AllowOther="@true" OtherValue="AssistantCategory.OTHER" @bind-OtherInput="@this.customCategory" ValidateOther="@this.ValidateCustomCategory" LabelOther="@T("Custom assistant category")" />
@if (!this.createChatLauncher) @if (!this.createChatLauncher)
{ {
<MudTextField T="string" @bind-Text="@this.typicalInput" AdornmentIcon="@Icons.Material.Filled.Login" Adornment="Adornment.Start" IconSize="Size.Small" Label="@T("Typical input (Optional)")" Placeholder="@T("What users provide, e.g. text, notes, files, or a URL")" Variant="Variant.Outlined" Margin="Margin.Dense" Lines="3" Sizing="InputSizing.Auto" MaxLines="8" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" @bind-Text="@this.typicalInput" AdornmentIcon="@Icons.Material.Filled.Login" Adornment="Adornment.Start" IconSize="Size.Small" Label="@T("Typical input (Optional)")" Placeholder="@T("What users provide, e.g. text, notes, files, or a URL")" Variant="Variant.Outlined" Margin="Margin.Dense" Lines="3" Sizing="InputSizing.Auto" MaxLines="8" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
@@ -59,11 +59,11 @@
@foreach (var component in ASSISTANT_COMPONENT_OPTIONS) @foreach (var component in ASSISTANT_COMPONENT_OPTIONS)
{ {
<MudSelectItem T="AssistantComponentType" Value="@component"> <MudSelectItem T="AssistantComponentType" Value="@component">
@component.GetDisplayName() @component.DisplayName
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedOutputLanguage" Icon="@Icons.Material.Filled.Translate" IconSize="Size.Small" Label="@T("(Optional) Output language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customOutputLanguage" ValidateOther="@this.ValidateCustomOutputLanguage" LabelOther="@T("Custom output language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional)" @bind-Value="@this.selectedOutputLanguage" Icon="@Icons.Material.Filled.Translate" IconSize="Size.Small" Label="@T("(Optional) Output language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customOutputLanguage" ValidateOther="@this.ValidateCustomOutputLanguage" LabelOther="@T("Custom output language")" />
<MudSwitch T="bool" @bind-Value="@this.allowGeneratedAssistantProfiles" Label="@T("Allow AI Studio profiles")" LabelPlacement="Placement.End" Color="Color.Primary" Class="mb-3"/> <MudSwitch T="bool" @bind-Value="@this.allowGeneratedAssistantProfiles" Label="@T("Allow AI Studio profiles")" LabelPlacement="Placement.End" Color="Color.Primary" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.extraRules" AdornmentIcon="@Icons.Material.Filled.Rule" Adornment="Adornment.Start" IconSize="Size.Small" Label="@T("Additional rules (Optional)")" Placeholder="@T("What to avoid or consider, e.g. do not invent missing facts")" Variant="Variant.Outlined" Margin="Margin.Dense" Lines="3" Sizing="InputSizing.Auto" MaxLines="10" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" @bind-Text="@this.extraRules" AdornmentIcon="@Icons.Material.Filled.Rule" Adornment="Adornment.Start" IconSize="Size.Small" Label="@T("Additional rules (Optional)")" Placeholder="@T("What to avoid or consider, e.g. do not invent missing facts")" Variant="Variant.Outlined" Margin="Margin.Dense" Lines="3" Sizing="InputSizing.Auto" MaxLines="10" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudTextField T="string" @bind-Text="@this.exampleRequest" AdornmentIcon="@Icons.Material.Filled.Lightbulb" Adornment="Adornment.Start" IconSize="Size.Small" Label="@T("Example prompt (Optional)")" Placeholder="@T("An expected user prompt, e.g. summarize this document")" Variant="Variant.Outlined" Margin="Margin.Dense" Lines="3" Sizing="InputSizing.Auto" MaxLines="10" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" @bind-Text="@this.exampleRequest" AdornmentIcon="@Icons.Material.Filled.Lightbulb" Adornment="Adornment.Start" IconSize="Size.Small" Label="@T("Example prompt (Optional)")" Placeholder="@T("An expected user prompt, e.g. summarize this document")" Variant="Variant.Outlined" Margin="Margin.Dense" Lines="3" Sizing="InputSizing.Auto" MaxLines="10" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
@@ -201,8 +201,8 @@ else
} }
else if (this.AuditCompleted) else if (this.AuditCompleted)
{ {
<MudAlert Severity="@this.AuditSeverity" Dense="@true" Icon="@this.pluginAudit!.Level.GetIcon()"> <MudAlert Severity="@this.AuditSeverity" Dense="@true" Icon="@this.pluginAudit!.Level.Icon">
<strong>@this.pluginAudit.Level.GetName()</strong><span>: @this.pluginAudit.Summary</span> <strong>@this.pluginAudit.Level.Name</strong><span>: @this.pluginAudit.Summary</span>
</MudAlert> </MudAlert>
} }
else else
@@ -520,14 +520,14 @@ public partial class AssistantBuilder : AssistantBaseCore<SettingsDialogAssistan
{ {
AssistantCategory.AS_IS => string.Empty, AssistantCategory.AS_IS => string.Empty,
AssistantCategory.OTHER => this.customCategory, AssistantCategory.OTHER => this.customCategory,
_ => this.selectedCategory.Name(), _ => this.selectedCategory.Name,
}; };
private string GetSelectedOutputLanguageName() => this.selectedOutputLanguage switch private string GetSelectedOutputLanguageName() => this.selectedOutputLanguage switch
{ {
CommonLanguages.AS_IS => string.Empty, CommonLanguages.AS_IS => string.Empty,
CommonLanguages.OTHER => this.customOutputLanguage, CommonLanguages.OTHER => this.customOutputLanguage,
_ => this.selectedOutputLanguage.Name(), _ => this.selectedOutputLanguage.Name,
}; };
private string GetSelectedAssistantComponentText(IReadOnlyList<string?>? selectedValues) private string GetSelectedAssistantComponentText(IReadOnlyList<string?>? selectedValues)
@@ -625,7 +625,7 @@ public partial class AssistantBuilder : AssistantBaseCore<SettingsDialogAssistan
private string GetAssistantComponentDisplayName(string? typeName) private string GetAssistantComponentDisplayName(string? typeName)
{ {
if (Enum.TryParse<AssistantComponentType>(typeName, out var type)) if (Enum.TryParse<AssistantComponentType>(typeName, out var type))
return type.GetDisplayName(); return type.DisplayName;
return typeName ?? string.Empty; return typeName ?? string.Empty;
} }
@@ -726,7 +726,7 @@ public partial class AssistantBuilder : AssistantBaseCore<SettingsDialogAssistan
this.UpsertAudit(this.pluginAudit); this.UpsertAudit(this.pluginAudit);
await this.SettingsManager.StoreSettings(); await this.SettingsManager.StoreSettings();
await this.MessageBus.SendSuccess(new( await this.MessageBus.SendSuccess(new(
this.pluginAudit.Level.GetIcon(), this.pluginAudit.Level.Icon,
this.pluginAudit.Findings.Count == 0 this.pluginAudit.Findings.Count == 0
? T("Security check completed. No security issues were found.") ? T("Security check completed. No security issues were found.")
: T("Security check completed with findings."))); : T("Security check completed with findings.")));
@@ -787,8 +787,8 @@ public partial class AssistantBuilder : AssistantBaseCore<SettingsDialogAssistan
string.Format( string.Format(
T("The assistant '{0}' was checked with the level '{1}', which is below your required level '{2}'. Your settings allow activation anyway, but this may be unsafe. Do you want to enable this assistant?"), T("The assistant '{0}' was checked with the level '{1}', which is below your required level '{2}'. Your settings allow activation anyway, but this may be unsafe. Do you want to enable this assistant?"),
this.pluginInstallResult?.PluginName ?? T("Unknown assistant"), this.pluginInstallResult?.PluginName ?? T("Unknown assistant"),
this.pluginAudit?.Level.GetName() ?? T("Unknown"), this.pluginAudit?.Level.Name ?? T("Unknown"),
this.SettingsManager.ConfigurationData.AssistantPluginAudit.MinimumLevel.GetName()) this.SettingsManager.ConfigurationData.AssistantPluginAudit.MinimumLevel.Name)
}, },
}; };
@@ -6,7 +6,7 @@ public static class CommonCodingLanguageExtensions
extension(CommonCodingLanguages language) extension(CommonCodingLanguages language)
{ {
public string Name() => language switch public string Name => language switch
{ {
CommonCodingLanguages.NONE => TB("None"), CommonCodingLanguages.NONE => TB("None"),
@@ -29,8 +29,8 @@ else
@if (this.audit is not null && this.audit.Level is not AssistantAuditLevel.SAFE) @if (this.audit is not null && this.audit.Level is not AssistantAuditLevel.SAFE)
{ {
<MudPaper Class="pa-4 ma-4" Elevation="0"> <MudPaper Class="pa-4 ma-4" Elevation="0">
<MudAlert Severity="@this.audit.Level.GetSeverity()" Variant="Variant.Filled" Square="false" Elevation="6" Class="pa-4"> <MudAlert Severity="@this.audit.Level.Severity" Variant="Variant.Filled" Square="false" Elevation="6" Class="pa-4">
<strong>@this.audit.Level.GetName().ToUpperInvariant(): </strong>@this.audit.Summary <strong>@this.audit.Level.Name.ToUpperInvariant(): </strong>@this.audit.Summary
</MudAlert> </MudAlert>
</MudPaper> </MudPaper>
} }
@@ -20,6 +20,6 @@
} }
</MudSelect> </MudSelect>
<MudTextField T="string" @bind-Text="@this.inputName" Label="@T("(Optional) Your name for the closing salutation")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Your name for the closing salutation of your e-mail.")" Class="mb-3"/> <MudTextField T="string" @bind-Text="@this.inputName" Label="@T("(Optional) Your name for the closing salutation")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="@T("Your name for the closing salutation of your e-mail.")" Class="mb-3"/>
<EnumSelection T="WritingStyles" NameFunc="@(style => style.Name())" @bind-Value="@this.selectedWritingStyle" Icon="@Icons.Material.Filled.Edit" Label="@T("Select the writing style")" ValidateSelection="@this.ValidateWritingStyle"/> <EnumSelection T="WritingStyles" NameFunc="@(style => style.Name)" @bind-Value="@this.selectedWritingStyle" Icon="@Icons.Material.Filled.Edit" Label="@T("Select the writing style")" ValidateSelection="@this.ValidateWritingStyle"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting)" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -17,7 +17,7 @@ public partial class AssistantEMail : AssistantBaseCore<SettingsDialogWritingEMa
protected override string SystemPrompt => protected override string SystemPrompt =>
$""" $"""
You are an automated system that writes emails. {this.SystemPromptHistory()} The user provides you with bullet points on what You are an automated system that writes emails. {this.SystemPromptHistory()} The user provides you with bullet points on what
he want to address in the response. Regarding the writing style of the email: {this.selectedWritingStyle.Prompt()} he want to address in the response. Regarding the writing style of the email: {this.selectedWritingStyle.Prompt}
{this.SystemPromptGreeting()} {this.SystemPromptName()} You write the email in the following language: {this.SystemPromptLanguage()}. {this.SystemPromptGreeting()} {this.SystemPromptName()} You write the email in the following language: {this.SystemPromptLanguage()}.
"""; """;
@@ -227,7 +227,7 @@ public partial class AssistantEMail : AssistantBaseCore<SettingsDialogWritingEMa
if(this.selectedTargetLanguage is CommonLanguages.OTHER) if(this.selectedTargetLanguage is CommonLanguages.OTHER)
return this.customTargetLanguage; return this.customTargetLanguage;
return this.selectedTargetLanguage.Name(); return this.selectedTargetLanguage.Name;
} }
private string PromptFoci() private string PromptFoci()
@@ -6,7 +6,7 @@ public static class WritingStylesExtensions
extension(WritingStyles style) extension(WritingStyles style)
{ {
public string Name() => style switch public string Name => style switch
{ {
WritingStyles.ACADEMIC => TB("Academic"), WritingStyles.ACADEMIC => TB("Academic"),
WritingStyles.PERSONAL => TB("Personal"), WritingStyles.PERSONAL => TB("Personal"),
@@ -16,7 +16,7 @@ public static class WritingStylesExtensions
_ => TB("Not specified"), _ => TB("Not specified"),
}; };
public string Prompt() => style switch public string Prompt => style switch
{ {
WritingStyles.ACADEMIC => "Use an academic style for communication in an academic context like between students and professors.", WritingStyles.ACADEMIC => "Use an academic style for communication in an academic context like between students and professors.",
WritingStyles.PERSONAL => "Use a personal style for communication between friends and family.", WritingStyles.PERSONAL => "Use a personal style for communication between friends and family.",
@@ -6,7 +6,7 @@ public static class AllowedLLMProvidersExtensions
extension(AllowedLLMProviders provider) extension(AllowedLLMProviders provider)
{ {
public string Description() => provider switch public string Description => provider switch
{ {
AllowedLLMProviders.NONE => TB("Please select what kind of LLM provider are allowed for this data source"), AllowedLLMProviders.NONE => TB("Please select what kind of LLM provider are allowed for this data source"),
AllowedLLMProviders.ANY => TB("Any LLM provider is allowed: users might choose a cloud-based or a self-hosted provider"), AllowedLLMProviders.ANY => TB("Any LLM provider is allowed: users might choose a cloud-based or a self-hosted provider"),
@@ -97,7 +97,7 @@ else
@foreach (var language in Enum.GetValues<ProgrammingLanguages>()) @foreach (var language in Enum.GetValues<ProgrammingLanguages>())
{ {
<MudSelectItem Value="@language"> <MudSelectItem Value="@language">
@language.Name() @language.Name
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
@@ -130,7 +130,7 @@ else
@foreach (var dataSource in Enum.GetValues<DataSources>()) @foreach (var dataSource in Enum.GetValues<DataSources>())
{ {
<MudSelectItem Value="@dataSource"> <MudSelectItem Value="@dataSource">
@dataSource.Name() @dataSource.Name
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
@@ -181,7 +181,7 @@ else
@foreach (var authMethod in Enum.GetValues<Auth>()) @foreach (var authMethod in Enum.GetValues<Auth>())
{ {
<MudSelectItemExtended Value="@authMethod"> <MudSelectItemExtended Value="@authMethod">
@authMethod.Name() @authMethod.Name
</MudSelectItemExtended> </MudSelectItemExtended>
} }
</MudSelectExtended> </MudSelectExtended>
@@ -194,7 +194,7 @@ else
@foreach (var os in Enum.GetValues<OperatingSystem>()) @foreach (var os in Enum.GetValues<OperatingSystem>())
{ {
<MudSelectItem Value="@os"> <MudSelectItem Value="@os">
@os.Name() @os.Name
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
@@ -208,7 +208,7 @@ else
@foreach (var option in Enum.GetValues<AllowedLLMProviders>()) @foreach (var option in Enum.GetValues<AllowedLLMProviders>())
{ {
<MudSelectItem Value="@option"> <MudSelectItem Value="@option">
@option.Description() @option.Description
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
@@ -378,7 +378,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
/// <summary> /// <summary>
/// Gets whether the selected ERI specification cannot be saved. /// Gets whether the selected ERI specification cannot be saved.
/// </summary> /// </summary>
private bool IsSpecificationSavingDisabled => !this.selectedERIVersion.WasSpecificationSelected() || this.IsERIInputDisabled; private bool IsSpecificationSavingDisabled => !this.selectedERIVersion.WasSpecificationSelected || this.IsERIInputDisabled;
/// <summary> /// <summary>
/// Lets the user save the selected ERI specification, a copy of the one the app carries. /// Lets the user save the selected ERI specification, a copy of the one the app carries.
@@ -389,7 +389,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
/// </remarks> /// </remarks>
private async Task SaveSpecificationAsync() private async Task SaveSpecificationAsync()
{ {
var specificationPath = this.selectedERIVersion.SpecificationURL(); var specificationPath = this.selectedERIVersion.SpecificationURL;
var response = await this.RustService.SaveFile(T("Save the ERI specification"), [FileTypes.JSON], Path.GetFileName(specificationPath)); var response = await this.RustService.SaveFile(T("Save the ERI specification"), [FileTypes.JSON], Path.GetFileName(specificationPath));
if (response.UserCancelled) if (response.UserCancelled)
return; return;
@@ -6,7 +6,7 @@ public static class AuthExtensions
extension(Auth auth) extension(Auth auth)
{ {
public string Name() => auth switch public string Name => auth switch
{ {
Auth.NONE => TB("No login necessary: useful for public data sources"), Auth.NONE => TB("No login necessary: useful for public data sources"),
@@ -17,7 +17,7 @@ public static class AuthExtensions
_ => TB("Unknown login method") _ => TB("Unknown login method")
}; };
public string ToPrompt() => auth switch public string Prompt => auth switch
{ {
Auth.NONE => "No login is necessary, the data source is public.", Auth.NONE => "No login is necessary, the data source is public.",
@@ -6,7 +6,7 @@ public static class DataSourcesExtensions
extension(DataSources dataSource) extension(DataSources dataSource)
{ {
public string Name() => dataSource switch public string Name => dataSource switch
{ {
DataSources.NONE => TB("No data source selected"), DataSources.NONE => TB("No data source selected"),
DataSources.CUSTOM => TB("Custom description"), DataSources.CUSTOM => TB("Custom description"),
@@ -58,7 +58,7 @@ internal sealed class ERIServerPrompt
// Introduction // Introduction
// --------------------------------- // ---------------------------------
// //
var programmingLanguage = this.ProgrammingLanguage is ProgrammingLanguages.OTHER ? this.OtherProgrammingLanguage : this.ProgrammingLanguage.ToPrompt(); var programmingLanguage = this.ProgrammingLanguage is ProgrammingLanguages.OTHER ? this.OtherProgrammingLanguage : this.ProgrammingLanguage.Prompt;
sb.Append($""" sb.Append($"""
# Introduction # Introduction
You are an experienced {programmingLanguage} developer. Your task is to implement an API server in You are an experienced {programmingLanguage} developer. Your task is to implement an API server in
@@ -172,7 +172,7 @@ internal sealed class ERIServerPrompt
{ {
sb.Append($""" sb.Append($"""
- {auth.ToPrompt()} - {auth.Prompt}
"""); """);
} }
@@ -192,7 +192,7 @@ internal sealed class ERIServerPrompt
{ {
sb.Append($""" sb.Append($"""
The server will run on {this.OperatingSystem.ToPrompt()} operating systems. Keep The server will run on {this.OperatingSystem.Prompt} operating systems. Keep
this in mind when implementing the SSO with Kerberos. this in mind when implementing the SSO with Kerberos.
"""); """);
} }
@@ -4,15 +4,18 @@ public static class ERIVersionExtensions
{ {
extension(ERIVersion version) extension(ERIVersion version)
{ {
public Task<string> ReadSpecification(WebRootFiles webRootFiles) => webRootFiles.ReadTextAsync(version.SpecificationURL()); public Task<string> ReadSpecification(WebRootFiles webRootFiles) => webRootFiles.ReadTextAsync(version.SpecificationURL);
public string SpecificationURL() public string SpecificationURL
{
get
{ {
var nameLower = version.ToString().ToLowerInvariant(); var nameLower = version.ToString().ToLowerInvariant();
var filename = $"{nameLower}.json"; var filename = $"{nameLower}.json";
return $"specs/eri/{filename}"; return $"specs/eri/{filename}";
} }
}
public bool WasSpecificationSelected() => version != ERIVersion.NONE; public bool WasSpecificationSelected => version != ERIVersion.NONE;
} }
} }
@@ -6,7 +6,7 @@ public static class OperatingSystemExtensions
extension(OperatingSystem os) extension(OperatingSystem os)
{ {
public string Name() => os switch public string Name => os switch
{ {
OperatingSystem.NONE => TB("No operating system specified"), OperatingSystem.NONE => TB("No operating system specified"),
@@ -16,7 +16,7 @@ public static class OperatingSystemExtensions
_ => TB("Unknown operating system") _ => TB("Unknown operating system")
}; };
public string ToPrompt() => os switch public string Prompt => os switch
{ {
OperatingSystem.NONE => "No operating system specified", OperatingSystem.NONE => "No operating system specified",
@@ -6,7 +6,7 @@ public static class ProgrammingLanguagesExtensions
extension(ProgrammingLanguages language) extension(ProgrammingLanguages language)
{ {
public string Name() => language switch public string Name => language switch
{ {
ProgrammingLanguages.NONE => TB("No programming language selected"), ProgrammingLanguages.NONE => TB("No programming language selected"),
@@ -26,7 +26,7 @@ public static class ProgrammingLanguagesExtensions
_ => TB("Unknown") _ => TB("Unknown")
}; };
public string ToPrompt() => language switch public string Prompt => language switch
{ {
ProgrammingLanguages.NONE => "No programming language selected", ProgrammingLanguages.NONE => "No programming language selected",
@@ -3,5 +3,5 @@
<ReadFileContent Text="@T("Load text from file")" @bind-FileContent="@this.inputText" EnableDragDrop="true" CatchAllDocuments="true"/> <ReadFileContent Text="@T("Load text from file")" @bind-FileContent="@this.inputText" EnableDragDrop="true" CatchAllDocuments="true"/>
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your input to check")" Variant="Variant.Outlined" Lines="6" Sizing="InputSizing.Auto" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your input to check")" Variant="Variant.Outlined" Lines="6" Sizing="InputSizing.Auto" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional)" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom language")" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -124,7 +124,7 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore<SettingsDialog
CommonLanguages.AS_IS => "the source language", CommonLanguages.AS_IS => "the source language",
CommonLanguages.OTHER => this.customTargetLanguage, CommonLanguages.OTHER => this.customTargetLanguage,
_ => $"{this.selectedTargetLanguage.Name()}", _ => $"{this.selectedTargetLanguage.Name}",
}; };
if (string.IsNullOrWhiteSpace(lang)) if (string.IsNullOrWhiteSpace(lang))
@@ -2,7 +2,7 @@
@using AIStudio.Settings @using AIStudio.Settings
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogI18N> @inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogI18N>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" SelectionUpdated="_ => this.OnChangedLanguage()" Disabled="@this.IsProcessing" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting)" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" SelectionUpdated="_ => this.OnChangedLanguage()" Disabled="@this.IsProcessing" />
<ConfigurationSelect OptionDescription="@T("Language plugin used for comparision")" SelectedValue="@(() => this.selectedLanguagePluginId)" Data="@ConfigurationSelectDataFactory.GetLanguagesData()" SelectionUpdate="@(async void (id) => await this.OnLanguagePluginChanged(id))" OptionHelp="@T("Select the language plugin used for comparision.")" Disabled="@(() => this.IsProcessing)"/> <ConfigurationSelect OptionDescription="@T("Language plugin used for comparision")" SelectedValue="@(() => this.selectedLanguagePluginId)" Data="@ConfigurationSelectDataFactory.GetLanguagesData()" SelectionUpdate="@(async void (id) => await this.OnLanguagePluginChanged(id))" OptionHelp="@T("Select the language plugin used for comparision.")" Disabled="@(() => this.IsProcessing)"/>
@if (this.isLoading) @if (this.isLoading)
{ {
@@ -190,7 +190,7 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
private string SystemPromptLanguage() => this.activeSystemPromptLanguage ?? (this.selectedTargetLanguage switch private string SystemPromptLanguage() => this.activeSystemPromptLanguage ?? (this.selectedTargetLanguage switch
{ {
CommonLanguages.OTHER => this.customTargetLanguage, CommonLanguages.OTHER => this.customTargetLanguage,
_ => $"{this.selectedTargetLanguage.Name()}", _ => $"{this.selectedTargetLanguage.Name}",
}); });
private async Task OnLanguagePluginChanged(Guid pluginId) private async Task OnLanguagePluginChanged(Guid pluginId)
@@ -215,9 +215,9 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
this.loadingIssue = string.Format(T("Was not able to load the language plugin for comparison ({0}). Please select a valid, loaded & running language plugin."), this.selectedLanguagePluginId); this.loadingIssue = string.Format(T("Was not able to load the language plugin for comparison ({0}). Please select a valid, loaded & running language plugin."), this.selectedLanguagePluginId);
this.selectedLanguagePlugin = null; this.selectedLanguagePlugin = null;
} }
else if (comparisonPlugin.IETFTag != this.selectedTargetLanguage.ToIETFTag()) else if (comparisonPlugin.IETFTag != this.selectedTargetLanguage.IETFTag)
{ {
this.loadingIssue = string.Format(T("The selected language plugin for comparison uses the IETF tag '{0}' which does not match the selected target language '{1}'. Please select a valid, loaded & running language plugin which matches the target language."), comparisonPlugin.IETFTag, this.selectedTargetLanguage.ToIETFTag()); this.loadingIssue = string.Format(T("The selected language plugin for comparison uses the IETF tag '{0}' which does not match the selected target language '{1}'. Please select a valid, loaded & running language plugin which matches the target language."), comparisonPlugin.IETFTag, this.selectedTargetLanguage.IETFTag);
this.selectedLanguagePlugin = null; this.selectedLanguagePlugin = null;
} }
else else
@@ -356,7 +356,7 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
if(this.selectedLanguagePlugin is null) if(this.selectedLanguagePlugin is null)
return; return;
if (this.selectedLanguagePlugin.IETFTag != this.selectedTargetLanguage.ToIETFTag()) if (this.selectedLanguagePlugin.IETFTag != this.selectedTargetLanguage.IETFTag)
return; return;
var addedContentSnapshot = this.addedContent.ToArray(); var addedContentSnapshot = this.addedContent.ToArray();
@@ -8,13 +8,13 @@
@foreach (var source in Enum.GetValues<IconSources>()) @foreach (var source in Enum.GetValues<IconSources>())
{ {
<MudSelectItem Value="@source"> <MudSelectItem Value="@source">
@source.Name() @source.Name
</MudSelectItem> </MudSelectItem>
} }
</MudSelect> </MudSelect>
@if (this.selectedIconSource is not IconSources.GENERIC) @if (this.selectedIconSource is not IconSources.GENERIC)
{ {
<MudButton Href="@this.selectedIconSource.URL()" Target="_blank" Variant="Variant.Filled" Size="Size.Medium"> <MudButton Href="@this.selectedIconSource.URL" Target="_blank" Variant="Variant.Filled" Size="Size.Medium">
@T("Open website") @T("Open website")
</MudButton> </MudButton>
} }
@@ -31,7 +31,7 @@ public partial class AssistantIconFinder : AssistantBaseCore<SettingsDialogIconF
protected override string SendToChatVisibleUserPromptText => protected override string SendToChatVisibleUserPromptText =>
$""" $"""
{string.Format(T("Find icon suggestions on {0} for the following context:"), this.selectedIconSource.Name())} {string.Format(T("Find icon suggestions on {0} for the following context:"), this.selectedIconSource.Name)}
{this.inputContext} {this.inputContext}
"""; """;
@@ -98,7 +98,7 @@ public partial class AssistantIconFinder : AssistantBaseCore<SettingsDialogIconF
this.CreateChatThread(); this.CreateChatThread();
var time = this.AddUserRequest( var time = this.AddUserRequest(
$""" $"""
{this.selectedIconSource.Prompt()} I search for an icon for the following context: {this.selectedIconSource.Prompt} I search for an icon for the following context:
``` ```
{this.inputContext} {this.inputContext}
@@ -4,7 +4,7 @@ public static class IconSourceExtensions
{ {
extension(IconSources iconSource) extension(IconSources iconSource)
{ {
public string Name() => iconSource switch public string Name => iconSource switch
{ {
IconSources.FLAT_ICON => "Flaticon", IconSources.FLAT_ICON => "Flaticon",
IconSources.FONT_AWESOME => "Font Awesome", IconSources.FONT_AWESOME => "Font Awesome",
@@ -16,7 +16,7 @@ public static class IconSourceExtensions
_ => "Generic", _ => "Generic",
}; };
public string Prompt() => iconSource switch public string Prompt => iconSource switch
{ {
IconSources.FLAT_ICON => "My icon source is Flaticon.", IconSources.FLAT_ICON => "My icon source is Flaticon.",
IconSources.FONT_AWESOME => "I look for an icon on Font Awesome. Please provide just valid icon names. Valid icon names are using the format `fa-icon-name`.", IconSources.FONT_AWESOME => "I look for an icon on Font Awesome. Please provide just valid icon names. Valid icon names are using the format `fa-icon-name`.",
@@ -28,7 +28,7 @@ public static class IconSourceExtensions
_ => string.Empty, _ => string.Empty,
}; };
public string URL() => iconSource switch public string URL => iconSource switch
{ {
IconSources.FLAT_ICON => "https://www.flaticon.com/", IconSources.FLAT_ICON => "https://www.flaticon.com/",
IconSources.FONT_AWESOME => "https://fontawesome.com/", IconSources.FONT_AWESOME => "https://fontawesome.com/",
@@ -16,5 +16,5 @@
<MudTextField T="string" @bind-Text="@this.inputEntryDate" Label="@T("(Optional) Provide the entry date")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.DateRange" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/> <MudTextField T="string" @bind-Text="@this.inputEntryDate" Label="@T("(Optional) Provide the entry date")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.DateRange" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<MudTextField T="string" @bind-Text="@this.inputValidUntil" Label="@T("(Optional) Provide the date until the job posting is valid")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.DateRange" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/> <MudTextField T="string" @bind-Text="@this.inputValidUntil" Label="@T("(Optional) Provide the date until the job posting is valid")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.DateRange" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional)" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -212,7 +212,7 @@ public partial class AssistantJobPostings : AssistantBaseCore<SettingsDialogJobP
if(this.selectedTargetLanguage is CommonLanguages.OTHER) if(this.selectedTargetLanguage is CommonLanguages.OTHER)
return this.customTargetLanguage; return this.customTargetLanguage;
return this.selectedTargetLanguage.Name(); return this.selectedTargetLanguage.Name;
} }
private string UserPromptMandatoryInformation() private string UserPromptMandatoryInformation()
@@ -10,5 +10,5 @@
<div class="mb-3"> <div class="mb-3">
<AttachDocuments Name="My Tasks Documents" @bind-DocumentPaths="@this.loadedDocumentPaths" OnChange="@this.OnDocumentsChanged" CatchAllDocuments="true" UseSmallForm="false" Provider="@this.ProviderSettings"/> <AttachDocuments Name="My Tasks Documents" @bind-DocumentPaths="@this.loadedDocumentPaths" OnChange="@this.OnDocumentsChanged" CatchAllDocuments="true" UseSmallForm="false" Provider="@this.ProviderSettings"/>
</div> </div>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional)" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -182,7 +182,7 @@ public partial class AssistantMyTasks : AssistantBaseCore<SettingsDialogMyTasks>
if(this.selectedTargetLanguage is CommonLanguages.OTHER) if(this.selectedTargetLanguage is CommonLanguages.OTHER)
return this.customTargetLanguage; return this.customTargetLanguage;
return this.selectedTargetLanguage.Name(); return this.selectedTargetLanguage.Name;
} }
private ContentBlock CloneHiddenUserBlockWithoutAttachments(ContentBlock block) private ContentBlock CloneHiddenUserBlockWithoutAttachments(ContentBlock block)
@@ -18,7 +18,7 @@
UserAttributes="@USER_INPUT_ATTRIBUTES"/> UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" <EnumSelection T="CommonLanguages"
NameFunc="@(language => language.NameSelectingOptional())" NameFunc="@(language => language.NameSelectingOptional)"
@bind-Value="@this.selectedTargetLanguage" @bind-Value="@this.selectedTargetLanguage"
Icon="@Icons.Material.Filled.Translate" Icon="@Icons.Material.Filled.Translate"
Label="@T("Language for the optimized prompt")" Label="@T("Language for the optimized prompt")"
@@ -280,7 +280,7 @@ public partial class AssistantPromptOptimizer : AssistantBaseCore<SettingsDialog
{ {
CommonLanguages.AS_IS => "the source language of the input prompt", CommonLanguages.AS_IS => "the source language of the input prompt",
CommonLanguages.OTHER => this.customTargetLanguage, CommonLanguages.OTHER => this.customTargetLanguage,
_ => this.selectedTargetLanguage.Name(), _ => this.selectedTargetLanguage.Name,
}; };
if (string.IsNullOrWhiteSpace(language)) if (string.IsNullOrWhiteSpace(language))
@@ -3,7 +3,7 @@
<ReadFileContent Text="@T("Load text from file")" @bind-FileContent="@this.inputText" EnableDragDrop="true" CatchAllDocuments="true"/> <ReadFileContent Text="@T("Load text from file")" @bind-FileContent="@this.inputText" EnableDragDrop="true" CatchAllDocuments="true"/>
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your input to improve")" Variant="Variant.Outlined" Lines="6" Sizing="InputSizing.Auto" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your input to improve")" Variant="Variant.Outlined" Lines="6" Sizing="InputSizing.Auto" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional)" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom language")" />
<EnumSelection T="WritingStyles" NameFunc="@(style => style.Name())" @bind-Value="@this.selectedWritingStyle" Icon="@Icons.Material.Filled.Edit" Label="@T("Writing style")" AllowOther="@false" /> <EnumSelection T="WritingStyles" NameFunc="@(style => style.Name)" @bind-Value="@this.selectedWritingStyle" Icon="@Icons.Material.Filled.Edit" Label="@T("Writing style")" AllowOther="@false" />
<EnumSelection T="SentenceStructure" NameFunc="@(voice => voice.Name())" @bind-Value="@this.selectedSentenceStructure" Icon="@Icons.Material.Filled.Person4" Label="@T("Sentence structure")" /> <EnumSelection T="SentenceStructure" NameFunc="@(voice => voice.Name)" @bind-Value="@this.selectedSentenceStructure" Icon="@Icons.Material.Filled.Person4" Label="@T("Sentence structure")" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -19,7 +19,7 @@ public partial class AssistantRewriteImprove : AssistantBaseCore<SettingsDialogR
text. You can also correct spelling and grammar issues. You never add additional information. You never text. You can also correct spelling and grammar issues. You never add additional information. You never
ask the user for additional information. Your response only contains the improved text. You do not explain ask the user for additional information. Your response only contains the improved text. You do not explain
your changes. If no changes are needed, you return the text unchanged. your changes. If no changes are needed, you return the text unchanged.
The style of the text: {this.selectedWritingStyle.Prompt()}.{this.selectedSentenceStructure.Prompt()} The style of the text: {this.selectedWritingStyle.Prompt}.{this.selectedSentenceStructure.Prompt}
You follow the rules according to {this.SystemPromptLanguage()} in all your changes. You follow the rules according to {this.SystemPromptLanguage()} in all your changes.
"""; """;
@@ -137,7 +137,7 @@ public partial class AssistantRewriteImprove : AssistantBaseCore<SettingsDialogR
CommonLanguages.AS_IS => "the source language", CommonLanguages.AS_IS => "the source language",
CommonLanguages.OTHER => this.customTargetLanguage, CommonLanguages.OTHER => this.customTargetLanguage,
_ => $"{this.selectedTargetLanguage.Name()}", _ => $"{this.selectedTargetLanguage.Name}",
}; };
if (string.IsNullOrWhiteSpace(lang)) if (string.IsNullOrWhiteSpace(lang))
@@ -6,7 +6,7 @@ public static class SentenceStructureExtensions
extension(SentenceStructure sentenceStructure) extension(SentenceStructure sentenceStructure)
{ {
public string Name() => sentenceStructure switch public string Name => sentenceStructure switch
{ {
SentenceStructure.ACTIVE => TB("Active voice"), SentenceStructure.ACTIVE => TB("Active voice"),
SentenceStructure.PASSIVE => TB("Passive voice"), SentenceStructure.PASSIVE => TB("Passive voice"),
@@ -14,7 +14,7 @@ public static class SentenceStructureExtensions
_ => TB("Not Specified"), _ => TB("Not Specified"),
}; };
public string Prompt() => sentenceStructure switch public string Prompt => sentenceStructure switch
{ {
SentenceStructure.ACTIVE => " Use an active voice for the sentence structure.", SentenceStructure.ACTIVE => " Use an active voice for the sentence structure.",
SentenceStructure.PASSIVE => " Use a passive voice for the sentence structure.", SentenceStructure.PASSIVE => " Use a passive voice for the sentence structure.",
@@ -6,7 +6,7 @@ public static class WritingStylesExtensions
extension(WritingStyles style) extension(WritingStyles style)
{ {
public string Name() => style switch public string Name => style switch
{ {
WritingStyles.EVERYDAY => TB("Everyday (personal texts, social media)"), WritingStyles.EVERYDAY => TB("Everyday (personal texts, social media)"),
WritingStyles.BUSINESS => TB("Business (business emails, reports, presentations)"), WritingStyles.BUSINESS => TB("Business (business emails, reports, presentations)"),
@@ -22,7 +22,7 @@ public static class WritingStylesExtensions
_ => TB("Not specified"), _ => TB("Not specified"),
}; };
public string Prompt() => style switch public string Prompt => style switch
{ {
WritingStyles.EVERYDAY => "Use a everyday style like for personal texts, social media, and informal communication.", WritingStyles.EVERYDAY => "Use a everyday style like for personal texts, social media, and informal communication.",
WritingStyles.BUSINESS => "Use a business style like for business emails, reports, and presentations. Most important is clarity and professionalism.", WritingStyles.BUSINESS => "Use a business style like for business emails, reports, and presentations. Most important is clarity and professionalism.",
@@ -34,6 +34,6 @@
<AttachDocuments Name="SWOT Analysis Context Material" @bind-DocumentPaths="@this.contextMaterials" UseSmallForm="false" Provider="@this.ProviderSettings"/> <AttachDocuments Name="SWOT Analysis Context Material" @bind-DocumentPaths="@this.contextMaterials" UseSmallForm="false" Provider="@this.ProviderSettings"/>
<div style="margin-top: 20px;"> <div style="margin-top: 20px;">
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" @bind-OtherInput="@this.customTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="@T("Custom target language")" ValidateOther="@this.ValidateCustomLanguage" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name)" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" @bind-OtherInput="@this.customTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="@T("Custom target language")" ValidateOther="@this.ValidateCustomLanguage" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
</div> </div>
@@ -7,7 +7,7 @@ internal static class SwotAnalysisCategoryExtensions
/// <summary> /// <summary>
/// The name of the category in the JSON the models read and write, e.g., "strengths". /// The name of the category in the JSON the models read and write, e.g., "strengths".
/// </summary> /// </summary>
public string JsonName() => category switch public string JsonName => category switch
{ {
SwotAnalysisCategory.STRENGTHS => "strengths", SwotAnalysisCategory.STRENGTHS => "strengths",
SwotAnalysisCategory.WEAKNESSES => "weaknesses", SwotAnalysisCategory.WEAKNESSES => "weaknesses",
@@ -20,7 +20,7 @@ internal static class SwotAnalysisCategoryExtensions
/// <summary> /// <summary>
/// The letter the factor IDs of the category start with, e.g., S1 for the first strength. /// The letter the factor IDs of the category start with, e.g., S1 for the first strength.
/// </summary> /// </summary>
public string FactorIdPrefix() => category switch public string FactorIdPrefix => category switch
{ {
SwotAnalysisCategory.STRENGTHS => "S", SwotAnalysisCategory.STRENGTHS => "S",
SwotAnalysisCategory.WEAKNESSES => "W", SwotAnalysisCategory.WEAKNESSES => "W",
@@ -78,8 +78,8 @@ internal static class SwotAnalysisModeration
string sharedResearch = "") string sharedResearch = "")
{ {
var payload = Enum.GetValues<SwotAnalysisCategory>().ToDictionary( var payload = Enum.GetValues<SwotAnalysisCategory>().ToDictionary(
category => category.JsonName(), category => category.JsonName,
category => CreateCategoryPayload(categories[category], category.FactorIdPrefix())); category => CreateCategoryPayload(categories[category], category.FactorIdPrefix));
return $""" return $"""
Reconcile these preliminary results of the four SWOT categories. Then write the overall assessment Reconcile these preliminary results of the four SWOT categories. Then write the overall assessment
@@ -152,12 +152,12 @@ internal static class SwotAnalysisModerationResponseParser
/// <returns>The first issue, or an empty string.</returns> /// <returns>The first issue, or an empty string.</returns>
private static string FindIssue(SwotAnalysisCategory category, SwotModeratedCategory moderatedCategory, HashSet<string> factorIds) private static string FindIssue(SwotAnalysisCategory category, SwotModeratedCategory moderatedCategory, HashSet<string> factorIds)
{ {
var name = category.JsonName(); var name = category.JsonName;
var listIssue = FindListIssue(name, moderatedCategory.Findings.Count, moderatedCategory.EmptyMessage); var listIssue = FindListIssue(name, moderatedCategory.Findings.Count, moderatedCategory.EmptyMessage);
if (listIssue.Length > 0) if (listIssue.Length > 0)
return listIssue; return listIssue;
var prefix = category.FactorIdPrefix(); var prefix = category.FactorIdPrefix;
for (var index = 0; index < moderatedCategory.Findings.Count; index++) for (var index = 0; index < moderatedCategory.Findings.Count; index++)
{ {
var finding = moderatedCategory.Findings[index]; var finding = moderatedCategory.Findings[index];
@@ -6,7 +6,7 @@ public static class AudienceAgeGroupExtensions
extension(AudienceAgeGroup ageGroup) extension(AudienceAgeGroup ageGroup)
{ {
public string Name() => ageGroup switch public string Name => ageGroup switch
{ {
AudienceAgeGroup.UNSPECIFIED => TB("Unspecified age group"), AudienceAgeGroup.UNSPECIFIED => TB("Unspecified age group"),
AudienceAgeGroup.CHILDREN => TB("Children"), AudienceAgeGroup.CHILDREN => TB("Children"),
@@ -16,7 +16,7 @@ public static class AudienceAgeGroupExtensions
_ => TB("Unspecified age group"), _ => TB("Unspecified age group"),
}; };
public string Prompt() => ageGroup switch public string Prompt => ageGroup switch
{ {
AudienceAgeGroup.UNSPECIFIED => "Do not tailor the text to a specific age group.", AudienceAgeGroup.UNSPECIFIED => "Do not tailor the text to a specific age group.",
AudienceAgeGroup.CHILDREN => "Use simple, concrete language with short sentences and minimal jargon.", AudienceAgeGroup.CHILDREN => "Use simple, concrete language with short sentences and minimal jargon.",
@@ -6,7 +6,7 @@ public static class AudienceExpertiseExtensions
extension(AudienceExpertise expertise) extension(AudienceExpertise expertise)
{ {
public string Name() => expertise switch public string Name => expertise switch
{ {
AudienceExpertise.UNSPECIFIED => TB("Unspecified expertise"), AudienceExpertise.UNSPECIFIED => TB("Unspecified expertise"),
AudienceExpertise.NON_EXPERTS => TB("No expertise"), AudienceExpertise.NON_EXPERTS => TB("No expertise"),
@@ -17,7 +17,7 @@ public static class AudienceExpertiseExtensions
_ => TB("Unspecified expertise"), _ => TB("Unspecified expertise"),
}; };
public string Prompt() => expertise switch public string Prompt => expertise switch
{ {
AudienceExpertise.UNSPECIFIED => "Do not tailor the text to a specific expertise level.", AudienceExpertise.UNSPECIFIED => "Do not tailor the text to a specific expertise level.",
AudienceExpertise.NON_EXPERTS => "Avoid jargon and explain specialized concepts plainly.", AudienceExpertise.NON_EXPERTS => "Avoid jargon and explain specialized concepts plainly.",
@@ -6,7 +6,7 @@ public static class AudienceOrganizationalLevelExtensions
extension(AudienceOrganizationalLevel level) extension(AudienceOrganizationalLevel level)
{ {
public string Name() => level switch public string Name => level switch
{ {
AudienceOrganizationalLevel.UNSPECIFIED => TB("Unspecified organizational level"), AudienceOrganizationalLevel.UNSPECIFIED => TB("Unspecified organizational level"),
AudienceOrganizationalLevel.TRAINEES => TB("Trainees"), AudienceOrganizationalLevel.TRAINEES => TB("Trainees"),
@@ -19,7 +19,7 @@ public static class AudienceOrganizationalLevelExtensions
_ => TB("Unspecified organizational level"), _ => TB("Unspecified organizational level"),
}; };
public string Prompt() => level switch public string Prompt => level switch
{ {
AudienceOrganizationalLevel.UNSPECIFIED => "Do not tailor the text to a specific organizational level.", AudienceOrganizationalLevel.UNSPECIFIED => "Do not tailor the text to a specific organizational level.",
AudienceOrganizationalLevel.TRAINEES => "Keep the content supportive and introductory. Explain context and avoid assuming prior organizational knowledge.", AudienceOrganizationalLevel.TRAINEES => "Keep the content supportive and introductory. Explain context and avoid assuming prior organizational knowledge.",
@@ -6,7 +6,7 @@ public static class AudienceProfileExtensions
extension(AudienceProfile profile) extension(AudienceProfile profile)
{ {
public string Name() => profile switch public string Name => profile switch
{ {
AudienceProfile.UNSPECIFIED => TB("Unspecified audience profile"), AudienceProfile.UNSPECIFIED => TB("Unspecified audience profile"),
AudienceProfile.STUDENTS => TB("Students"), AudienceProfile.STUDENTS => TB("Students"),
@@ -23,7 +23,7 @@ public static class AudienceProfileExtensions
_ => TB("Unspecified audience profile"), _ => TB("Unspecified audience profile"),
}; };
public string Prompt() => profile switch public string Prompt => profile switch
{ {
AudienceProfile.UNSPECIFIED => "Do not tailor the text to a specific audience profile.", AudienceProfile.UNSPECIFIED => "Do not tailor the text to a specific audience profile.",
AudienceProfile.STUDENTS => "Write for students. Keep it structured, easy to study, and focused on key takeaways.", AudienceProfile.STUDENTS => "Write for students. Keep it structured, easy to study, and focused on key takeaways.",
@@ -7,7 +7,7 @@ public static class PresentationOccasionExtensions
/// <param name="occasion">The occasion.</param> /// <param name="occasion">The occasion.</param>
extension(PresentationOccasion occasion) extension(PresentationOccasion occasion)
{ {
public string Name() => occasion switch public string Name => occasion switch
{ {
PresentationOccasion.UNSPECIFIED => TB("Unspecified occasion"), PresentationOccasion.UNSPECIFIED => TB("Unspecified occasion"),
PresentationOccasion.TALK => TB("Talk"), PresentationOccasion.TALK => TB("Talk"),
@@ -95,22 +95,22 @@
</MudGrid> </MudGrid>
<MudText Typo="Typo.h6" Class="mb-1 mt-3"> @T("Language")</MudText> <MudText Typo="Typo.h6" Class="mb-1 mt-3"> @T("Language")</MudText>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" @bind-OtherInput="@this.customTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="@T("Custom target language")" ValidateOther="@this.ValidateCustomLanguage" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name)" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" @bind-OtherInput="@this.customTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="@T("Custom target language")" ValidateOther="@this.ValidateCustomLanguage" />
<MudText Typo="Typo.h6" Class="mb-1 mt-3">@T("Occasion")</MudText> <MudText Typo="Typo.h6" Class="mb-1 mt-3">@T("Occasion")</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2"> <MudJustifiedText Typo="Typo.body1" Class="mb-2">
@T("The occasion helps the LLM to structure the presentation. A lecture, for example, may close its chapters with an interim summary or with room for questions, and a report to management leads with the key messages.") @T("The occasion helps the LLM to structure the presentation. A lecture, for example, may close its chapters with an interim summary or with room for questions, and a report to management leads with the key messages.")
</MudJustifiedText> </MudJustifiedText>
<EnumSelection T="PresentationOccasion" NameFunc="@(occasion => occasion.Name())" @bind-Value="@this.selectedOccasion" Icon="@Icons.Material.Filled.Event" Label="@T("Occasion of the presentation")" AllowOther="@true" @bind-OtherInput="@this.customOccasion" OtherValue="PresentationOccasion.OTHER" LabelOther="@T("Other occasion")" ValidateOther="@this.ValidateCustomOccasion" /> <EnumSelection T="PresentationOccasion" NameFunc="@(occasion => occasion.Name)" @bind-Value="@this.selectedOccasion" Icon="@Icons.Material.Filled.Event" Label="@T("Occasion of the presentation")" AllowOther="@true" @bind-OtherInput="@this.customOccasion" OtherValue="PresentationOccasion.OTHER" LabelOther="@T("Other occasion")" ValidateOther="@this.ValidateCustomOccasion" />
<MudText Typo="Typo.h6" Class="mb-1 mt-3"> @T("Audience")</MudText> <MudText Typo="Typo.h6" Class="mb-1 mt-3"> @T("Audience")</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2"> <MudJustifiedText Typo="Typo.body1" Class="mb-2">
@T("Please specify the audience for the planned presentation. This will help the LLM to create a presentation that fits your needs. You can specify the audience profile, the age group, organizational level, and the expertise. You don't have to specify all of these parameters, for example you might only want to specify the audience profile and leave the other parameters at their default values.") @T("Please specify the audience for the planned presentation. This will help the LLM to create a presentation that fits your needs. You can specify the audience profile, the age group, organizational level, and the expertise. You don't have to specify all of these parameters, for example you might only want to specify the audience profile and leave the other parameters at their default values.")
</MudJustifiedText> </MudJustifiedText>
<EnumSelection T="AudienceProfile" NameFunc="@(profile => profile.Name())" @bind-Value="@this.selectedAudienceProfile" Icon="@Icons.Material.Filled.Groups" Label="@T("Audience profile")" /> <EnumSelection T="AudienceProfile" NameFunc="@(profile => profile.Name)" @bind-Value="@this.selectedAudienceProfile" Icon="@Icons.Material.Filled.Groups" Label="@T("Audience profile")" />
<EnumSelection T="AudienceAgeGroup" NameFunc="@(ageGroup => ageGroup.Name())" @bind-Value="@this.selectedAudienceAgeGroup" Icon="@Icons.Material.Filled.Cake" Label="@T("Audience age group")" /> <EnumSelection T="AudienceAgeGroup" NameFunc="@(ageGroup => ageGroup.Name)" @bind-Value="@this.selectedAudienceAgeGroup" Icon="@Icons.Material.Filled.Cake" Label="@T("Audience age group")" />
<EnumSelection T="AudienceOrganizationalLevel" NameFunc="@(level => level.Name())" @bind-Value="@this.selectedAudienceOrganizationalLevel" Icon="@Icons.Material.Filled.AccountTree" Label="@T("Audience organizational level")" /> <EnumSelection T="AudienceOrganizationalLevel" NameFunc="@(level => level.Name)" @bind-Value="@this.selectedAudienceOrganizationalLevel" Icon="@Icons.Material.Filled.AccountTree" Label="@T("Audience organizational level")" />
<EnumSelection T="AudienceExpertise" NameFunc="@(expertise => expertise.Name())" @bind-Value="@this.selectedAudienceExpertise" Icon="@Icons.Material.Filled.School" Label="@T("Audience expertise")" /> <EnumSelection T="AudienceExpertise" NameFunc="@(expertise => expertise.Name)" @bind-Value="@this.selectedAudienceExpertise" Icon="@Icons.Material.Filled.School" Label="@T("Audience expertise")" />
<MudText Typo="Typo.h5" Class="mb-1 mt-6"> @T("PowerPoint template")</MudText> <MudText Typo="Typo.h5" Class="mb-1 mt-6"> @T("PowerPoint template")</MudText>
<MudJustifiedText Typo="Typo.body1" Class="mb-2"> <MudJustifiedText Typo="Typo.body1" Class="mb-2">
@@ -160,7 +160,7 @@
</MudJustifiedText> </MudJustifiedText>
<LayoutChoicePanels IsChosen="@(purpose => this.LayoutNameOf(purpose).Length > 0)"> <LayoutChoicePanels IsChosen="@(purpose => this.LayoutNameOf(purpose).Length > 0)">
<ChoiceContent Context="purpose"> <ChoiceContent Context="purpose">
<MudSelect T="string" Value="@this.LayoutNameOf(purpose)" ValueChanged="@(name => this.SetLayoutName(purpose, name))" Disabled="@this.AreLayoutsLocked" Label="@purpose.Label()" HelperText="@purpose.Help()" Variant="Variant.Outlined" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ViewQuilt" Class="mb-3"> <MudSelect T="string" Value="@this.LayoutNameOf(purpose)" ValueChanged="@(name => this.SetLayoutName(purpose, name))" Disabled="@this.AreLayoutsLocked" Label="@purpose.Label" HelperText="@purpose.Help" Variant="Variant.Outlined" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ViewQuilt" Class="mb-3">
<MudSelectItem T="string" Value="@string.Empty">@LayoutPurposeExtensions.NoPreference</MudSelectItem> <MudSelectItem T="string" Value="@string.Empty">@LayoutPurposeExtensions.NoPreference</MudSelectItem>
@foreach (var layoutName in loadedTemplate.FamilyNames) @foreach (var layoutName in loadedTemplate.FamilyNames)
{ {
@@ -178,7 +178,7 @@
</MudJustifiedText> </MudJustifiedText>
@foreach (var templateSlide in loadedTemplate.Slides) @foreach (var templateSlide in loadedTemplate.Slides)
{ {
<EnumSelection T="TemplateSlideUse" NameFunc="@(use => use.Name())" Value="@this.TemplateSlideUseOf(templateSlide.Number)" ValueChanged="@(use => this.SetTemplateSlideUse(templateSlide.Number, use))" ValidateSelection="@(use => this.ValidateTemplateSlideUse(templateSlide, use))" Disabled="@this.AreTemplateSlideUsesLocked" Icon="@Icons.Material.Filled.Slideshow" Label="@templateSlide.Label()"/> <EnumSelection T="TemplateSlideUse" NameFunc="@(use => use.Name)" Value="@this.TemplateSlideUseOf(templateSlide.Number)" ValueChanged="@(use => this.SetTemplateSlideUse(templateSlide.Number, use))" ValidateSelection="@(use => this.ValidateTemplateSlideUse(templateSlide, use))" Disabled="@this.AreTemplateSlideUsesLocked" Icon="@Icons.Material.Filled.Slideshow" Label="@templateSlide.Label"/>
} }
} }
</CompactExpansionPanel> </CompactExpansionPanel>
@@ -491,16 +491,16 @@ public partial class SlideAssistant : AssistantBaseCore<SettingsDialogSlideBuild
var prompts = new List<string>(); var prompts = new List<string>();
if (this.selectedAudienceProfile is not AudienceProfile.UNSPECIFIED) if (this.selectedAudienceProfile is not AudienceProfile.UNSPECIFIED)
prompts.Add(this.selectedAudienceProfile.Prompt()); prompts.Add(this.selectedAudienceProfile.Prompt);
if (this.selectedAudienceAgeGroup is not AudienceAgeGroup.UNSPECIFIED) if (this.selectedAudienceAgeGroup is not AudienceAgeGroup.UNSPECIFIED)
prompts.Add(this.selectedAudienceAgeGroup.Prompt()); prompts.Add(this.selectedAudienceAgeGroup.Prompt);
if (this.selectedAudienceOrganizationalLevel is not AudienceOrganizationalLevel.UNSPECIFIED) if (this.selectedAudienceOrganizationalLevel is not AudienceOrganizationalLevel.UNSPECIFIED)
prompts.Add(this.selectedAudienceOrganizationalLevel.Prompt()); prompts.Add(this.selectedAudienceOrganizationalLevel.Prompt);
if (this.selectedAudienceExpertise is not AudienceExpertise.UNSPECIFIED) if (this.selectedAudienceExpertise is not AudienceExpertise.UNSPECIFIED)
prompts.Add(this.selectedAudienceExpertise.Prompt()); prompts.Add(this.selectedAudienceExpertise.Prompt);
if (prompts.Count == 0) if (prompts.Count == 0)
return " - Do not tailor the text to a specific audience."; return " - Do not tailor the text to a specific audience.";
@@ -20,7 +20,9 @@ internal static class TemplateSlideExtensions
/// The title tells the slides apart at a glance, since a template rarely gives its slides more /// The title tells the slides apart at a glance, since a template rarely gives its slides more
/// than a title. A long one is cut, so that the label stays on one line. /// than a title. A long one is cut, so that the label stays on one line.
/// </remarks> /// </remarks>
public string Label() public string Label
{
get
{ {
var title = slide.Title.Length > MAX_SLIDE_TITLE_CHARACTERS ? $"{slide.Title[..MAX_SLIDE_TITLE_CHARACTERS].TrimEnd()}…" : slide.Title; var title = slide.Title.Length > MAX_SLIDE_TITLE_CHARACTERS ? $"{slide.Title[..MAX_SLIDE_TITLE_CHARACTERS].TrimEnd()}…" : slide.Title;
var label = title.Length > 0 ? string.Format(TB("Slide {0}: {1}"), slide.Number, title) : string.Format(TB("Slide {0}"), slide.Number); var label = title.Length > 0 ? string.Format(TB("Slide {0}: {1}"), slide.Number, title) : string.Format(TB("Slide {0}"), slide.Number);
@@ -31,3 +33,4 @@ internal static class TemplateSlideExtensions
} }
} }
} }
}
@@ -8,7 +8,7 @@ internal static class TemplateSlideUseExtensions
extension(TemplateSlideUse use) extension(TemplateSlideUse use)
{ {
public string Name() => use switch public string Name => use switch
{ {
TemplateSlideUse.OMIT => TB("Leave out"), TemplateSlideUse.OMIT => TB("Leave out"),
TemplateSlideUse.KEEP => TB("Keep unchanged"), TemplateSlideUse.KEEP => TB("Keep unchanged"),
@@ -4,5 +4,5 @@
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.Spellcheck" Adornment="Adornment.Start" Label="@T("Your word or phrase")" Variant="Variant.Outlined" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.Spellcheck" Adornment="Adornment.Start" Label="@T("Your word or phrase")" Variant="Variant.Outlined" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<MudTextField T="string" @bind-Text="@this.inputContext" AdornmentIcon="@Icons.Material.Filled.Description" Adornment="Adornment.Start" Lines="2" Sizing="InputSizing.Fixed" Label="@T("(Optional) The context for the given word or phrase")" Variant="Variant.Outlined" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" @bind-Text="@this.inputContext" AdornmentIcon="@Icons.Material.Filled.Description" Adornment="Adornment.Start" Lines="2" Sizing="InputSizing.Fixed" Label="@T("(Optional) The context for the given word or phrase")" Variant="Variant.Outlined" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional)" @bind-Value="@this.selectedLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -157,7 +157,7 @@ public partial class AssistantSynonyms : AssistantBaseCore<SettingsDialogSynonym
CommonLanguages.AS_IS => "source", CommonLanguages.AS_IS => "source",
CommonLanguages.OTHER => this.customTargetLanguage, CommonLanguages.OTHER => this.customTargetLanguage,
_ => $"{this.selectedLanguage.Name()}", _ => $"{this.selectedLanguage.Name}",
}; };
if (string.IsNullOrWhiteSpace(lang)) if (string.IsNullOrWhiteSpace(lang))
@@ -8,7 +8,7 @@
<ReadFileContent @bind-FileContent="@this.inputText" EnableDragDrop="true" CatchAllDocuments="true"/> <ReadFileContent @bind-FileContent="@this.inputText" EnableDragDrop="true" CatchAllDocuments="true"/>
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your input")" Variant="Variant.Outlined" Lines="6" Sizing="InputSizing.Auto" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your input")" Variant="Variant.Outlined" Lines="6" Sizing="InputSizing.Auto" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" @bind-OtherInput="@this.customTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="@T("Custom target language")" ValidateOther="@this.ValidateCustomLanguage" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name)" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" @bind-OtherInput="@this.customTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="@T("Custom target language")" ValidateOther="@this.ValidateCustomLanguage" />
<EnumSelection T="Complexity" NameFunc="@(complexity => complexity.Name())" @bind-Value="@this.selectedComplexity" Icon="@Icons.Material.Filled.Layers" Label="@T("Target complexity")" AllowOther="@true" @bind-OtherInput="@this.expertInField" OtherValue="Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS" LabelOther="@T("Your expertise")" ValidateOther="@this.ValidateExpertInField" /> <EnumSelection T="Complexity" NameFunc="@(complexity => complexity.Name)" @bind-Value="@this.selectedComplexity" Icon="@Icons.Material.Filled.Layers" Label="@T("Target complexity")" AllowOther="@true" @bind-OtherInput="@this.expertInField" OtherValue="Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS" LabelOther="@T("Your expertise")" ValidateOther="@this.ValidateExpertInField" />
<MudTextField T="string" Sizing="InputSizing.Auto" Lines="2" @bind-Text="@this.importantAspects" class="mb-3" Label="@T("(Optional) Important Aspects")" HelperText="@T("(Optional) Specify aspects for the LLM to focus on when generating a summary, such as summary length or specific topics to emphasize.")" ShrinkLabel="true" Variant="Variant.Outlined" AdornmentIcon="@Icons.Material.Filled.List" Adornment="Adornment.Start"/> <MudTextField T="string" Sizing="InputSizing.Auto" Lines="2" @bind-Text="@this.importantAspects" class="mb-3" Label="@T("(Optional) Important Aspects")" HelperText="@T("(Optional) Specify aspects for the LLM to focus on when generating a summary, such as summary length or specific topics to emphasize.")" ShrinkLabel="true" Variant="Variant.Outlined" AdornmentIcon="@Icons.Material.Filled.List" Adornment="Adornment.Start"/>
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -6,7 +6,7 @@ public static class ComplexityExtensions
extension(Complexity complexity) extension(Complexity complexity)
{ {
public string Name() => complexity switch public string Name => complexity switch
{ {
Complexity.NO_CHANGE => TB("No change in complexity"), Complexity.NO_CHANGE => TB("No change in complexity"),
@@ -18,5 +18,5 @@ else
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your input")" Variant="Variant.Outlined" Lines="6" Sizing="InputSizing.Auto" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/> <MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="@T("Your input")" Variant="Variant.Outlined" Lines="6" Sizing="InputSizing.Auto" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
} }
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" /> <EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting)" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" />
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/> <ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
@@ -39,7 +39,7 @@ public partial class AssistantTranslation : AssistantBaseCore<SettingsDialogTran
protected override string SendToChatVisibleUserPromptText => protected override string SendToChatVisibleUserPromptText =>
$""" $"""
{string.Format(T("Translate the following text to {0}:"), this.selectedTargetLanguage is CommonLanguages.OTHER ? this.customTargetLanguage : this.selectedTargetLanguage.Name())} {string.Format(T("Translate the following text to {0}:"), this.selectedTargetLanguage is CommonLanguages.OTHER ? this.customTargetLanguage : this.selectedTargetLanguage.Name)}
{this.inputText} {this.inputText}
"""; """;
@@ -215,11 +215,11 @@
</MudStack> </MudStack>
<ProfileFormSelection @bind-Profile="@this.editor.Profile" Disabled="@this.IsCurrentBusy"/> <ProfileFormSelection @bind-Profile="@this.editor.Profile" 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="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="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"/> <EnumSelection T="AudienceAgeGroup" NameFunc="@(value => value.Name)" @bind-Value="@this.editor.AudienceAgeGroup" Label="@T("Audience age group")" Disabled="@this.IsCurrentBusy"/>
<EnumSelection T="AudienceOrganizationalLevel" NameFunc="@(value => value.Name())" @bind-Value="@this.editor.AudienceOrganizationalLevel" Label="@T("Audience organizational level")" Disabled="@this.IsCurrentBusy"/> <EnumSelection T="AudienceOrganizationalLevel" NameFunc="@(value => value.Name)" @bind-Value="@this.editor.AudienceOrganizationalLevel" Label="@T("Audience organizational level")" Disabled="@this.IsCurrentBusy"/>
<EnumSelection T="AudienceExpertise" NameFunc="@(value => value.Name())" @bind-Value="@this.editor.AudienceExpertise" Label="@T("Audience expertise")" Disabled="@this.IsCurrentBusy"/> <EnumSelection T="AudienceExpertise" NameFunc="@(value => value.Name)" @bind-Value="@this.editor.AudienceExpertise" Label="@T("Audience expertise")" Disabled="@this.IsCurrentBusy"/>
<MudSwitch T="bool" @bind-Value="@this.editor.ShowSourceReferences" Color="Color.Primary" Disabled="@this.IsCurrentBusy">@T("Show source references")</MudSwitch> <MudSwitch T="bool" @bind-Value="@this.editor.ShowSourceReferences" Color="Color.Primary" Disabled="@this.IsCurrentBusy">@T("Show source references")</MudSwitch>
<MudSwitch T="bool" @bind-Value="@this.editor.OptimizeImages" Color="Color.Primary" Disabled="@this.IsCurrentBusy">@T("Optimize large visual assets")</MudSwitch> <MudSwitch T="bool" @bind-Value="@this.editor.OptimizeImages" Color="Color.Primary" Disabled="@this.IsCurrentBusy">@T("Optimize large visual assets")</MudSwitch>
</MudPaper> </MudPaper>
@@ -147,7 +147,7 @@ public partial class VisualBriefingAssistant : MSGComponentBase
if (!this.SettingsManager.IsAssistantVisible( if (!this.SettingsManager.IsAssistantVisible(
ComponentKind.VISUAL_BRIEFING_ASSISTANT, ComponentKind.VISUAL_BRIEFING_ASSISTANT,
assistantName: T("Visual Briefing Assistant"), assistantName: T("Visual Briefing Assistant"),
requiredPreviewFeature: ComponentKind.VISUAL_BRIEFING_ASSISTANT.RequiredPreviewFeature())) requiredPreviewFeature: ComponentKind.VISUAL_BRIEFING_ASSISTANT.RequiredPreviewFeature))
{ {
this.NavigationManager.NavigateTo(Routes.ASSISTANTS); this.NavigationManager.NavigateTo(Routes.ASSISTANTS);
return; return;
@@ -12,8 +12,8 @@ public static class ChatRoleExtensions
/// <summary> /// <summary>
/// Returns the name of the role. /// Returns the name of the role.
/// </summary> /// </summary>
/// <returns>The name of the role.</returns> /// <value>The name of the role.</value>
public string ToName() => role switch public string Name => role switch
{ {
ChatRole.SYSTEM => TB("System"), ChatRole.SYSTEM => TB("System"),
ChatRole.USER => TB("You"), ChatRole.USER => TB("You"),
@@ -25,8 +25,8 @@ public static class ChatRoleExtensions
/// <summary> /// <summary>
/// Returns the color of the role. /// Returns the color of the role.
/// </summary> /// </summary>
/// <returns>The color of the role.</returns> /// <value>The color of the role.</value>
public Color ToColor() => role switch public Color Color => role switch
{ {
ChatRole.SYSTEM => Color.Info, ChatRole.SYSTEM => Color.Info,
ChatRole.USER => Color.Primary, ChatRole.USER => Color.Primary,
@@ -38,8 +38,8 @@ public static class ChatRoleExtensions
/// <summary> /// <summary>
/// Returns the icon of the role. /// Returns the icon of the role.
/// </summary> /// </summary>
/// <returns>The icon of the role.</returns> /// <value>The icon of the role.</value>
public string ToIcon() => role switch public string Icon => role switch
{ {
ChatRole.SYSTEM => Icons.Material.Filled.Settings, ChatRole.SYSTEM => Icons.Material.Filled.Settings,
ChatRole.USER => Icons.Material.Filled.Person, ChatRole.USER => Icons.Material.Filled.Person,
@@ -51,8 +51,8 @@ public static class ChatRoleExtensions
/// <summary> /// <summary>
/// Returns the specific name of the role for the chat template. /// Returns the specific name of the role for the chat template.
/// </summary> /// </summary>
/// <returns>The name of the role.</returns> /// <value>The name of the role.</value>
public string ToChatTemplateName() => role switch public string ChatTemplateName => role switch
{ {
ChatRole.SYSTEM => TB("System"), ChatRole.SYSTEM => TB("System"),
ChatRole.USER => TB("User"), ChatRole.USER => TB("User"),
@@ -6,14 +6,14 @@
<MudCard Class="@this.CardClasses" Outlined="@true"> <MudCard Class="@this.CardClasses" Outlined="@true">
<MudCardHeader> <MudCardHeader>
<CardHeaderAvatar> <CardHeaderAvatar>
<MudAvatar Color="@this.Role.ToColor()"> <MudAvatar Color="@this.Role.Color">
<MudIcon Icon="@this.Role.ToIcon()"/> <MudIcon Icon="@this.Role.Icon"/>
</MudAvatar> </MudAvatar>
</CardHeaderAvatar> </CardHeaderAvatar>
<CardHeaderContent> <CardHeaderContent>
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2"> <MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
<MudText Typo="Typo.body1"> <MudText Typo="Typo.body1">
@this.Role.ToName() (@this.Time.LocalDateTime) @this.Role.Name (@this.Time.LocalDateTime)
</MudText> </MudText>
@if (this.HasToolTrace) @if (this.HasToolTrace)
{ {
@@ -87,9 +87,9 @@
{ {
<MudTooltip Text="@this.EffectiveExportTitle" Placement="Placement.Bottom"> <MudTooltip Text="@this.EffectiveExportTitle" Placement="Placement.Bottom">
<MudMenu Icon="@Icons.Material.Filled.Save" MaxHeight="@MenuDefaults.MAX_HEIGHT"> <MudMenu Icon="@Icons.Material.Filled.Save" MaxHeight="@MenuDefaults.MAX_HEIGHT">
@foreach (var documentFormat in FileExportFormatExtensions.DOCUMENT_FORMATS) @foreach (var documentFormat in FileExportFormat.DocumentFormats)
{ {
<MudMenuItem OnClick="@(() => this.ExportDocument(documentFormat))" Icon="@documentFormat.ToIcon()" Label="@documentFormat.ToName()"/> <MudMenuItem OnClick="@(() => this.ExportDocument(documentFormat))" Icon="@documentFormat.Icon" Label="@documentFormat.Name"/>
} }
@if (this.MessageFiles.Count > MAX_FILES_WITHOUT_SUBMENUS) @if (this.MessageFiles.Count > MAX_FILES_WITHOUT_SUBMENUS)
{ {
@@ -113,9 +113,9 @@
} }
} }
<MudDivider/> <MudDivider/>
@foreach (var textFormat in FileExportFormatExtensions.TEXT_FORMATS) @foreach (var textFormat in FileExportFormat.TextFormats)
{ {
<MudMenuItem OnClick="@(() => this.ExportDocument(textFormat))" Icon="@textFormat.ToIcon()" Label="@textFormat.ToName()"/> <MudMenuItem OnClick="@(() => this.ExportDocument(textFormat))" Icon="@textFormat.Icon" Label="@textFormat.Name"/>
} }
</MudMenu> </MudMenu>
</MudTooltip> </MudTooltip>
@@ -126,7 +126,7 @@
<MudMenu Icon="@Icons.Material.Filled.Apps" Disabled="@(!this.IsSendToEnabled)" MaxHeight="@MenuDefaults.MAX_HEIGHT"> <MudMenu Icon="@Icons.Material.Filled.Apps" Disabled="@(!this.IsSendToEnabled)" MaxHeight="@MenuDefaults.MAX_HEIGHT">
@foreach (var destination in this.SendToDestinations) @foreach (var destination in this.SendToDestinations)
{ {
<MudMenuItem OnClick="@(() => this.SendTo(destination))" Label="@destination.Name()"/> <MudMenuItem OnClick="@(() => this.SendTo(destination))" Label="@destination.Name"/>
} }
</MudMenu> </MudMenu>
</MudTooltip> </MudTooltip>
@@ -274,8 +274,8 @@ public partial class ContentBlockComponent : MSGComponentBase
/// </remarks> /// </remarks>
private string ExportLabel(MessageFile file) private string ExportLabel(MessageFile file)
{ {
var isTable = file.Format.IsTabular(); var isTable = file.Format.IsTabular;
var filesOfItsKind = this.MessageFiles.Where(entry => entry.Format.IsTabular() == isTable).ToList(); var filesOfItsKind = this.MessageFiles.Where(entry => entry.Format.IsTabular == isTable).ToList();
var extensionOrName = file.ToFileExtensionOrName(); var extensionOrName = file.ToFileExtensionOrName();
var typeName = file.ToName(); var typeName = file.ToName();
@@ -308,7 +308,7 @@ public partial class ContentBlockComponent : MSGComponentBase
/// for the entire answer out of sight. Each submenu keeps the order of the answer, so "Code /// for the entire answer out of sight. Each submenu keeps the order of the answer, so "Code
/// block 3" is the third entry of its submenu as well. /// block 3" is the third entry of its submenu as well.
/// </remarks> /// </remarks>
private IEnumerable<IGrouping<bool, MessageFile>> MessageFilesByKind => this.MessageFiles.GroupBy(file => file.Format.IsTabular()).OrderByDescending(isTable => isTable.Key); private IEnumerable<IGrouping<bool, MessageFile>> MessageFilesByKind => this.MessageFiles.GroupBy(file => file.Format.IsTabular).OrderByDescending(isTable => isTable.Key);
/// <summary> /// <summary>
/// Names the submenu of one kind of files in the export menu, with the number of its files. /// Names the submenu of one kind of files in the export menu, with the number of its files.
@@ -322,7 +322,7 @@ public partial class ContentBlockComponent : MSGComponentBase
/// <summary> /// <summary>
/// Returns the icon of the submenu of one kind of files in the export menu. /// Returns the icon of the submenu of one kind of files in the export menu.
/// </summary> /// </summary>
private static string ExportGroupIcon(IGrouping<bool, MessageFile> filesOfAKind) => filesOfAKind.Key ? FileExportFormat.CSV.ToIcon() : FileExportFormat.SOURCE_CODE.ToIcon(); private static string ExportGroupIcon(IGrouping<bool, MessageFile> filesOfAKind) => filesOfAKind.Key ? FileExportFormat.CSV.Icon : FileExportFormat.SOURCE_CODE.Icon;
/// <summary> /// <summary>
/// What the export offers, falling back to the chat wording when nobody named it. /// What the export offers, falling back to the chat wording when nobody named it.
@@ -649,7 +649,7 @@ public partial class ContentBlockComponent : MSGComponentBase
// here which would fall out of sync with the one in FileExportFormatExtensions. // here which would fall out of sync with the one in FileExportFormatExtensions.
// //
var disclosureService = this.GetsAIGeneratedContentDisclosure ? this.DisclosureService : null; var disclosureService = this.GetsAIGeneratedContentDisclosure ? this.DisclosureService : null;
if (format.UsesPandoc()) if (format.UsesPandoc)
await PandocExport.ToDocument(this.RustService, this.PandocAvailability, disclosureService, this.EffectiveExportTitle, format, this.Content, this.ExportFileName); await PandocExport.ToDocument(this.RustService, this.PandocAvailability, disclosureService, this.EffectiveExportTitle, format, this.Content, this.ExportFileName);
else if (this.Content.TryGetExportMarkdown(out var markdown)) else if (this.Content.TryGetExportMarkdown(out var markdown))
await PlainFileExport.ToFile(this.RustService, this.EffectiveExportTitle, format, disclosureService?.AddDisclosureToMarkdown(markdown) ?? markdown, this.ExportFileName); await PlainFileExport.ToFile(this.RustService, this.EffectiveExportTitle, format, disclosureService?.AddDisclosureToMarkdown(markdown) ?? markdown, this.ExportFileName);
+3 -3
View File
@@ -127,7 +127,7 @@ public sealed class ContentText : IContent
try try
{ {
// Most answers, those of the agents among them, received nothing to store, and need no database: // Most answers, those of the agents among them, received nothing to store, and need no database:
if (!this.SourcePassages.Any(passage => passage.HoldsTextsToStore())) if (!this.SourcePassages.Any(passage => passage.HoldsTextsToStore))
return; return;
if (await ChatProvenance.GetStoreAsync() is { } store && await this.StoreReceivedContentAsync(store, chatId)) if (await ChatProvenance.GetStoreAsync() is { } store && await this.StoreReceivedContentAsync(store, chatId))
@@ -158,7 +158,7 @@ public sealed class ContentText : IContent
var passages = new List<SourcePassage>(this.SourcePassages.Count); var passages = new List<SourcePassage>(this.SourcePassages.Count);
foreach (var passage in this.SourcePassages) foreach (var passage in this.SourcePassages)
{ {
if (!passage.HoldsTextsToStore()) if (!passage.HoldsTextsToStore)
{ {
passages.Add(passage); passages.Add(passage);
continue; continue;
@@ -168,7 +168,7 @@ public sealed class ContentText : IContent
try try
{ {
// Not cancellable: the answer is complete, also when the user stopped it. // Not cancellable: the answer is complete, also when the user stopped it.
provenanceId = await store.StoreAsync(chatId, passage.GetProvenanceKind(), passage.Text, passage.SurroundingContent, CancellationToken.None); provenanceId = await store.StoreAsync(chatId, passage.ProvenanceKind, passage.Text, passage.SurroundingContent, CancellationToken.None);
} }
catch (Exception exception) catch (Exception exception)
{ {
@@ -95,13 +95,13 @@ public static class IContentExtensions
/// <returns>The content of the file to write.</returns> /// <returns>The content of the file to write.</returns>
public string ToExportContent(MessageFile file) public string ToExportContent(MessageFile file)
{ {
if (file.Format.IsTabular()) if (file.Format.IsTabular)
return file.Content; return file.Content;
if (file.Format is FileExportFormat.SOURCE_CODE) if (file.Format is FileExportFormat.SOURCE_CODE)
return ToSourceCodeFile(file); return ToSourceCodeFile(file);
var sources = content.Sources.ToExportMarkdown(file.Format.FollowsPageAnchors()); var sources = content.Sources.ToExportMarkdown(file.Format.FollowsPageAnchors);
if (file.Format is FileExportFormat.MARKDOWN) if (file.Format is FileExportFormat.MARKDOWN)
return AppendSources(file.Content, sources); return AppendSources(file.Content, sources);
@@ -25,8 +25,8 @@ public static class IImageSourceExtensions
/// <returns>The size limit of one image file.</returns> /// <returns>The size limit of one image file.</returns>
public static long MaxImageSizeBytesFor(AIStudio.Settings.Provider provider) public static long MaxImageSizeBytesFor(AIStudio.Settings.Provider provider)
{ {
var engineLimit = provider.UsedLLMProvider is LLMProviders.SELF_HOSTED ? provider.Host.GetMaxImageSizeBytes() : null; var engineLimit = provider.UsedLLMProvider is LLMProviders.SELF_HOSTED ? provider.Host.MaxImageSizeBytes : null;
var providerLimit = provider.UsedLLMProvider.GetMaxImageSizeBytes(); var providerLimit = provider.UsedLLMProvider.MaxImageSizeBytes;
return Math.Min(Math.Min(engineLimit ?? MAX_IMAGE_SIZE_BYTES, providerLimit ?? MAX_IMAGE_SIZE_BYTES), MAX_IMAGE_SIZE_BYTES); return Math.Min(Math.Min(engineLimit ?? MAX_IMAGE_SIZE_BYTES, providerLimit ?? MAX_IMAGE_SIZE_BYTES), MAX_IMAGE_SIZE_BYTES);
} }
@@ -125,8 +125,8 @@ public partial class AssistantBlock<TSettings> : MSGComponentBase, IAssistantCat
/// <returns><c>true</c> when this block represents the owner.</returns> /// <returns><c>true</c> when this block represents the owner.</returns>
private bool OwnedByThisBlock(MediaImportOwner owner) private bool OwnedByThisBlock(MediaImportOwner owner)
{ {
if (owner.Kind.PersistsOwnSources()) if (owner.Kind.PersistsOwnSources)
return owner.Kind == this.Component.MediaOwnerKind(); return owner.Kind == this.Component.MediaOwnerKind;
if (string.IsNullOrWhiteSpace(this.AssistantSessionInstanceId)) if (string.IsNullOrWhiteSpace(this.AssistantSessionInstanceId))
return owner.Kind is MediaImportOwnerKind.ASSISTANT && owner.Id.StartsWith($"{this.Component}:", StringComparison.Ordinal); return owner.Kind is MediaImportOwnerKind.ASSISTANT && owner.Id.StartsWith($"{this.Component}:", StringComparison.Ordinal);
@@ -256,7 +256,7 @@
<td> <td>
<MudText Typo="Typo.body2"><b>@T("Required minimum")</b></MudText> <MudText Typo="Typo.body2"><b>@T("Required minimum")</b></MudText>
</td> </td>
<td><MudText Typo="Typo.body2">@state.Settings.MinimumLevel.GetName()</MudText></td> <td><MudText Typo="Typo.body2">@state.Settings.MinimumLevel.Name</MudText></td>
</tr> </tr>
</tbody> </tbody>
</MudSimpleTable> </MudSimpleTable>
@@ -290,7 +290,7 @@
<MudStack Spacing="2"> <MudStack Spacing="2">
@foreach (var finding in state.Audit.Findings) @foreach (var finding in state.Audit.Findings)
{ {
<MudAlert Severity="@finding.Severity.GetSeverity()" Variant="Variant.Text" Dense="@true"> <MudAlert Severity="@finding.Severity.Severity" Variant="Variant.Text" Dense="@true">
<strong>@finding.Category</strong><span>: @finding.Description</span> <strong>@finding.Category</strong><span>: @finding.Description</span>
@if (!string.IsNullOrWhiteSpace(finding.Location)) @if (!string.IsNullOrWhiteSpace(finding.Location))
{ {
@@ -185,7 +185,7 @@ public partial class AttachDocuments : MSGComponentBase
var delivery = this.MediaTranscriptionService.GetPendingDelivery(this.EffectiveMediaImportTarget); var delivery = this.MediaTranscriptionService.GetPendingDelivery(this.EffectiveMediaImportTarget);
// Owners that persist their own sources have already taken the media over when the batch // Owners that persist their own sources have already taken the media over when the batch
// started, so re-adding the delivered transcripts here would duplicate them. // started, so re-adding the delivered transcripts here would duplicate them.
var completed = this.EffectiveImportOwner.Kind.PersistsOwnSources() var completed = this.EffectiveImportOwner.Kind.PersistsOwnSources
? Array.Empty<FileAttachment>() ? Array.Empty<FileAttachment>()
: delivery?.Attachments ?? []; : delivery?.Attachments ?? [];
var pending = this.OwnerChat?.Draft.MediaTranscripts ?? []; var pending = this.OwnerChat?.Draft.MediaTranscripts ?? [];
@@ -436,7 +436,7 @@ public partial class AttachDocuments : MSGComponentBase
// Owners that persist their own sources show the file right away and keep it next to the // Owners that persist their own sources show the file right away and keep it next to the
// stored document, instead of waiting for the transcription to be delivered back. // stored document, instead of waiting for the transcription to be delivered back.
if (this.EffectiveImportOwner.Kind.PersistsOwnSources()) if (this.EffectiveImportOwner.Kind.PersistsOwnSources)
{ {
foreach (var mediaPath in mediaPaths) foreach (var mediaPath in mediaPaths)
this.DocumentPaths.Add(FileAttachment.FromPath(mediaPath)); this.DocumentPaths.Add(FileAttachment.FromPath(mediaPath));
@@ -795,7 +795,7 @@ public partial class ChatComponent : MSGComponentBase
get get
{ {
if (this.IsProviderSelected) if (this.IsProviderSelected)
return string.Format(T("Your Prompt (use selected instance '{0}', provider '{1}')"), this.Provider.InstanceName, this.Provider.UsedLLMProvider.ToName()); return string.Format(T("Your Prompt (use selected instance '{0}', provider '{1}')"), this.Provider.InstanceName, this.Provider.UsedLLMProvider.Name);
return this.T("Select a provider first"); return this.T("Select a provider first");
} }
@@ -48,7 +48,7 @@
@T("Confidence Level") @T("Confidence Level")
</MudText> </MudText>
<MudText Typo="Typo.body1" Style="@this.GetCurrentConfidenceColor()"> <MudText Typo="Typo.body1" Style="@this.GetCurrentConfidenceColor()">
<b>@this.currentConfidence.Level.GetName()</b> <b>@this.currentConfidence.Level.Name</b>
</MudText> </MudText>
</MudCardContent> </MudCardContent>
<MudCardActions> <MudCardActions>
@@ -58,7 +58,7 @@
<MudTd Style="white-space: normal; overflow-wrap: anywhere;"> <MudTd Style="white-space: normal; overflow-wrap: anywhere;">
<div style="min-width: 10em;">@context.Name</div> <div style="min-width: 10em;">@context.Name</div>
</MudTd> </MudTd>
<MudTd>@context.Type.GetDisplayName()</MudTd> <MudTd>@context.Type.DisplayName</MudTd>
<MudTd>@this.GetEmbeddingName(context)</MudTd> <MudTd>@this.GetEmbeddingName(context)</MudTd>
<MudTd> <MudTd>
@if (context is IIndexedDataSource) @if (context is IIndexedDataSource)
@@ -306,7 +306,7 @@ public partial class DataSourceManagement : MSGComponentBase
var dialogParameters = new DialogParameters<ConfirmDialog> var dialogParameters = new DialogParameters<ConfirmDialog>
{ {
{ x => x.Message, string.Format(T("Are you sure you want to delete the data source '{0}' of type '{1}'?"), dataSource.Name, dataSource.Type.GetDisplayName()) }, { x => x.Message, string.Format(T("Are you sure you want to delete the data source '{0}' of type '{1}'?"), dataSource.Name, dataSource.Type.DisplayName) },
}; };
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Delete Data Source"), dialogParameters, DialogOptions.FULLSCREEN); var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Delete Data Source"), dialogParameters, DialogOptions.FULLSCREEN);
@@ -146,7 +146,7 @@
@if (source.DataSource is IInternalDataSource internalSource) @if (source.DataSource is IInternalDataSource internalSource)
{ {
<MudSpacer/> <MudSpacer/>
<MudTooltip Text="@internalSource.ConfidenceLevel.GetName()"> <MudTooltip Text="@internalSource.ConfidenceLevel.Name">
<MudIcon Icon="@Icons.Material.Filled.Security" Size="Size.Small" Class="confidence-icon" Style="@this.GetConfidenceIconStyle(internalSource)"/> <MudIcon Icon="@Icons.Material.Filled.Security" Size="Size.Small" Class="confidence-icon" Style="@this.GetConfidenceIconStyle(internalSource)"/>
</MudTooltip> </MudTooltip>
} }
@@ -15,7 +15,7 @@
{ {
<MudIcon Icon="@this.GetBlockedIcon()" Size="Size.Small" Color="@this.GetBlockedIconColor()" Style="flex-shrink: 0;"/> <MudIcon Icon="@this.GetBlockedIcon()" Size="Size.Small" Color="@this.GetBlockedIconColor()" Style="flex-shrink: 0;"/>
} }
<MudTooltip Text="@internalSource.ConfidenceLevel.GetName()"> <MudTooltip Text="@internalSource.ConfidenceLevel.Name">
<MudIcon Icon="@Icons.Material.Filled.Security" Size="Size.Small" Class="confidence-icon" Style="@this.GetConfidenceIconStyle(internalSource)"/> <MudIcon Icon="@Icons.Material.Filled.Security" Size="Size.Small" Class="confidence-icon" Style="@this.GetConfidenceIconStyle(internalSource)"/>
</MudTooltip> </MudTooltip>
} }
@@ -66,7 +66,7 @@ public sealed class HighlightedCodeBlock : ComponentBase
builder.AddContent(2, this.Code[position..token.Start]); builder.AddContent(2, this.Code[position..token.Start]);
builder.OpenElement(3, "span"); builder.OpenElement(3, "span");
builder.AddAttribute(4, "class", token.Kind.ToCssClass()); builder.AddAttribute(4, "class", token.Kind.CssClass);
builder.AddContent(5, this.Code.Substring(token.Start, token.Length)); builder.AddContent(5, this.Code.Substring(token.Start, token.Length));
builder.CloseElement(); builder.CloseElement();
position = token.Start + token.Length; position = token.Start + token.Length;
@@ -4,7 +4,7 @@
<CompactExpansionPanel HeaderText="@this.HeaderTextOf(area)" HeaderIcon="@IconOf(area)" Class="mb-3 rounded" Expanded="@this.expandedAreas.Contains(area)" ExpandedChanged="@(expanded => this.SetExpanded(area, expanded))"> <CompactExpansionPanel HeaderText="@this.HeaderTextOf(area)" HeaderIcon="@IconOf(area)" Class="mb-3 rounded" Expanded="@this.expandedAreas.Contains(area)" ExpandedChanged="@(expanded => this.SetExpanded(area, expanded))">
@if (this.expandedAreas.Contains(area)) @if (this.expandedAreas.Contains(area))
{ {
@foreach (var purpose in Enum.GetValues<LayoutPurpose>().Where(purpose => purpose.Area() == area)) @foreach (var purpose in Enum.GetValues<LayoutPurpose>().Where(purpose => purpose.Area == area))
{ {
@this.ChoiceContent(purpose) @this.ChoiceContent(purpose)
} }
@@ -35,8 +35,8 @@ public partial class LayoutChoicePanels : ComponentBase
private string HeaderTextOf(LayoutPurposeArea area) private string HeaderTextOf(LayoutPurposeArea area)
{ {
var chosen = Enum.GetValues<LayoutPurpose>().Count(purpose => purpose.Area() == area && this.IsChosen(purpose)); var chosen = Enum.GetValues<LayoutPurpose>().Count(purpose => purpose.Area == area && this.IsChosen(purpose));
return chosen == 0 ? area.Label() : $"{area.Label()} ({chosen})"; return chosen == 0 ? area.Label : $"{area.Label} ({chosen})";
} }
private void SetExpanded(LayoutPurposeArea area, bool expanded) private void SetExpanded(LayoutPurposeArea area, bool expanded)
@@ -2,7 +2,7 @@
@using AIStudio.Settings.DataModel @using AIStudio.Settings.DataModel
@inherits MSGComponentBase @inherits MSGComponentBase
<MudSelect T="OutboundDataRestriction" Value="@this.Value" ValueChanged="@this.ValueChanged" Text="@this.Value.GetName()" Label="@this.Label" Class="mb-1" OpenIcon="@Icons.Material.Filled.ExpandMore" AdornmentColor="Color.Info" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Shield"> <MudSelect T="OutboundDataRestriction" Value="@this.Value" ValueChanged="@this.ValueChanged" Text="@this.Value.Name" Label="@this.Label" Class="mb-1" OpenIcon="@Icons.Material.Filled.ExpandMore" AdornmentColor="Color.Info" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Shield">
@foreach (var restriction in ConfigurationSelectDataFactory.GetOutboundDataRestrictionData(this.Minimum)) @foreach (var restriction in ConfigurationSelectDataFactory.GetOutboundDataRestrictionData(this.Minimum))
{ {
<MudSelectItem T="OutboundDataRestriction" Value="@restriction.Value"> <MudSelectItem T="OutboundDataRestriction" Value="@restriction.Value">
@@ -11,7 +11,7 @@
} }
</MudSelect> </MudSelect>
<MudJustifiedText Typo="Typo.body2" Class="mb-1"> <MudJustifiedText Typo="Typo.body2" Class="mb-1">
@this.Value.GetDescription() @this.Value.Description
</MudJustifiedText> </MudJustifiedText>
@if (this.LimitationText is { } limitationText) @if (this.LimitationText is { } limitationText)
{ {
@@ -12,8 +12,8 @@ public static class ReadWebContentStepsExtensions
/// <summary> /// <summary>
/// Gets the text representation of a given ReadWebContentSteps enum value. /// Gets the text representation of a given ReadWebContentSteps enum value.
/// </summary> /// </summary>
/// <returns>>The text representation of the process step.</returns> /// <value>The text representation of the process step.</value>
public string GetText() => step switch public string Text => step switch
{ {
ReadWebContentSteps.START => TB("Start"), ReadWebContentSteps.START => TB("Start"),
ReadWebContentSteps.LOADING => TB("Loading"), ReadWebContentSteps.LOADING => TB("Loading"),
@@ -128,14 +128,14 @@ public partial class SettingsPanelApp : SettingsPanelBase
// Several configuration plugins may contribute at the same time, e.g. one preview feature // Several configuration plugins may contribute at the same time, e.g. one preview feature
// for the whole organization and another one for a single department: // for the whole organization and another one for a single department:
if (ManagedConfiguration.TryGet(x => x.App, x => x.EnabledPreviewFeatures, out var meta) && meta.HasPluginContribution) if (ManagedConfiguration.TryGet(x => x.App, x => x.EnabledPreviewFeatures, out var meta) && meta.HasPluginContribution)
return meta.PluginContributions.Values.SelectMany(contribution => contribution).Where(x => !x.IsReleased()).ToHashSet(); return meta.PluginContributions.Values.SelectMany(contribution => contribution).Where(x => !x.IsReleased).ToHashSet();
return []; return [];
} }
private bool IsPluginContributedPreviewFeature(PreviewFeatures feature) private bool IsPluginContributedPreviewFeature(PreviewFeatures feature)
{ {
if (feature.IsReleased()) if (feature.IsReleased)
return false; return false;
if (!ManagedConfiguration.TryGet(x => x.App, x => x.EnabledPreviewFeatures, out var meta) || !meta.HasPluginContribution) if (!ManagedConfiguration.TryGet(x => x.App, x => x.EnabledPreviewFeatures, out var meta) || !meta.HasPluginContribution)
@@ -146,7 +146,7 @@ public partial class SettingsPanelApp : SettingsPanelBase
private HashSet<PreviewFeatures> GetSelectedPreviewFeatures() private HashSet<PreviewFeatures> GetSelectedPreviewFeatures()
{ {
var enabled = this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures.Where(x => !x.IsReleased()).ToHashSet(); var enabled = this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures.Where(x => !x.IsReleased).ToHashSet();
enabled.UnionWith(this.GetPluginContributedPreviewFeatures()); enabled.UnionWith(this.GetPluginContributedPreviewFeatures());
return enabled; return enabled;
} }
@@ -35,7 +35,7 @@
</HeaderContent> </HeaderContent>
<RowTemplate> <RowTemplate>
<MudTd Style="vertical-align: top;"> <MudTd Style="vertical-align: top;">
@context.ToName() @context.Name
</MudTd> </MudTd>
<MudTd> <MudTd>
<MudMarkdown Value="@context.GetConfidence(this.SettingsManager).Description" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/> <MudMarkdown Value="@context.GetConfidence(this.SettingsManager).Description" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE"/>
@@ -54,7 +54,7 @@
continue; continue;
<MudMenuItem OnClick="@(async () => await this.ChangeCustomConfidenceLevel(context, confidenceLevel))"> <MudMenuItem OnClick="@(async () => await this.ChangeCustomConfidenceLevel(context, confidenceLevel))">
@confidenceLevel.GetName() @confidenceLevel.Name
</MudMenuItem> </MudMenuItem>
} }
</MudMenu> </MudMenu>
@@ -8,7 +8,7 @@ public partial class SettingsPanelConfidence : SettingsPanelBase
private string GetCurrentConfidenceLevelName(LLMProviders llmProvider) private string GetCurrentConfidenceLevelName(LLMProviders llmProvider)
{ {
if (this.TryGetShownConfidenceLevel(llmProvider, out var level)) if (this.TryGetShownConfidenceLevel(llmProvider, out var level))
return level.GetName(); return level.Name;
return T("Not yet configured"); return T("Not yet configured");
} }
Loaded 100 of 286 files, more files were not shown because too many files have changed in this diff. Show more