mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-20 16:38:01 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebe00812e2 | ||
|
|
ae72c50236 | ||
|
|
48874d617a | ||
|
|
63be312bb4 | ||
|
|
06f66fdab2 |
No files matched your search
@@ -11,7 +11,7 @@ Things we are currently working on:
|
|||||||
- [x] ~~App: Add an option to show preview features (PR [#222](https://github.com/MindWorkAI/AI-Studio/pull/222))~~
|
- [x] ~~App: Add an option to show preview features (PR [#222](https://github.com/MindWorkAI/AI-Studio/pull/222))~~
|
||||||
- [x] ~~App: Configure embedding providers (PR [#224](https://github.com/MindWorkAI/AI-Studio/pull/224))~~
|
- [x] ~~App: Configure embedding providers (PR [#224](https://github.com/MindWorkAI/AI-Studio/pull/224))~~
|
||||||
- [x] ~~App: Implement an [ERI](https://github.com/MindWorkAI/ERI) server coding assistant (PR [#231](https://github.com/MindWorkAI/AI-Studio/pull/231))~~
|
- [x] ~~App: Implement an [ERI](https://github.com/MindWorkAI/ERI) server coding assistant (PR [#231](https://github.com/MindWorkAI/AI-Studio/pull/231))~~
|
||||||
- [ ] App: Management of data sources (local & external data via [ERI](https://github.com/MindWorkAI/ERI))
|
- [x] ~~App: Management of data sources (local & external data via [ERI](https://github.com/MindWorkAI/ERI)) (PR [#259](https://github.com/MindWorkAI/AI-Studio/pull/259))~~
|
||||||
- [ ] Runtime: Extract data from txt / md / pdf / docx / xlsx files
|
- [ ] Runtime: Extract data from txt / md / pdf / docx / xlsx files
|
||||||
- [ ] (*Optional*) Runtime: Implement internal embedding provider through [fastembed-rs](https://github.com/Anush008/fastembed-rs)
|
- [ ] (*Optional*) Runtime: Implement internal embedding provider through [fastembed-rs](https://github.com/Anush008/fastembed-rs)
|
||||||
- [ ] App: Implement external embedding providers
|
- [ ] App: Implement external embedding providers
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,10 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MindWork AI Studio", "MindWork AI Studio\MindWork AI Studio.csproj", "{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MindWork AI Studio", "MindWork AI Studio\MindWork AI Studio.csproj", "{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ERIClients", "ERIClients", "{5C2AF789-287B-4FCB-B675-7273D8CD4579}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ERIClientV1", "ERIClientV1\ERIClientV1.csproj", "{9E35A273-0FA6-4BD5-8880-A1DDAC106926}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -12,5 +16,12 @@ Global
|
|||||||
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.Build.0 = Release|Any CPU
|
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9E35A273-0FA6-4BD5-8880-A1DDAC106926}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9E35A273-0FA6-4BD5-8880-A1DDAC106926}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9E35A273-0FA6-4BD5-8880-A1DDAC106926}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9E35A273-0FA6-4BD5-8880-A1DDAC106926}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{9E35A273-0FA6-4BD5-8880-A1DDAC106926} = {5C2AF789-287B-4FCB-B675-7273D8CD4579}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
@@ -18,7 +18,7 @@ public sealed class AgentTextContentCleaner(ILogger<AgentBase> logger, SettingsM
|
|||||||
|
|
||||||
#region Overrides of AgentBase
|
#region Overrides of AgentBase
|
||||||
|
|
||||||
public override Settings.Provider? ProviderSettings { get; set; }
|
public override AIStudio.Settings.Provider? ProviderSettings { get; set; }
|
||||||
|
|
||||||
protected override Type Type => Type.SYSTEM;
|
protected override Type Type => Type.SYSTEM;
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ else
|
|||||||
<MudButton Disabled="@this.AreServerPresetsBlocked" OnClick="@this.AddERIServer" Variant="Variant.Filled" Color="Color.Primary">
|
<MudButton Disabled="@this.AreServerPresetsBlocked" OnClick="@this.AddERIServer" Variant="Variant.Filled" Color="Color.Primary">
|
||||||
Add ERI server preset
|
Add ERI server preset
|
||||||
</MudButton>
|
</MudButton>
|
||||||
<MudButton OnClick="@this.RemoveERIServer" Disabled="@(this.AreServerPresetsBlocked || this.IsNoneERIServerSelected)" Variant="Variant.Filled" Color="Color.Primary">
|
<MudButton OnClick="@this.RemoveERIServer" Disabled="@(this.AreServerPresetsBlocked || this.IsNoneERIServerSelected)" Variant="Variant.Filled" Color="Color.Error">
|
||||||
Delete this server preset
|
Delete this server preset
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
@@ -346,4 +346,4 @@ else
|
|||||||
</MudText>
|
</MudText>
|
||||||
|
|
||||||
<MudTextSwitch Label="Should we write the generated code to the file system?" Disabled="@this.IsNoneERIServerSelected" @bind-Value="@this.writeToFilesystem" LabelOn="Yes, please write or update all generated code to the file system" LabelOff="No, just show me the code" />
|
<MudTextSwitch Label="Should we write the generated code to the file system?" Disabled="@this.IsNoneERIServerSelected" @bind-Value="@this.writeToFilesystem" LabelOn="Yes, please write or update all generated code to the file system" LabelOff="No, just show me the code" />
|
||||||
<SelectDirectory Label="Base directory where to write the code" @bind-Directory="@this.baseDirectory" Disabled="@(this.IsNoneERIServerSelected || !this.writeToFilesystem)" DirectoryDialogTitle="Select the target directory for the ERI server"/>
|
<SelectDirectory Label="Base directory where to write the code" @bind-Directory="@this.baseDirectory" Disabled="@(this.IsNoneERIServerSelected || !this.writeToFilesystem)" DirectoryDialogTitle="Select the target directory for the ERI server" Validation="@this.ValidateDirectory" />
|
||||||
@@ -476,6 +476,16 @@ public partial class AssistantERI : AssistantBaseCore
|
|||||||
if(this.selectedERIServer is null)
|
if(this.selectedERIServer is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var dialogParameters = new DialogParameters
|
||||||
|
{
|
||||||
|
{ "Message", $"Are you sure you want to delete the ERI server preset '{this.selectedERIServer.ServerName}'?" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete ERI server preset", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
this.SettingsManager.ConfigurationData.ERI.ERIServers.Remove(this.selectedERIServer);
|
this.SettingsManager.ConfigurationData.ERI.ERIServers.Remove(this.selectedERIServer);
|
||||||
this.selectedERIServer = null;
|
this.selectedERIServer = null;
|
||||||
this.ResetForm();
|
this.ResetForm();
|
||||||
@@ -739,6 +749,17 @@ public partial class AssistantERI : AssistantBaseCore
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string? ValidateDirectory(string path)
|
||||||
|
{
|
||||||
|
if(!this.writeToFilesystem)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(path))
|
||||||
|
return "Please provide a base directory for the ERI server to write files to.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private string GetMultiSelectionAuthText(List<Auth> selectedValues)
|
private string GetMultiSelectionAuthText(List<Auth> selectedValues)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public partial class Changelog
|
|||||||
|
|
||||||
public static readonly Log[] LOGS =
|
public static readonly Log[] LOGS =
|
||||||
[
|
[
|
||||||
|
new (201, "v0.9.26, build 201 (2025-01-13 19:11 UTC)", "v0.9.26.md"),
|
||||||
new (200, "v0.9.25, build 200 (2025-01-04 18:33 UTC)", "v0.9.25.md"),
|
new (200, "v0.9.25, build 200 (2025-01-04 18:33 UTC)", "v0.9.25.md"),
|
||||||
new (199, "v0.9.24, build 199 (2025-01-04 11:40 UTC)", "v0.9.24.md"),
|
new (199, "v0.9.24, build 199 (2025-01-04 11:40 UTC)", "v0.9.24.md"),
|
||||||
new (198, "v0.9.23, build 198 (2025-01-02 19:39 UTC)", "v0.9.23.md"),
|
new (198, "v0.9.23, build 198 (2025-01-02 19:39 UTC)", "v0.9.23.md"),
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
|||||||
public EventCallback<ChatThread?> ChatThreadChanged { get; set; }
|
public EventCallback<ChatThread?> ChatThreadChanged { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Settings.Provider Provider { get; set; }
|
public AIStudio.Settings.Provider Provider { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<Settings.Provider> ProviderChanged { get; set; }
|
public EventCallback<AIStudio.Settings.Provider> ProviderChanged { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Action<string> WorkspaceName { get; set; } = _ => { };
|
public Action<string> WorkspaceName { get; set; } = _ => { };
|
||||||
|
|||||||
@@ -12,24 +12,24 @@ public partial class ProviderSelection : ComponentBase
|
|||||||
public AssistantBase? AssistantBase { get; set; }
|
public AssistantBase? AssistantBase { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Settings.Provider ProviderSettings { get; set; }
|
public AIStudio.Settings.Provider ProviderSettings { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<Settings.Provider> ProviderSettingsChanged { get; set; }
|
public EventCallback<AIStudio.Settings.Provider> ProviderSettingsChanged { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Func<Settings.Provider, string?> ValidateProvider { get; set; } = _ => null;
|
public Func<AIStudio.Settings.Provider, string?> ValidateProvider { get; set; } = _ => null;
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
private SettingsManager SettingsManager { get; init; } = null!;
|
private SettingsManager SettingsManager { get; init; } = null!;
|
||||||
|
|
||||||
private async Task SelectionChanged(Settings.Provider provider)
|
private async Task SelectionChanged(AIStudio.Settings.Provider provider)
|
||||||
{
|
{
|
||||||
this.ProviderSettings = provider;
|
this.ProviderSettings = provider;
|
||||||
await this.ProviderSettingsChanged.InvokeAsync(provider);
|
await this.ProviderSettingsChanged.InvokeAsync(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<Settings.Provider> GetAvailableProviders()
|
private IEnumerable<AIStudio.Settings.Provider> GetAvailableProviders()
|
||||||
{
|
{
|
||||||
var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(this.AssistantBase?.Component ?? Tools.Components.NONE);
|
var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(this.AssistantBase?.Component ?? Tools.Components.NONE);
|
||||||
foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public partial class ReadWebContent : ComponentBase
|
|||||||
public EventCallback<string> ContentChanged { get; set; }
|
public EventCallback<string> ContentChanged { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Settings.Provider ProviderSettings { get; set; }
|
public AIStudio.Settings.Provider ProviderSettings { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool AgentIsRunning { get; set; }
|
public bool AgentIsRunning { get; set; }
|
||||||
@@ -47,7 +47,7 @@ public partial class ReadWebContent : ComponentBase
|
|||||||
private bool urlIsValid;
|
private bool urlIsValid;
|
||||||
private bool isProviderValid;
|
private bool isProviderValid;
|
||||||
|
|
||||||
private Settings.Provider providerSettings;
|
private AIStudio.Settings.Provider providerSettings;
|
||||||
|
|
||||||
#region Overrides of ComponentBase
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
Text="@this.Directory"
|
Text="@this.Directory"
|
||||||
Label="@this.Label"
|
Label="@this.Label"
|
||||||
ReadOnly="@true"
|
ReadOnly="@true"
|
||||||
|
Validation="@this.Validation"
|
||||||
Adornment="Adornment.Start"
|
Adornment="Adornment.Start"
|
||||||
AdornmentIcon="@Icons.Material.Filled.Folder"
|
AdornmentIcon="@Icons.Material.Filled.Folder"
|
||||||
UserAttributes="@SPELLCHECK_ATTRIBUTES"
|
UserAttributes="@SPELLCHECK_ATTRIBUTES"
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ public partial class SelectDirectory : ComponentBase
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string DirectoryDialogTitle { get; set; } = "Select Directory";
|
public string DirectoryDialogTitle { get; set; } = "Select Directory";
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public Func<string, string?> Validation { get; set; } = _ => null;
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
private SettingsManager SettingsManager { get; init; } = null!;
|
private SettingsManager SettingsManager { get; init; } = null!;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<MudStack Row="@true" Spacing="3" Class="mb-3" StretchItems="StretchItems.None" AlignItems="AlignItems.Center">
|
||||||
|
<MudTextField
|
||||||
|
T="string"
|
||||||
|
Text="@this.File"
|
||||||
|
Label="@this.Label"
|
||||||
|
ReadOnly="@true"
|
||||||
|
Validation="@this.Validation"
|
||||||
|
Adornment="Adornment.Start"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.AttachFile"
|
||||||
|
UserAttributes="@SPELLCHECK_ATTRIBUTES"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MudButton StartIcon="@Icons.Material.Filled.FolderOpen" Variant="Variant.Outlined" Color="Color.Primary" Disabled="this.Disabled" OnClick="@this.OpenFileDialog">
|
||||||
|
Choose File
|
||||||
|
</MudButton>
|
||||||
|
</MudStack>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using AIStudio.Settings;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Components;
|
||||||
|
|
||||||
|
public partial class SelectFile : ComponentBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public string File { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<string> FileChanged { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool Disabled { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string Label { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string FileDialogTitle { get; set; } = "Select File";
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public Func<string, string?> Validation { get; set; } = _ => null;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private SettingsManager SettingsManager { get; init; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public RustService RustService { get; set; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected ILogger<SelectDirectory> Logger { get; init; } = null!;
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, object?> SPELLCHECK_ATTRIBUTES = new();
|
||||||
|
|
||||||
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
// Configure the spellchecking for the instance name input:
|
||||||
|
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void InternalFileChanged(string file)
|
||||||
|
{
|
||||||
|
this.File = file;
|
||||||
|
this.FileChanged.InvokeAsync(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OpenFileDialog()
|
||||||
|
{
|
||||||
|
var response = await this.RustService.SelectFile(this.FileDialogTitle, string.IsNullOrWhiteSpace(this.File) ? null : this.File);
|
||||||
|
this.Logger.LogInformation($"The user selected the file '{response.SelectedFilePath}'.");
|
||||||
|
|
||||||
|
if (!response.UserCancelled)
|
||||||
|
this.InternalFileChanged(response.SelectedFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.CalendarToday" HeaderText="Assistant: Agenda Options">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect agenda options?" LabelOn="Agenda options are preselected" LabelOff="No agenda options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect most agenda options. This is might be useful when you need to create similar agendas often."/>
|
||||||
|
<ConfigurationText OptionDescription="Preselect a name?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Tag" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectName)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectName = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect a topic?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.EventNote" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectTopic)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectTopic = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect an objective?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Flag" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectObjective)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectObjective = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect a moderator?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Person3" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectModerator)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectModerator = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect a duration?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Schedule" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectDuration)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectDuration = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect a start time?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Schedule" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime = updatedText)" />
|
||||||
|
<ConfigurationOption OptionDescription="Preselect whether the participants should get to know each other" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Participants should get to know each other" LabelOff="Participants do not need to get to know each other" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants = updatedState)" />
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the number of participants" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants)" Data="@ConfigurationSelectDataFactory.GetNumberParticipantsData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants = selectedValue)" OptionHelp="How many participants should be preselected?"/>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect whether the participants should actively involved" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Participants should be actively involved" LabelOff="Participants do not need to be actively involved" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation = updatedState)" />
|
||||||
|
<ConfigurationOption OptionDescription="Preselect whether the meeting is virtual" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Meeting is virtual" LabelOff="Meeting is in person" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual = updatedState)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect a location?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.MyLocation" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectLocation)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectLocation = updatedText)" />
|
||||||
|
<ConfigurationOption OptionDescription="Preselect whether there is a joint dinner" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="There is a joint dinner" LabelOff="There is no joint dinner" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner = updatedState)" />
|
||||||
|
<ConfigurationOption OptionDescription="Preselect whether there is a social event" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="There is a social event" LabelOff="There is no social event" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity = updatedState)" />
|
||||||
|
<ConfigurationOption OptionDescription="Preselect whether participants needs to arrive and depart" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Participants need to arrive and depart" LabelOff="Participants do not need to arrive and depart" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart = updatedState)" />
|
||||||
|
<ConfigurationSlider T="int" OptionDescription="Preselect the approx. lunch time" Min="30" Max="120" Step="5" Unit="minutes" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Value="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime)" ValueUpdate="@(updatedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime = updatedValue)" />
|
||||||
|
<ConfigurationSlider T="int" OptionDescription="Preselect the approx. break time" Min="10" Max="60" Step="5" Unit="minutes" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Value="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime)" ValueUpdate="@(updatedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime = updatedValue)" />
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the agenda language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which agenda language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another agenda language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.AGENDA_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider = selectedValue)"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelAgenda : SettingsPanelBase;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TextFields" HeaderText="Agent: Text Content Cleaner Options">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<MudText Typo="Typo.body1" Class="mb-3">
|
||||||
|
Use Case: this agent is used to clean up text content. It extracts the main content, removes advertisements and other irrelevant things,
|
||||||
|
and attempts to convert relative links into absolute links so that they can be used.
|
||||||
|
</MudText>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect text content cleaner options?" LabelOn="Options are preselected" LabelOff="No options are preselected" State="@(() => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions = updatedState)" OptionHelp="When enabled, you can preselect some agent options. This is might be useful when you prefer a LLM."/>
|
||||||
|
<ConfigurationProviderSelection Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelAgentContentCleaner : SettingsPanelBase;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@using AIStudio.Settings.DataModel
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Apps" HeaderText="App Options">
|
||||||
|
<ConfigurationSelect OptionDescription="Color theme" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreferredTheme)" Data="@ConfigurationSelectDataFactory.GetThemesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreferredTheme = selectedValue)" OptionHelp="Choose the color theme that best suits for you."/>
|
||||||
|
<ConfigurationOption OptionDescription="Save energy?" LabelOn="Energy saving is enabled" LabelOff="Energy saving is disabled" State="@(() => this.SettingsManager.ConfigurationData.App.IsSavingEnergy)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.App.IsSavingEnergy = updatedState)" OptionHelp="When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available."/>
|
||||||
|
<ConfigurationOption OptionDescription="Enable spellchecking?" LabelOn="Spellchecking is enabled" LabelOff="Spellchecking is disabled" State="@(() => this.SettingsManager.ConfigurationData.App.EnableSpellchecking)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.App.EnableSpellchecking = updatedState)" OptionHelp="When enabled, spellchecking will be active in all input fields. Depending on your operating system, errors may not be visually highlighted, but right-clicking may still offer possible corrections." />
|
||||||
|
<ConfigurationSelect OptionDescription="Check for updates" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UpdateBehavior)" Data="@ConfigurationSelectDataFactory.GetUpdateBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UpdateBehavior = selectedValue)" OptionHelp="How often should we check for app updates?"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Navigation bar behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.NavigationBehavior)" Data="@ConfigurationSelectDataFactory.GetNavBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.NavigationBehavior = selectedValue)" OptionHelp="Select the desired behavior for the navigation bar."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preview feature visibility" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreviewVisibility)" Data="@ConfigurationSelectDataFactory.GetPreviewVisibility()" SelectionUpdate="@this.UpdatePreviewFeatures" OptionHelp="Do you want to show preview features in the app?"/>
|
||||||
|
|
||||||
|
@if(this.SettingsManager.ConfigurationData.App.PreviewVisibility > PreviewVisibility.NONE)
|
||||||
|
{
|
||||||
|
var availablePreviewFeatures = ConfigurationSelectDataFactory.GetPreviewFeaturesData(this.SettingsManager).ToList();
|
||||||
|
if (availablePreviewFeatures.Count > 0)
|
||||||
|
{
|
||||||
|
<ConfigurationMultiSelect OptionDescription="Select preview features" SelectedValues="@(() => this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures)" Data="@availablePreviewFeatures" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures = selectedValue)" OptionHelp="Which preview features would you like to enable?"/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<ConfigurationProviderSelection Data="@this.AvailableLLMProvidersFunc()" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreselectedProvider = selectedValue)" HelpText="@(() => "Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence.")"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreselectedProfile = selectedValue)" OptionHelp="Would you like to set one of your profiles as the default for the entire app? When you configure a different profile for an assistant, it will always take precedence."/>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelApp : SettingsPanelBase
|
||||||
|
{
|
||||||
|
private void UpdatePreviewFeatures(PreviewVisibility previewVisibility)
|
||||||
|
{
|
||||||
|
this.SettingsManager.ConfigurationData.App.PreviewVisibility = previewVisibility;
|
||||||
|
this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures = previewVisibility.FilterPreviewFeatures(this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@using AIStudio.Settings.DataModel
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Psychology" HeaderText="Assistant: Bias of the Day">
|
||||||
|
|
||||||
|
<ConfigurationOption OptionDescription="Restrict to one bias a day?" LabelOn="Yes, you can only retrieve one bias per day" LabelOff="No restriction. You can retrieve as many biases as you want per day." State="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.RestrictOneBiasPerDay)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.BiasOfTheDay.RestrictOneBiasPerDay = updatedState)"/>
|
||||||
|
|
||||||
|
<MudField Label="Statistics" Variant="Variant.Outlined" Class="mb-2">
|
||||||
|
<MudText Typo="Typo.body1">
|
||||||
|
You have learned about @this.SettingsManager.ConfigurationData.BiasOfTheDay.UsedBias.Count out of @BiasCatalog.ALL_BIAS.Count biases.
|
||||||
|
</MudText>
|
||||||
|
<MudButton Size="Size.Small" Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.Restore" Color="Color.Error" OnClick="@(() => this.ResetBiasOfTheDayHistory())">
|
||||||
|
Reset
|
||||||
|
</MudButton>
|
||||||
|
</MudField>
|
||||||
|
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect options?" LabelOn="Options are preselected" LabelOff="No options are preselected" State="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect options. This is might be useful when you prefer a specific language or LLM model."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the language" Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another language" Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.BiasOfTheDay.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.BIAS_DAY_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using AIStudio.Dialogs;
|
||||||
|
|
||||||
|
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||||
|
|
||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelAssistantBias : SettingsPanelBase
|
||||||
|
{
|
||||||
|
private async Task ResetBiasOfTheDayHistory()
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters
|
||||||
|
{
|
||||||
|
{ "Message", "Are you sure you want to reset your bias-of-the-day statistics? The system will no longer remember which biases you already know. As a result, biases you are already familiar with may be addressed again." },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Reset your bias-of-the-day statistics", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.SettingsManager.ConfigurationData.BiasOfTheDay.UsedBias.Clear();
|
||||||
|
this.SettingsManager.ConfigurationData.BiasOfTheDay.DateLastBiasDrawn = DateOnly.MinValue;
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using AIStudio.Settings;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public abstract class SettingsPanelBase : ComponentBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public Func<IReadOnlyList<ConfigurationSelectData<string>>> AvailableLLMProvidersFunc { get; set; } = () => [];
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected SettingsManager SettingsManager { get; init; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected IDialogService DialogService { get; init; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected MessageBus MessageBus { get; init; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected RustService RustService { get; init; } = null!;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Chat" HeaderText="Chat Options">
|
||||||
|
<ConfigurationSelect OptionDescription="Shortcut to send input" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.ShortcutSendBehavior)" Data="@ConfigurationSelectDataFactory.GetSendBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.ShortcutSendBehavior = selectedValue)" OptionHelp="Do you want to use any shortcut to send your input?"/>
|
||||||
|
<ConfigurationOption OptionDescription="Show the latest message after loading?" LabelOn="Latest message is shown, after loading a chat" LabelOff="First (oldest) message is shown, after loading a chat" State="@(() => this.SettingsManager.ConfigurationData.Chat.ShowLatestMessageAfterLoading)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Chat.ShowLatestMessageAfterLoading = updatedState)" OptionHelp="When enabled, the latest message is shown after loading a chat. When disabled, the first (oldest) message is shown."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Provider selection when creating new chats" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.AddChatProviderBehavior)" Data="@ConfigurationSelectDataFactory.GetAddChatProviderBehavior()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.AddChatProviderBehavior = selectedValue)" OptionHelp="Control how the LLM provider for added chats is selected."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Provider selection when loading a chat and sending assistant results to chat" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.LoadingProviderBehavior)" Data="@ConfigurationSelectDataFactory.GetLoadingChatProviderBehavior()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.LoadingProviderBehavior = selectedValue)" OptionHelp="Control how the LLM provider for loaded chats is selected and when assistant results are sent to chat."/>
|
||||||
|
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect chat options?" LabelOn="Chat options are preselected" LabelOff="No chat options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Chat.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Chat.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect chat options. This is might be useful when you prefer a specific provider."/>
|
||||||
|
<ConfigurationProviderSelection Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.Chat.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.PreselectedProvider = selectedValue)"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Chat.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.PreselectedProfile = selectedValue)" OptionHelp="Would you like to set one of your profiles as the default for chats?"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelChat : SettingsPanelBase;
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
@using AIStudio.Assistants.Coding
|
||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Code" HeaderText="Assistant: Coding Options">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect coding options?" LabelOn="Coding options are preselected" LabelOff="No coding options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Coding.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the coding options. This is might be useful when you prefer a specific programming language or LLM model."/>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect compiler messages?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" LabelOn="Compiler messages are preselected" LabelOff="Compiler messages are not preselected" State="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectCompilerMessages)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Coding.PreselectCompilerMessages = updatedState)" />
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect a programming language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonCodingLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage = selectedValue)" OptionHelp="Which programming language should be preselected for added contexts?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage is CommonCodingLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another programming language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" Icon="@Icons.Material.Filled.Code" Text="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedOtherProgrammingLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Coding.PreselectedOtherProgrammingLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.CODING_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.PreselectedProvider = selectedValue)"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelCoding : SettingsPanelBase;
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@using AIStudio.Settings.DataModel
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
|
||||||
|
{
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.IntegrationInstructions" HeaderText="Configure Data Sources">
|
||||||
|
<PreviewPrototype/>
|
||||||
|
<MudText Typo="Typo.h4" Class="mb-3">
|
||||||
|
Configured Data Sources
|
||||||
|
</MudText>
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
You might configure different data sources. A data source can include one file, all files
|
||||||
|
in a directory, or data from your company. Later, you can incorporate these data sources
|
||||||
|
as needed when the AI requires this data to complete a certain task.
|
||||||
|
</MudJustifiedText>
|
||||||
|
|
||||||
|
<MudTable Items="@this.SettingsManager.ConfigurationData.DataSources" Hover="@true" Class="border-dashed border rounded-lg">
|
||||||
|
<ColGroup>
|
||||||
|
<col style="width: 3em;"/>
|
||||||
|
<col/>
|
||||||
|
<col style="width: 12em;"/>
|
||||||
|
<col style="width: 12em;"/>
|
||||||
|
<col style="width: 40em;"/>
|
||||||
|
</ColGroup>
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>#</MudTh>
|
||||||
|
<MudTh>Name</MudTh>
|
||||||
|
<MudTh>Type</MudTh>
|
||||||
|
<MudTh>Embedding</MudTh>
|
||||||
|
<MudTh Style="text-align: left;">Actions</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd>@context.Num</MudTd>
|
||||||
|
<MudTd>@context.Name</MudTd>
|
||||||
|
<MudTd>@context.Type.GetDisplayName()</MudTd>
|
||||||
|
<MudTd>@this.GetEmbeddingName(context)</MudTd>
|
||||||
|
|
||||||
|
<MudTd Style="text-align: left;">
|
||||||
|
@if (context is IERIDataSource)
|
||||||
|
{
|
||||||
|
@* <MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Info" Class="ma-2" OnClick="() => this.ShowInformation(context)"> *@
|
||||||
|
@* Show Information *@
|
||||||
|
@* </MudButton> *@
|
||||||
|
}
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditDataSource(context)">
|
||||||
|
Edit
|
||||||
|
</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteDataSource(context)">
|
||||||
|
Delete
|
||||||
|
</MudButton>
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
|
||||||
|
@if (this.SettingsManager.ConfigurationData.DataSources.Count == 0)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.h6" Class="mt-3">No data sources configured yet.</MudText>
|
||||||
|
}
|
||||||
|
|
||||||
|
<MudMenu EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="Add Data Source" Color="Color.Primary" Variant="Variant.Filled" AnchorOrigin="Origin.CenterCenter" TransformOrigin="Origin.TopLeft" Class="mt-3 mb-6">
|
||||||
|
<MudMenuItem OnClick="() => this.AddDataSource(DataSourceType.ERI_V1)">External Data (ERI-Server v1)</MudMenuItem>
|
||||||
|
<MudMenuItem OnClick="() => this.AddDataSource(DataSourceType.LOCAL_DIRECTORY)">Local Directory</MudMenuItem>
|
||||||
|
<MudMenuItem OnClick="() => this.AddDataSource(DataSourceType.LOCAL_FILE)">Local File</MudMenuItem>
|
||||||
|
</MudMenu>
|
||||||
|
</ExpansionPanel>
|
||||||
|
}
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
using AIStudio.Dialogs;
|
||||||
|
using AIStudio.Settings;
|
||||||
|
using AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
|
using ERI_Client.V1;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||||
|
|
||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelDataSources : SettingsPanelBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public List<ConfigurationSelectData<string>> AvailableDataSources { get; set; } = new();
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<List<ConfigurationSelectData<string>>> AvailableDataSourcesChanged { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public Func<IReadOnlyList<ConfigurationSelectData<string>>> AvailableEmbeddingsFunc { get; set; } = () => [];
|
||||||
|
|
||||||
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await this.UpdateDataSources();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private string GetEmbeddingName(IDataSource dataSource)
|
||||||
|
{
|
||||||
|
if(dataSource is IInternalDataSource internalDataSource)
|
||||||
|
{
|
||||||
|
var matchedEmbedding = this.SettingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(x => x.Id == internalDataSource.EmbeddingId);
|
||||||
|
if(matchedEmbedding == default)
|
||||||
|
return "No valid embedding";
|
||||||
|
|
||||||
|
return matchedEmbedding.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dataSource is IExternalDataSource)
|
||||||
|
return "External (ERI)";
|
||||||
|
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AddDataSource(DataSourceType type)
|
||||||
|
{
|
||||||
|
IDataSource? addedDataSource = null;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case DataSourceType.LOCAL_FILE:
|
||||||
|
var localFileDialogParameters = new DialogParameters<DataSourceLocalFileDialog>
|
||||||
|
{
|
||||||
|
{ x => x.IsEditing, false },
|
||||||
|
{ x => x.AvailableEmbeddings, this.AvailableEmbeddingsFunc() }
|
||||||
|
};
|
||||||
|
|
||||||
|
var localFileDialogReference = await this.DialogService.ShowAsync<DataSourceLocalFileDialog>("Add Local File as Data Source", localFileDialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var localFileDialogResult = await localFileDialogReference.Result;
|
||||||
|
if (localFileDialogResult is null || localFileDialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var localFile = (DataSourceLocalFile)localFileDialogResult.Data!;
|
||||||
|
localFile = localFile with { Num = this.SettingsManager.ConfigurationData.NextDataSourceNum++ };
|
||||||
|
addedDataSource = localFile;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataSourceType.LOCAL_DIRECTORY:
|
||||||
|
var localDirectoryDialogParameters = new DialogParameters<DataSourceLocalDirectoryDialog>
|
||||||
|
{
|
||||||
|
{ x => x.IsEditing, false },
|
||||||
|
{ x => x.AvailableEmbeddings, this.AvailableEmbeddingsFunc() }
|
||||||
|
};
|
||||||
|
|
||||||
|
var localDirectoryDialogReference = await this.DialogService.ShowAsync<DataSourceLocalDirectoryDialog>("Add Local Directory as Data Source", localDirectoryDialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var localDirectoryDialogResult = await localDirectoryDialogReference.Result;
|
||||||
|
if (localDirectoryDialogResult is null || localDirectoryDialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var localDirectory = (DataSourceLocalDirectory)localDirectoryDialogResult.Data!;
|
||||||
|
localDirectory = localDirectory with { Num = this.SettingsManager.ConfigurationData.NextDataSourceNum++ };
|
||||||
|
addedDataSource = localDirectory;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataSourceType.ERI_V1:
|
||||||
|
var eriDialogParameters = new DialogParameters<DataSourceERI_V1Dialog>
|
||||||
|
{
|
||||||
|
{ x => x.IsEditing, false },
|
||||||
|
};
|
||||||
|
|
||||||
|
var eriDialogReference = await this.DialogService.ShowAsync<DataSourceERI_V1Dialog>("Add ERI v1 Data Source", eriDialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var eriDialogResult = await eriDialogReference.Result;
|
||||||
|
if (eriDialogResult is null || eriDialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var eriDataSource = (DataSourceERI_V1)eriDialogResult.Data!;
|
||||||
|
eriDataSource = eriDataSource with { Num = this.SettingsManager.ConfigurationData.NextDataSourceNum++ };
|
||||||
|
addedDataSource = eriDataSource;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(addedDataSource is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.SettingsManager.ConfigurationData.DataSources.Add(addedDataSource);
|
||||||
|
await this.UpdateDataSources();
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task EditDataSource(IDataSource dataSource)
|
||||||
|
{
|
||||||
|
IDataSource? editedDataSource = null;
|
||||||
|
switch (dataSource)
|
||||||
|
{
|
||||||
|
case DataSourceLocalFile localFile:
|
||||||
|
var localFileDialogParameters = new DialogParameters<DataSourceLocalFileDialog>
|
||||||
|
{
|
||||||
|
{ x => x.IsEditing, true },
|
||||||
|
{ x => x.DataSource, localFile },
|
||||||
|
{ x => x.AvailableEmbeddings, this.AvailableEmbeddingsFunc() }
|
||||||
|
};
|
||||||
|
|
||||||
|
var localFileDialogReference = await this.DialogService.ShowAsync<DataSourceLocalFileDialog>("Edit Local File Data Source", localFileDialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var localFileDialogResult = await localFileDialogReference.Result;
|
||||||
|
if (localFileDialogResult is null || localFileDialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
editedDataSource = (DataSourceLocalFile)localFileDialogResult.Data!;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataSourceLocalDirectory localDirectory:
|
||||||
|
var localDirectoryDialogParameters = new DialogParameters<DataSourceLocalDirectoryDialog>
|
||||||
|
{
|
||||||
|
{ x => x.IsEditing, true },
|
||||||
|
{ x => x.DataSource, localDirectory },
|
||||||
|
{ x => x.AvailableEmbeddings, this.AvailableEmbeddingsFunc() }
|
||||||
|
};
|
||||||
|
|
||||||
|
var localDirectoryDialogReference = await this.DialogService.ShowAsync<DataSourceLocalDirectoryDialog>("Edit Local Directory Data Source", localDirectoryDialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var localDirectoryDialogResult = await localDirectoryDialogReference.Result;
|
||||||
|
if (localDirectoryDialogResult is null || localDirectoryDialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
editedDataSource = (DataSourceLocalDirectory)localDirectoryDialogResult.Data!;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DataSourceERI_V1 eriDataSource:
|
||||||
|
var eriDialogParameters = new DialogParameters<DataSourceERI_V1Dialog>
|
||||||
|
{
|
||||||
|
{ x => x.IsEditing, true },
|
||||||
|
{ x => x.DataSource, eriDataSource },
|
||||||
|
};
|
||||||
|
|
||||||
|
var eriDialogReference = await this.DialogService.ShowAsync<DataSourceERI_V1Dialog>("Edit ERI v1 Data Source", eriDialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var eriDialogResult = await eriDialogReference.Result;
|
||||||
|
if (eriDialogResult is null || eriDialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
editedDataSource = (DataSourceERI_V1)eriDialogResult.Data!;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(editedDataSource is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.SettingsManager.ConfigurationData.DataSources[this.SettingsManager.ConfigurationData.DataSources.IndexOf(dataSource)] = editedDataSource;
|
||||||
|
|
||||||
|
await this.UpdateDataSources();
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteDataSource(IDataSource dataSource)
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters
|
||||||
|
{
|
||||||
|
{ "Message", $"Are you sure you want to delete the data source '{dataSource.Name}' of type {dataSource.Type.GetDisplayName()}?" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Data Source", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var applyChanges = dataSource is IInternalDataSource;
|
||||||
|
|
||||||
|
// External data sources may need a secret for authentication:
|
||||||
|
if (dataSource is IExternalDataSource externalDataSource)
|
||||||
|
{
|
||||||
|
// When the auth method is NONE or KERBEROS, we don't need to delete a secret.
|
||||||
|
// In the case of KERBEROS, we don't store the Kerberos ticket in the secret store.
|
||||||
|
if(dataSource is IERIDataSource { AuthMethod: AuthMethod.NONE or AuthMethod.KERBEROS })
|
||||||
|
applyChanges = true;
|
||||||
|
|
||||||
|
// All other auth methods require a secret, which we need to delete now:
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var deleteSecretResponse = await this.RustService.DeleteSecret(externalDataSource);
|
||||||
|
if (deleteSecretResponse.Success)
|
||||||
|
applyChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(applyChanges)
|
||||||
|
{
|
||||||
|
this.SettingsManager.ConfigurationData.DataSources.Remove(dataSource);
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
await this.UpdateDataSources();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task ShowInformation(IDataSource dataSource)
|
||||||
|
{
|
||||||
|
#warning Implement the information dialog for ERI data sources.
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateDataSources()
|
||||||
|
{
|
||||||
|
this.AvailableDataSources.Clear();
|
||||||
|
foreach (var dataSource in this.SettingsManager.ConfigurationData.DataSources)
|
||||||
|
this.AvailableDataSources.Add(new (dataSource.Name, dataSource.Id));
|
||||||
|
|
||||||
|
await this.AvailableDataSourcesChanged.InvokeAsync(this.AvailableDataSources);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.PrivateConnectivity" HeaderText="Assistant: ERI Server Options">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect ERI server options?" LabelOn="ERI server options are preselected" LabelOff="No ERI server options are preselected" State="@(() => this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.ERI.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect some ERI server options."/>
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.ERI.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.ERI.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.ERI.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.ERI.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
||||||
|
|
||||||
|
<MudText Typo="Typo.body1" Class="mb-3">
|
||||||
|
Most ERI server options can be customized and saved directly in the ERI server assistant.
|
||||||
|
For this, the ERI server assistant has an auto-save function.
|
||||||
|
</MudText>
|
||||||
|
|
||||||
|
<MudButton Size="Size.Large" Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.PrivateConnectivity" Color="Color.Default" Href="@Routes.ASSISTANT_ERI">
|
||||||
|
Switch to ERI server assistant
|
||||||
|
</MudButton>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelERIServer : SettingsPanelBase;
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
@using AIStudio.Provider
|
||||||
|
@using AIStudio.Settings.DataModel
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
|
||||||
|
{
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.IntegrationInstructions" HeaderText="Configure Embeddings">
|
||||||
|
<PreviewPrototype/>
|
||||||
|
<MudText Typo="Typo.h4" Class="mb-3">
|
||||||
|
Configured Embeddings
|
||||||
|
</MudText>
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
Embeddings are a way to represent words, sentences, entire documents, or even images and videos as digital
|
||||||
|
fingerprints. Just like each person has a unique fingerprint, embedding models create unique digital patterns
|
||||||
|
that capture the meaning and characteristics of the content they analyze. When two things are similar in meaning
|
||||||
|
or content, their digital fingerprints will look very similar. For example, the fingerprints for 'happy' and
|
||||||
|
'joyful' would be more alike than those for 'happy' and 'sad'.
|
||||||
|
</MudJustifiedText>
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
This helps AI Studio understand and compare things in a way that's similar to how humans do. When you're working on
|
||||||
|
something, AI Studio can automatically identify related documents and data by comparing their digital fingerprints.
|
||||||
|
For instance, if you're writing about customer service, AI Studio can instantly find other documents in your data that
|
||||||
|
discuss similar topics or experiences, even if they use different words.
|
||||||
|
</MudJustifiedText>
|
||||||
|
<MudTable Items="@this.SettingsManager.ConfigurationData.EmbeddingProviders" Hover="@true" Class="border-dashed border rounded-lg">
|
||||||
|
<ColGroup>
|
||||||
|
<col style="width: 3em;"/>
|
||||||
|
<col style="width: 12em;"/>
|
||||||
|
<col style="width: 12em;"/>
|
||||||
|
<col/>
|
||||||
|
<col style="width: 40em;"/>
|
||||||
|
</ColGroup>
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>#</MudTh>
|
||||||
|
<MudTh>Name</MudTh>
|
||||||
|
<MudTh>Provider</MudTh>
|
||||||
|
<MudTh>Model</MudTh>
|
||||||
|
<MudTh Style="text-align: left;">Actions</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd>@context.Num</MudTd>
|
||||||
|
<MudTd>@context.Name</MudTd>
|
||||||
|
<MudTd>@context.UsedLLMProvider</MudTd>
|
||||||
|
<MudTd>@this.GetEmbeddingProviderModelName(context)</MudTd>
|
||||||
|
|
||||||
|
<MudTd Style="text-align: left;">
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.OpenInBrowser" Class="ma-2" Href="@context.UsedLLMProvider.GetDashboardURL()" Target="_blank" Disabled="@(!context.UsedLLMProvider.HasDashboard())">
|
||||||
|
Open Dashboard
|
||||||
|
</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditEmbeddingProvider(context)">
|
||||||
|
Edit
|
||||||
|
</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteEmbeddingProvider(context)">
|
||||||
|
Delete
|
||||||
|
</MudButton>
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
|
||||||
|
@if (this.SettingsManager.ConfigurationData.EmbeddingProviders.Count == 0)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.h6" Class="mt-3">No embeddings configured yet.</MudText>
|
||||||
|
}
|
||||||
|
|
||||||
|
<MudButton Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddEmbeddingProvider">
|
||||||
|
Add Embedding
|
||||||
|
</MudButton>
|
||||||
|
</ExpansionPanel>
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
using AIStudio.Dialogs;
|
||||||
|
using AIStudio.Settings;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||||
|
|
||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelEmbeddings : SettingsPanelBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public List<ConfigurationSelectData<string>> AvailableEmbeddingProviders { get; set; } = new();
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<List<ConfigurationSelectData<string>>> AvailableEmbeddingProvidersChanged { get; set; }
|
||||||
|
|
||||||
|
private string GetEmbeddingProviderModelName(EmbeddingProvider provider)
|
||||||
|
{
|
||||||
|
const int MAX_LENGTH = 36;
|
||||||
|
var modelName = provider.Model.ToString();
|
||||||
|
return modelName.Length > MAX_LENGTH ? "[...] " + modelName[^Math.Min(MAX_LENGTH, modelName.Length)..] : modelName;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await this.UpdateEmbeddingProviders();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private async Task AddEmbeddingProvider()
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters<EmbeddingProviderDialog>
|
||||||
|
{
|
||||||
|
{ x => x.IsEditing, false },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<EmbeddingProviderDialog>("Add Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var addedEmbedding = (EmbeddingProvider)dialogResult.Data!;
|
||||||
|
addedEmbedding = addedEmbedding with { Num = this.SettingsManager.ConfigurationData.NextEmbeddingNum++ };
|
||||||
|
|
||||||
|
this.SettingsManager.ConfigurationData.EmbeddingProviders.Add(addedEmbedding);
|
||||||
|
await this.UpdateEmbeddingProviders();
|
||||||
|
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task EditEmbeddingProvider(EmbeddingProvider embeddingProvider)
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters<EmbeddingProviderDialog>
|
||||||
|
{
|
||||||
|
{ x => x.DataNum, embeddingProvider.Num },
|
||||||
|
{ x => x.DataId, embeddingProvider.Id },
|
||||||
|
{ x => x.DataName, embeddingProvider.Name },
|
||||||
|
{ x => x.DataLLMProvider, embeddingProvider.UsedLLMProvider },
|
||||||
|
{ x => x.DataModel, embeddingProvider.Model },
|
||||||
|
{ x => x.DataHostname, embeddingProvider.Hostname },
|
||||||
|
{ x => x.IsSelfHosted, embeddingProvider.IsSelfHosted },
|
||||||
|
{ x => x.IsEditing, true },
|
||||||
|
{ x => x.DataHost, embeddingProvider.Host },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<EmbeddingProviderDialog>("Edit Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var editedEmbeddingProvider = (EmbeddingProvider)dialogResult.Data!;
|
||||||
|
|
||||||
|
// Set the provider number if it's not set. This is important for providers
|
||||||
|
// added before we started saving the provider number.
|
||||||
|
if(editedEmbeddingProvider.Num == 0)
|
||||||
|
editedEmbeddingProvider = editedEmbeddingProvider with { Num = this.SettingsManager.ConfigurationData.NextEmbeddingNum++ };
|
||||||
|
|
||||||
|
this.SettingsManager.ConfigurationData.EmbeddingProviders[this.SettingsManager.ConfigurationData.EmbeddingProviders.IndexOf(embeddingProvider)] = editedEmbeddingProvider;
|
||||||
|
await this.UpdateEmbeddingProviders();
|
||||||
|
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteEmbeddingProvider(EmbeddingProvider provider)
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters
|
||||||
|
{
|
||||||
|
{ "Message", $"Are you sure you want to delete the embedding provider '{provider.Name}'?" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var deleteSecretResponse = await this.RustService.DeleteAPIKey(provider);
|
||||||
|
if(deleteSecretResponse.Success)
|
||||||
|
{
|
||||||
|
this.SettingsManager.ConfigurationData.EmbeddingProviders.Remove(provider);
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.UpdateEmbeddingProviders();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateEmbeddingProviders()
|
||||||
|
{
|
||||||
|
this.AvailableEmbeddingProviders.Clear();
|
||||||
|
foreach (var provider in this.SettingsManager.ConfigurationData.EmbeddingProviders)
|
||||||
|
this.AvailableEmbeddingProviders.Add(new (provider.Name, provider.Id));
|
||||||
|
|
||||||
|
await this.AvailableEmbeddingProvidersChanged.InvokeAsync(this.AvailableEmbeddingProviders);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Edit" HeaderText="Assistant: Grammar & Spelling Checker">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect grammar & spell checker options?" LabelOn="Grammar & spell checker options are preselected" LabelOff="No grammar & spell checker options are preselected" State="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the grammar & spell checker options. This is might be useful when you prefer a specific language or LLM model."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.GRAMMAR_SPELLING_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelGrammarSpelling : SettingsPanelBase;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.FindInPage" HeaderText="Assistant: Icon Finder Options">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect icon options?" LabelOn="Icon options are preselected" LabelOff="No icon options are preselected" State="@(() => this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the icon options. This is might be useful when you prefer a specific icon source or LLM model."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the icon source" Disabled="@(() => !this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource)" Data="@ConfigurationSelectDataFactory.GetIconSourcesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource = selectedValue)" OptionHelp="Which icon source should be preselected?"/>
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.IconFinder.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.IconFinder.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.ICON_FINDER_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelIconFinder : SettingsPanelBase;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Work" HeaderText="Assistant: Job Postings">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect job posting options?" LabelOn="Job posting options are preselected" LabelOff="No job posting options are preselected" State="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect some job posting options. This is might be useful when you prefer a specific LLM model."/>
|
||||||
|
<ConfigurationText OptionDescription="Preselect the company name?" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Warehouse" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedCompanyName)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedCompanyName = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect some mandatory information about the job posting?" NumLines="6" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.TextSnippet" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedMandatoryInformation)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedMandatoryInformation = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect the job description?" NumLines="3" MaxLines="6" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Settings" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedJobDescription)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedJobDescription = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect the job qualifications?" NumLines="3" MaxLines="6" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Settings" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedQualifications)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedQualifications = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect the job responsibilities?" NumLines="3" MaxLines="6" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Settings" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedResponsibilities)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedResponsibilities = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect the work location?" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.MyLocation" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedWorkLocation)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedWorkLocation = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect the country (legal framework)?" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Flag" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedCountryLegalFramework)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedCountryLegalFramework = updatedText)" />
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the language" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.JobPostings.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.JobPostings.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.JobPostings.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.JobPostings.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.JOB_POSTING_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.JobPostings.PreselectedProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelJobPostings : SettingsPanelBase;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Gavel" HeaderText="Assistant: Legal Check">
|
||||||
|
<ConfigurationOption OptionDescription="Hide the web content reader?" LabelOn="Web content reader is hidden" LabelOff="Web content reader is shown" State="@(() => this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader = updatedState)" OptionHelp="When activated, the web content reader is hidden and cannot be used. As a result, the user interface becomes a bit easier to use."/>
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect legal check options?" LabelOn="Legal check options are preselected" LabelOff="No legal check options are preselected" State="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect some legal check options. This is might be useful when you prefer a specific LLM model."/>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect the web content reader?" Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions || this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader)" LabelOn="Web content reader is preselected" LabelOff="Web content reader is not preselected" State="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LegalCheck.PreselectWebContentReader = updatedState)" OptionHelp="When enabled, the web content reader is preselected. This is might be useful when you prefer to load legal content from the web very often."/>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect the content cleaner agent?" Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions || this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader)" LabelOn="Content cleaner agent is preselected" LabelOff="Content cleaner agent is not preselected" State="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectContentCleanerAgent)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LegalCheck.PreselectContentCleanerAgent = updatedState)" OptionHelp="When enabled, the content cleaner agent is preselected. This is might be useful when you prefer to clean up the legal content before translating it."/>
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LegalCheck.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LegalCheck.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.LEGAL_CHECK_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LegalCheck.PreselectedProvider = selectedValue)"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LegalCheck.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelLegalCheck : SettingsPanelBase;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Task" HeaderText="Assistant: My Tasks">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect options?" LabelOn="Options are preselected" LabelOff="No options are preselected" State="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect options. This is might be useful when you prefer a specific language or LLM model."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the language" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another language" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.MyTasks.PreselectOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.MY_TASKS_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelMyTasks : SettingsPanelBase;
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Person4" HeaderText="Configure Profiles">
|
||||||
|
<MudText Typo="Typo.h4" Class="mb-3">Your Profiles</MudText>
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
Store personal data about yourself in various profiles so that the AIs know your personal context.
|
||||||
|
This saves you from having to explain your context each time, for example, in every chat. When you
|
||||||
|
have different roles, you can create a profile for each role.
|
||||||
|
</MudJustifiedText>
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
Are you a project manager in a research facility? You might want to create a profile for your project
|
||||||
|
management activities, one for your scientific work, and a profile for when you need to write program
|
||||||
|
code. In these profiles, you can record how much experience you have or which methods you like or
|
||||||
|
dislike using. Later, you can choose when and where you want to use each profile.
|
||||||
|
</MudJustifiedText>
|
||||||
|
<MudTable Items="@this.SettingsManager.ConfigurationData.Profiles" Hover="@true" Class="border-dashed border rounded-lg">
|
||||||
|
<ColGroup>
|
||||||
|
<col style="width: 3em;"/>
|
||||||
|
<col/>
|
||||||
|
<col style="width: 40em;"/>
|
||||||
|
</ColGroup>
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>#</MudTh>
|
||||||
|
<MudTh>Profile Name</MudTh>
|
||||||
|
<MudTh Style="text-align: left;">Actions</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd>@context.Num</MudTd>
|
||||||
|
<MudTd>@context.Name</MudTd>
|
||||||
|
<MudTd Style="text-align: left;">
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditProfile(context)">
|
||||||
|
Edit
|
||||||
|
</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteProfile(context)">
|
||||||
|
Delete
|
||||||
|
</MudButton>
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
|
||||||
|
@if(this.SettingsManager.ConfigurationData.Profiles.Count == 0)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.h6" Class="mt-3">No profiles configured yet.</MudText>
|
||||||
|
}
|
||||||
|
|
||||||
|
<MudButton Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddProfile">
|
||||||
|
Add Profile
|
||||||
|
</MudButton>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using AIStudio.Dialogs;
|
||||||
|
using AIStudio.Settings;
|
||||||
|
|
||||||
|
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||||
|
|
||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelProfiles : SettingsPanelBase
|
||||||
|
{
|
||||||
|
private async Task AddProfile()
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters<ProfileDialog>
|
||||||
|
{
|
||||||
|
{ x => x.IsEditing, false },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ProfileDialog>("Add Profile", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var addedProfile = (Profile)dialogResult.Data!;
|
||||||
|
addedProfile = addedProfile with { Num = this.SettingsManager.ConfigurationData.NextProfileNum++ };
|
||||||
|
|
||||||
|
this.SettingsManager.ConfigurationData.Profiles.Add(addedProfile);
|
||||||
|
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task EditProfile(Profile profile)
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters<ProfileDialog>
|
||||||
|
{
|
||||||
|
{ x => x.DataNum, profile.Num },
|
||||||
|
{ x => x.DataId, profile.Id },
|
||||||
|
{ x => x.DataName, profile.Name },
|
||||||
|
{ x => x.DataNeedToKnow, profile.NeedToKnow },
|
||||||
|
{ x => x.DataActions, profile.Actions },
|
||||||
|
{ x => x.IsEditing, true },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ProfileDialog>("Edit Profile", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var editedProfile = (Profile)dialogResult.Data!;
|
||||||
|
this.SettingsManager.ConfigurationData.Profiles[this.SettingsManager.ConfigurationData.Profiles.IndexOf(profile)] = editedProfile;
|
||||||
|
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteProfile(Profile profile)
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters
|
||||||
|
{
|
||||||
|
{ "Message", $"Are you sure you want to delete the profile '{profile.Name}'?" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Profile", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.SettingsManager.ConfigurationData.Profiles.Remove(profile);
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
@using AIStudio.Provider
|
||||||
|
@using AIStudio.Settings
|
||||||
|
@using AIStudio.Provider.SelfHosted
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Layers" HeaderText="Configure Providers">
|
||||||
|
<MudText Typo="Typo.h4" Class="mb-3">Configured Providers</MudText>
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
What we call a provider is the combination of an LLM provider such as OpenAI and a model like GPT-4o.
|
||||||
|
You can configure as many providers as you want. This way, you can use the appropriate model for each
|
||||||
|
task. As an LLM provider, you can also choose local providers. However, to use this app, you must
|
||||||
|
configure at least one provider.
|
||||||
|
</MudJustifiedText>
|
||||||
|
<MudTable Items="@this.SettingsManager.ConfigurationData.Providers" Hover="@true" Class="border-dashed border rounded-lg">
|
||||||
|
<ColGroup>
|
||||||
|
<col style="width: 3em;"/>
|
||||||
|
<col style="width: 12em;"/>
|
||||||
|
<col style="width: 12em;"/>
|
||||||
|
<col/>
|
||||||
|
<col style="width: 34em;"/>
|
||||||
|
</ColGroup>
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>#</MudTh>
|
||||||
|
<MudTh>Instance Name</MudTh>
|
||||||
|
<MudTh>Provider</MudTh>
|
||||||
|
<MudTh>Model</MudTh>
|
||||||
|
<MudTh Style="text-align: left;">Actions</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd>@context.Num</MudTd>
|
||||||
|
<MudTd>@context.InstanceName</MudTd>
|
||||||
|
<MudTd>@context.UsedLLMProvider</MudTd>
|
||||||
|
<MudTd>
|
||||||
|
@if (context.UsedLLMProvider is not LLMProviders.SELF_HOSTED)
|
||||||
|
{
|
||||||
|
@this.GetLLMProviderModelName(context)
|
||||||
|
}
|
||||||
|
else if (context.UsedLLMProvider is LLMProviders.SELF_HOSTED && context.Host is not Host.LLAMACPP)
|
||||||
|
{
|
||||||
|
@this.GetLLMProviderModelName(context)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@("as selected by provider")
|
||||||
|
}
|
||||||
|
</MudTd>
|
||||||
|
<MudTd Style="text-align: left;">
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.OpenInBrowser" Class="ma-2" Href="@context.UsedLLMProvider.GetDashboardURL()" Target="_blank" Disabled="@(!context.UsedLLMProvider.HasDashboard())">
|
||||||
|
Open Dashboard
|
||||||
|
</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditLLMProvider(context)">
|
||||||
|
Edit
|
||||||
|
</MudButton>
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteLLMProvider(context)">
|
||||||
|
Delete
|
||||||
|
</MudButton>
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
|
||||||
|
@if(this.SettingsManager.ConfigurationData.Providers.Count == 0)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.h6" Class="mt-3">No providers configured yet.</MudText>
|
||||||
|
}
|
||||||
|
|
||||||
|
<MudButton Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddLLMProvider">
|
||||||
|
Add Provider
|
||||||
|
</MudButton>
|
||||||
|
|
||||||
|
<MudText Typo="Typo.h4" Class="mb-3">LLM Provider Confidence</MudText>
|
||||||
|
<MudJustifiedText Class="mb-3">
|
||||||
|
Do you want to always be able to recognize how trustworthy your LLM providers are? This way,
|
||||||
|
you keep control over which provider you send your data to. You have two options for this:
|
||||||
|
Either you choose a common schema, or you configure the trust levels for each LLM provider yourself.
|
||||||
|
</MudJustifiedText>
|
||||||
|
|
||||||
|
<ConfigurationOption OptionDescription="Do you want to enforce an app-wide minimum confidence level?" LabelOn="Yes, enforce a minimum confidence level" LabelOff="No, do not enforce a minimum confidence level" State="@(() => this.SettingsManager.ConfigurationData.LLMProviders.EnforceGlobalMinimumConfidence)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LLMProviders.EnforceGlobalMinimumConfidence = updatedState)" OptionHelp="When enabled, you can enforce a minimum confidence level for all LLM providers. This way, you can ensure that only trustworthy providers are used."/>
|
||||||
|
@if(this.SettingsManager.ConfigurationData.LLMProviders.EnforceGlobalMinimumConfidence)
|
||||||
|
{
|
||||||
|
<ConfigurationMinConfidenceSelection RestrictToGlobalMinimumConfidence="@false" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LLMProviders.GlobalMinimumConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LLMProviders.GlobalMinimumConfidence = selectedValue)"/>
|
||||||
|
}
|
||||||
|
|
||||||
|
<ConfigurationOption OptionDescription="Show provider's confidence level?" LabelOn="Yes, show me the confidence level" LabelOff="No, please hide the confidence level" State="@(() => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence = updatedState)" OptionHelp="When enabled, we show you the confidence level for the selected provider in the app. This helps you assess where you are sending your data at any time. Example: are you currently working with sensitive data? Then choose a particularly trustworthy provider, etc."/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)
|
||||||
|
{
|
||||||
|
<ConfigurationSelect OptionDescription="Select a confidence scheme" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LLMProviders.ConfidenceScheme)" Data="@ConfigurationSelectDataFactory.GetConfidenceSchemesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LLMProviders.ConfidenceScheme = selectedValue)" OptionHelp="Choose the scheme that best suits you and your life. Do you trust any western provider? Or only providers from the USA or exclusively European providers? Then choose the appropriate scheme. Alternatively, you can assign the confidence levels to each provider yourself."/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.LLMProviders.ConfidenceScheme is ConfidenceSchemes.CUSTOM)
|
||||||
|
{
|
||||||
|
<MudTable Items="@(Enum.GetValues<LLMProviders>().Where(x => x is not LLMProviders.NONE))" Hover="@true" Class="border-dashed border rounded-lg">
|
||||||
|
<ColGroup>
|
||||||
|
<col style="width: 12em;"/>
|
||||||
|
<col/>
|
||||||
|
<col style="width: 22em;"/>
|
||||||
|
</ColGroup>
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>LLM Provider</MudTh>
|
||||||
|
<MudTh>Description</MudTh>
|
||||||
|
<MudTh>Confidence Level</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd Style="vertical-align: top;">
|
||||||
|
@context.ToName()
|
||||||
|
</MudTd>
|
||||||
|
<MudTd>
|
||||||
|
<MudMarkdown Value="@context.GetConfidence(this.SettingsManager).Description"/>
|
||||||
|
</MudTd>
|
||||||
|
<MudTd Style="vertical-align: top;">
|
||||||
|
<MudMenu StartIcon="@Icons.Material.Filled.Security" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="@this.GetCurrentConfidenceLevelName(context)" Variant="Variant.Filled" Style="@this.SetCurrentConfidenceLevelColorStyle(context)">
|
||||||
|
@foreach (var confidenceLevel in Enum.GetValues<ConfidenceLevel>().OrderBy(n => n))
|
||||||
|
{
|
||||||
|
if(confidenceLevel is ConfidenceLevel.NONE or ConfidenceLevel.UNKNOWN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
<MudMenuItem OnClick="@(async () => await this.ChangeCustomConfidenceLevel(context, confidenceLevel))">
|
||||||
|
@confidenceLevel.GetName()
|
||||||
|
</MudMenuItem>
|
||||||
|
}
|
||||||
|
</MudMenu>
|
||||||
|
</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
using AIStudio.Dialogs;
|
||||||
|
using AIStudio.Provider;
|
||||||
|
using AIStudio.Settings;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||||
|
|
||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelProviders : SettingsPanelBase
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public List<ConfigurationSelectData<string>> AvailableLLMProviders { get; set; } = new();
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<List<ConfigurationSelectData<string>>> AvailableLLMProvidersChanged { get; set; }
|
||||||
|
|
||||||
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await this.UpdateProviders();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private async Task AddLLMProvider()
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters<ProviderDialog>
|
||||||
|
{
|
||||||
|
{ x => x.IsEditing, false },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ProviderDialog>("Add LLM Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var addedProvider = (AIStudio.Settings.Provider)dialogResult.Data!;
|
||||||
|
addedProvider = addedProvider with { Num = this.SettingsManager.ConfigurationData.NextProviderNum++ };
|
||||||
|
|
||||||
|
this.SettingsManager.ConfigurationData.Providers.Add(addedProvider);
|
||||||
|
await this.UpdateProviders();
|
||||||
|
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task EditLLMProvider(AIStudio.Settings.Provider provider)
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters<ProviderDialog>
|
||||||
|
{
|
||||||
|
{ x => x.DataNum, provider.Num },
|
||||||
|
{ x => x.DataId, provider.Id },
|
||||||
|
{ x => x.DataInstanceName, provider.InstanceName },
|
||||||
|
{ x => x.DataLLMProvider, provider.UsedLLMProvider },
|
||||||
|
{ x => x.DataModel, provider.Model },
|
||||||
|
{ x => x.DataHostname, provider.Hostname },
|
||||||
|
{ x => x.IsSelfHosted, provider.IsSelfHosted },
|
||||||
|
{ x => x.IsEditing, true },
|
||||||
|
{ x => x.DataHost, provider.Host },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ProviderDialog>("Edit LLM Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var editedProvider = (AIStudio.Settings.Provider)dialogResult.Data!;
|
||||||
|
|
||||||
|
// Set the provider number if it's not set. This is important for providers
|
||||||
|
// added before we started saving the provider number.
|
||||||
|
if(editedProvider.Num == 0)
|
||||||
|
editedProvider = editedProvider with { Num = this.SettingsManager.ConfigurationData.NextProviderNum++ };
|
||||||
|
|
||||||
|
this.SettingsManager.ConfigurationData.Providers[this.SettingsManager.ConfigurationData.Providers.IndexOf(provider)] = editedProvider;
|
||||||
|
await this.UpdateProviders();
|
||||||
|
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteLLMProvider(AIStudio.Settings.Provider provider)
|
||||||
|
{
|
||||||
|
var dialogParameters = new DialogParameters
|
||||||
|
{
|
||||||
|
{ "Message", $"Are you sure you want to delete the provider '{provider.InstanceName}'?" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete LLM Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
||||||
|
var dialogResult = await dialogReference.Result;
|
||||||
|
if (dialogResult is null || dialogResult.Canceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var deleteSecretResponse = await this.RustService.DeleteAPIKey(provider);
|
||||||
|
if(deleteSecretResponse.Success)
|
||||||
|
{
|
||||||
|
this.SettingsManager.ConfigurationData.Providers.Remove(provider);
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.UpdateProviders();
|
||||||
|
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetLLMProviderModelName(AIStudio.Settings.Provider provider)
|
||||||
|
{
|
||||||
|
const int MAX_LENGTH = 36;
|
||||||
|
var modelName = provider.Model.ToString();
|
||||||
|
return modelName.Length > MAX_LENGTH ? "[...] " + modelName[^Math.Min(MAX_LENGTH, modelName.Length)..] : modelName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateProviders()
|
||||||
|
{
|
||||||
|
this.AvailableLLMProviders.Clear();
|
||||||
|
foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||||
|
this.AvailableLLMProviders.Add(new (provider.InstanceName, provider.Id));
|
||||||
|
|
||||||
|
await this.AvailableLLMProvidersChanged.InvokeAsync(this.AvailableLLMProviders);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetCurrentConfidenceLevelName(LLMProviders llmProvider)
|
||||||
|
{
|
||||||
|
if (this.SettingsManager.ConfigurationData.LLMProviders.CustomConfidenceScheme.TryGetValue(llmProvider, out var level))
|
||||||
|
return level.GetName();
|
||||||
|
|
||||||
|
return "Not yet configured";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SetCurrentConfidenceLevelColorStyle(LLMProviders llmProvider)
|
||||||
|
{
|
||||||
|
if (this.SettingsManager.ConfigurationData.LLMProviders.CustomConfidenceScheme.TryGetValue(llmProvider, out var level))
|
||||||
|
return $"background-color: {level.GetColor(this.SettingsManager)};";
|
||||||
|
|
||||||
|
return $"background-color: {ConfidenceLevel.UNKNOWN.GetColor(this.SettingsManager)};";
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ChangeCustomConfidenceLevel(LLMProviders llmProvider, ConfidenceLevel level)
|
||||||
|
{
|
||||||
|
this.SettingsManager.ConfigurationData.LLMProviders.CustomConfidenceScheme[llmProvider] = level;
|
||||||
|
await this.SettingsManager.StoreSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Edit" HeaderText="Assistant: Rewrite & Improve Text">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect rewrite & improve text options?" LabelOn="Rewrite & improve text options are preselected" LabelOff="No rewrite & improve text options are preselected" State="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the rewrite & improve text options. This is might be useful when you prefer a specific language or LLM model."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect a writing style" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle)" Data="@ConfigurationSelectDataFactory.GetWritingStyles4RewriteData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle = selectedValue)" OptionHelp="Which writing style should be preselected?"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect a sentence structure" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedSentenceStructure)" Data="@ConfigurationSelectDataFactory.GetSentenceStructureData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedSentenceStructure = selectedValue)" OptionHelp="Which voice should be preselected for the sentence structure?"/>
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.REWRITE_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelRewrite : SettingsPanelBase;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Spellcheck" HeaderText="Assistant: Synonyms">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect synonym options?" LabelOn="Synonym options are preselected" LabelOff="No synonym options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect synonym options. This is might be useful when you prefer a specific language or LLM model."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Synonyms.PreselectedLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Synonyms.PreselectedLanguage = selectedValue)" OptionHelp="Which language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.Synonyms.PreselectedLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Synonyms.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Synonyms.PreselectedOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Synonyms.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Synonyms.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.SYNONYMS_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Synonyms.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Synonyms.PreselectedProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelSynonyms : SettingsPanelBase;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
@using AIStudio.Assistants.TextSummarizer
|
||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TextSnippet" HeaderText="Assistant: Text Summarizer Options">
|
||||||
|
<ConfigurationOption OptionDescription="Hide the web content reader?" LabelOn="Web content reader is hidden" LabelOff="Web content reader is shown" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader = updatedState)" OptionHelp="When activated, the web content reader is hidden and cannot be used. As a result, the user interface becomes a bit easier to use."/>
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect summarizer options?" LabelOn="Summarizer options are preselected" LabelOff="No summarizer options are preselected" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the text summarizer options. This is might be useful when you prefer a specific language, complexity, or LLM."/>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect the web content reader?" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions || this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)" LabelOn="Web content reader is preselected" LabelOff="Web content reader is not preselected" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectWebContentReader = updatedState)" OptionHelp="When enabled, the web content reader is preselected. This is might be useful when you prefer to load content from the web very often."/>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect the content cleaner agent?" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions || this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)" LabelOn="Content cleaner agent is preselected" LabelOff="Content cleaner agent is not preselected" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectContentCleanerAgent)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectContentCleanerAgent = updatedState)" OptionHelp="When enabled, the content cleaner agent is preselected. This is might be useful when you prefer to clean up the content before summarize it."/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the summarizer complexity" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity)" Data="@ConfigurationSelectDataFactory.GetComplexityData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity = selectedValue)" OptionHelp="Which summarizer complexity should be preselected?"/>
|
||||||
|
@if(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity is Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect your expertise" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" Icon="@Icons.Material.Filled.Person" Text="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedExpertInField)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedExpertInField = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.TEXT_SUMMARIZER_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelTextSummarizer : SettingsPanelBase;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Translate" HeaderText="Assistant: Translator Options">
|
||||||
|
<ConfigurationSlider T="int" OptionDescription="How fast should the live translation react?" Min="500" Max="3_000" Step="100" Unit="milliseconds" Value="@(() => this.SettingsManager.ConfigurationData.Translation.DebounceIntervalMilliseconds)" ValueUpdate="@(updatedValue => this.SettingsManager.ConfigurationData.Translation.DebounceIntervalMilliseconds = updatedValue)"/>
|
||||||
|
<ConfigurationOption OptionDescription="Hide the web content reader?" LabelOn="Web content reader is hidden" LabelOff="Web content reader is shown" State="@(() => this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.HideWebContentReader = updatedState)" OptionHelp="When activated, the web content reader is hidden and cannot be used. As a result, the user interface becomes a bit easier to use."/>
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect translator options?" LabelOn="Translator options are preselected" LabelOff="No translator options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the translator options. This is might be useful when you prefer a specific target language or LLM model."/>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect the web content reader?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions || this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)" LabelOn="Web content reader is preselected" LabelOff="Web content reader is not preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectWebContentReader = updatedState)" OptionHelp="When enabled, the web content reader is preselected. This is might be useful when you prefer to load content from the web very often."/>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect the content cleaner agent?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions || this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)" LabelOn="Content cleaner agent is preselected" LabelOff="Content cleaner agent is not preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectContentCleanerAgent)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectContentCleanerAgent = updatedState)" OptionHelp="When enabled, the content cleaner agent is preselected. This is might be useful when you prefer to clean up the content before translating it."/>
|
||||||
|
<ConfigurationOption OptionDescription="Preselect live translation?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" LabelOn="Live translation is preselected" LabelOff="Live translation is not preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectLiveTranslation)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectLiveTranslation = updatedState)" />
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.TRANSLATION_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.PreselectedProvider = selectedValue)"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelTranslation : SettingsPanelBase;
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@using AIStudio.Settings.DataModel
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Work" HeaderText="Workspace Options">
|
||||||
|
<ConfigurationSelect OptionDescription="Workspace behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Workspace.StorageBehavior)" Data="@ConfigurationSelectDataFactory.GetWorkspaceStorageBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Workspace.StorageBehavior = selectedValue)" OptionHelp="Should we store your chats?"/>
|
||||||
|
|
||||||
|
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES)
|
||||||
|
{
|
||||||
|
<ConfigurationSelect OptionDescription="Workspace maintenance" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy)" Data="@ConfigurationSelectDataFactory.GetWorkspaceStorageTemporaryMaintenancePolicyData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy = selectedValue)" OptionHelp="If and when should we delete your temporary chats?"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Workspace display behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior)" Data="@ConfigurationSelectDataFactory.GetWorkspaceDisplayBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior = selectedValue)" OptionHelp="How should we display your workspaces?"/>
|
||||||
|
}
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelWorkspaces : SettingsPanelBase;
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
@using AIStudio.Settings
|
||||||
|
@inherits SettingsPanelBase
|
||||||
|
|
||||||
|
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Email" HeaderText="Assistant: Writing E-Mails">
|
||||||
|
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||||
|
<ConfigurationOption OptionDescription="Preselect e-mail options?" LabelOn="E-Mail options are preselected" LabelOff="No e-mail options are preselected" State="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.EMail.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the e-mail options. This is might be useful when you prefer a specific language or LLM model."/>
|
||||||
|
<ConfigurationText OptionDescription="Preselect a greeting?" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" Icon="@Icons.Material.Filled.Person" Text="@(() => this.SettingsManager.ConfigurationData.EMail.Greeting)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.EMail.Greeting = updatedText)" />
|
||||||
|
<ConfigurationText OptionDescription="Preselect your name for the closing salutation?" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" Icon="@Icons.Material.Filled.Person" Text="@(() => this.SettingsManager.ConfigurationData.EMail.SenderName)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.EMail.SenderName = updatedText)" />
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||||
|
@if (this.SettingsManager.ConfigurationData.EMail.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||||
|
{
|
||||||
|
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.EMail.PreselectOtherLanguage = updatedText)"/>
|
||||||
|
}
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect a writing style" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectedWritingStyle)" Data="@ConfigurationSelectDataFactory.GetWritingStyles4EMailData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.PreselectedWritingStyle = selectedValue)" OptionHelp="Which writing style should be preselected?"/>
|
||||||
|
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.MinimumProviderConfidence = selectedValue)"/>
|
||||||
|
<ConfigurationProviderSelection Component="Components.EMAIL_ASSISTANT" Data="@this.AvailableLLMProvidersFunc()" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.PreselectedProvider = selectedValue)"/>
|
||||||
|
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
||||||
|
</MudPaper>
|
||||||
|
</ExpansionPanel>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace AIStudio.Components.Settings;
|
||||||
|
|
||||||
|
public partial class SettingsPanelWritingEMails : SettingsPanelBase;
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
@using ERI_Client.V1
|
||||||
|
<MudDialog>
|
||||||
|
<DialogContent>
|
||||||
|
<MudForm @ref="@this.form" @bind-IsValid="@this.dataIsValid" @bind-Errors="@this.dataIssues">
|
||||||
|
@* ReSharper disable once CSharpWarnings::CS8974 *@
|
||||||
|
<MudTextField
|
||||||
|
T="string"
|
||||||
|
@bind-Text="@this.dataName"
|
||||||
|
Label="Data Source Name"
|
||||||
|
Class="mb-6"
|
||||||
|
MaxLength="40"
|
||||||
|
Counter="40"
|
||||||
|
Immediate="@true"
|
||||||
|
Validation="@this.dataSourceValidation.ValidatingName"
|
||||||
|
Adornment="Adornment.Start"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Lightbulb"
|
||||||
|
AdornmentColor="Color.Info"
|
||||||
|
UserAttributes="@SPELLCHECK_ATTRIBUTES"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MudStack Row="@true">
|
||||||
|
@* ReSharper disable once CSharpWarnings::CS8974 *@
|
||||||
|
<MudTextField
|
||||||
|
T="string"
|
||||||
|
@bind-Text="@this.dataHostname"
|
||||||
|
Label="ERI v1 Server Hostname"
|
||||||
|
Class="mb-6"
|
||||||
|
Immediate="@true"
|
||||||
|
Validation="@this.dataSourceValidation.ValidatingHostname"
|
||||||
|
Adornment="Adornment.Start"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.NetworkCheck"
|
||||||
|
AdornmentColor="Color.Info"
|
||||||
|
Variant="Variant.Text"
|
||||||
|
UserAttributes="@SPELLCHECK_ATTRIBUTES"/>
|
||||||
|
|
||||||
|
<MudNumericField
|
||||||
|
Label="Port"
|
||||||
|
Immediate="@true"
|
||||||
|
Min="1" Max="65535"
|
||||||
|
Validation="@this.dataSourceValidation.ValidatePort"
|
||||||
|
@bind-Value="@this.dataPort"
|
||||||
|
Variant="Variant.Text"
|
||||||
|
Margin="Margin.Dense"/>
|
||||||
|
</MudStack>
|
||||||
|
|
||||||
|
@if (!this.IsConnectionEncrypted())
|
||||||
|
{
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Color="Color.Error" Class="mb-3">
|
||||||
|
Please note: the connection to the ERI v1 server is not encrypted. This means that all
|
||||||
|
data sent to the server is transmitted in plain text. Please ask the ERI server administrator
|
||||||
|
to enable encryption.
|
||||||
|
</MudJustifiedText>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (this.IsConnectionPossible())
|
||||||
|
{
|
||||||
|
<MudStack Row="@true" AlignItems="AlignItems.Center">
|
||||||
|
<MudButton Variant="Variant.Filled" Color="@this.GetTestResultColor()" StartIcon="@this.GetTestResultIcon()" Class="mb-3" OnClick="@this.TestConnection">
|
||||||
|
Test connection & read available metadata
|
||||||
|
</MudButton>
|
||||||
|
<MudText Typo="Typo.body1" Class="mb-3">
|
||||||
|
@this.GetTestResultText()
|
||||||
|
</MudText>
|
||||||
|
</MudStack>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if(this.availableAuthMethods.Count > 0 || this.dataAuthMethod != default)
|
||||||
|
{
|
||||||
|
<MudSelect @bind-Value="@this.dataAuthMethod" Text="@this.dataAuthMethod.DisplayName()" Label="Authentication Method" Class="mb-3" OpenIcon="@Icons.Material.Filled.ExpandMore" AdornmentColor="Color.Info" Adornment="Adornment.Start" Validation="@this.dataSourceValidation.ValidateAuthMethod">
|
||||||
|
@foreach (var authMethod in this.availableAuthMethods)
|
||||||
|
{
|
||||||
|
<MudSelectItem Value="@authMethod">@authMethod.DisplayName()</MudSelectItem>
|
||||||
|
}
|
||||||
|
</MudSelect>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (this.NeedsSecret())
|
||||||
|
{
|
||||||
|
if (this.dataAuthMethod is AuthMethod.USERNAME_PASSWORD)
|
||||||
|
{
|
||||||
|
@* ReSharper disable once CSharpWarnings::CS8974 *@
|
||||||
|
<MudTextField
|
||||||
|
T="string"
|
||||||
|
@bind-Text="@this.dataUsername"
|
||||||
|
Label="Username"
|
||||||
|
Class="mb-6"
|
||||||
|
Immediate="@true"
|
||||||
|
Validation="@this.dataSourceValidation.ValidateUsername"
|
||||||
|
Adornment="Adornment.Start"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Person2"
|
||||||
|
AdornmentColor="Color.Info"
|
||||||
|
Variant="Variant.Text"
|
||||||
|
UserAttributes="@SPELLCHECK_ATTRIBUTES"/>
|
||||||
|
}
|
||||||
|
|
||||||
|
@* ReSharper disable once CSharpWarnings::CS8974 *@
|
||||||
|
<MudTextField
|
||||||
|
T="string"
|
||||||
|
@bind-Text="@this.dataSecret"
|
||||||
|
Label="@this.GetSecretLabel()"
|
||||||
|
Class="mb-6"
|
||||||
|
Immediate="@true"
|
||||||
|
Validation="@this.dataSourceValidation.ValidatingSecret"
|
||||||
|
Adornment="Adornment.Start"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Security"
|
||||||
|
AdornmentColor="Color.Info"
|
||||||
|
Variant="Variant.Text"
|
||||||
|
InputType="InputType.Password"
|
||||||
|
UserAttributes="@SPELLCHECK_ATTRIBUTES"/>
|
||||||
|
}
|
||||||
|
|
||||||
|
</MudForm>
|
||||||
|
<Issues IssuesData="@this.dataIssues"/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton OnClick="@this.Cancel" Variant="Variant.Filled">Cancel</MudButton>
|
||||||
|
<MudButton OnClick="@this.Store" Variant="Variant.Filled" Color="Color.Primary">
|
||||||
|
@if(this.IsEditing)
|
||||||
|
{
|
||||||
|
@:Update
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@:Add
|
||||||
|
}
|
||||||
|
</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
using AIStudio.Settings;
|
||||||
|
using AIStudio.Settings.DataModel;
|
||||||
|
using AIStudio.Tools.Validation;
|
||||||
|
|
||||||
|
using ERI_Client.V1;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
namespace AIStudio.Dialogs;
|
||||||
|
|
||||||
|
public partial class DataSourceERI_V1Dialog : ComponentBase, ISecretId
|
||||||
|
{
|
||||||
|
[CascadingParameter]
|
||||||
|
private MudDialogInstance MudDialog { get; set; } = null!;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool IsEditing { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public DataSourceERI_V1 DataSource { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private SettingsManager SettingsManager { get; init; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private ILogger<ProviderDialog> Logger { get; init; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private RustService RustService { get; init; } = null!;
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, object?> SPELLCHECK_ATTRIBUTES = new();
|
||||||
|
|
||||||
|
private readonly DataSourceValidation dataSourceValidation;
|
||||||
|
private readonly Encryption encryption = Program.ENCRYPTION;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of used data source names. We need this to check for uniqueness.
|
||||||
|
/// </summary>
|
||||||
|
private List<string> UsedDataSourcesNames { get; set; } = [];
|
||||||
|
|
||||||
|
private bool dataIsValid;
|
||||||
|
private string[] dataIssues = [];
|
||||||
|
private string dataSecretStorageIssue = string.Empty;
|
||||||
|
private string dataEditingPreviousInstanceName = string.Empty;
|
||||||
|
private HttpClient? httpClient;
|
||||||
|
private List<AuthMethod> availableAuthMethods = [];
|
||||||
|
private bool connectionTested;
|
||||||
|
private bool connectionSuccessfulTested;
|
||||||
|
|
||||||
|
private uint dataNum;
|
||||||
|
private string dataSecret = string.Empty;
|
||||||
|
private string dataId = Guid.NewGuid().ToString();
|
||||||
|
private string dataName = string.Empty;
|
||||||
|
private string dataHostname = string.Empty;
|
||||||
|
private int dataPort;
|
||||||
|
private AuthMethod dataAuthMethod;
|
||||||
|
private string dataUsername = string.Empty;
|
||||||
|
|
||||||
|
// We get the form reference from Blazor code to validate it manually:
|
||||||
|
private MudForm form = null!;
|
||||||
|
|
||||||
|
public DataSourceERI_V1Dialog()
|
||||||
|
{
|
||||||
|
this.dataSourceValidation = new()
|
||||||
|
{
|
||||||
|
GetAuthMethod = () => this.dataAuthMethod,
|
||||||
|
GetPreviousDataSourceName = () => this.dataEditingPreviousInstanceName,
|
||||||
|
GetUsedDataSourceNames = () => this.UsedDataSourcesNames,
|
||||||
|
GetSecretStorageIssue = () => this.dataSecretStorageIssue,
|
||||||
|
GetTestedConnection = () => this.connectionTested,
|
||||||
|
GetTestedConnectionResult = () => this.connectionSuccessfulTested,
|
||||||
|
GetAvailableAuthMethods = () => this.availableAuthMethods,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
// Configure the spellchecking for the instance name input:
|
||||||
|
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
|
||||||
|
|
||||||
|
// Load the used instance names:
|
||||||
|
this.UsedDataSourcesNames = this.SettingsManager.ConfigurationData.DataSources.Select(x => x.Name.ToLowerInvariant()).ToList();
|
||||||
|
|
||||||
|
// When editing, we need to load the data:
|
||||||
|
if(this.IsEditing)
|
||||||
|
{
|
||||||
|
this.dataEditingPreviousInstanceName = this.DataSource.Name.ToLowerInvariant();
|
||||||
|
this.dataNum = this.DataSource.Num;
|
||||||
|
this.dataId = this.DataSource.Id;
|
||||||
|
this.dataName = this.DataSource.Name;
|
||||||
|
this.dataHostname = this.DataSource.Hostname;
|
||||||
|
this.dataPort = this.DataSource.Port;
|
||||||
|
this.dataAuthMethod = this.DataSource.AuthMethod;
|
||||||
|
this.dataUsername = this.DataSource.Username;
|
||||||
|
|
||||||
|
if (this.dataAuthMethod is AuthMethod.TOKEN or AuthMethod.USERNAME_PASSWORD)
|
||||||
|
{
|
||||||
|
// Load the secret:
|
||||||
|
var requestedSecret = await this.RustService.GetSecret(this);
|
||||||
|
if (requestedSecret.Success)
|
||||||
|
this.dataSecret = await requestedSecret.Secret.Decrypt(this.encryption);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.dataSecret = string.Empty;
|
||||||
|
this.dataSecretStorageIssue = $"Failed to load the auth. secret from the operating system. The message was: {requestedSecret.Issue}. You might ignore this message and provide the secret again.";
|
||||||
|
await this.form.Validate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
// Reset the validation when not editing and on the first render.
|
||||||
|
// We don't want to show validation errors when the user opens the dialog.
|
||||||
|
if(!this.IsEditing && firstRender)
|
||||||
|
this.form.ResetValidation();
|
||||||
|
|
||||||
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Implementation of ISecretId
|
||||||
|
|
||||||
|
public string SecretId => this.dataId;
|
||||||
|
|
||||||
|
public string SecretName => this.dataName;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private DataSourceERI_V1 CreateDataSource()
|
||||||
|
{
|
||||||
|
var cleanedHostname = this.dataHostname.Trim();
|
||||||
|
return new DataSourceERI_V1
|
||||||
|
{
|
||||||
|
Id = this.dataId,
|
||||||
|
Num = this.dataNum,
|
||||||
|
Port = this.dataPort,
|
||||||
|
Name = this.dataName,
|
||||||
|
Hostname = cleanedHostname.EndsWith('/') ? cleanedHostname[..^1] : cleanedHostname,
|
||||||
|
AuthMethod = this.dataAuthMethod,
|
||||||
|
Username = this.dataUsername,
|
||||||
|
Type = DataSourceType.ERI_V1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsConnectionEncrypted() => this.dataHostname.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
|
||||||
|
private bool IsConnectionPossible()
|
||||||
|
{
|
||||||
|
if(this.dataSourceValidation.ValidatingHostname(this.dataHostname) is not null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(this.dataSourceValidation.ValidatePort(this.dataPort) is not null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task TestConnection()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.httpClient = new HttpClient
|
||||||
|
{
|
||||||
|
BaseAddress = new Uri($"{this.dataHostname}:{this.dataPort}"),
|
||||||
|
Timeout = TimeSpan.FromSeconds(5),
|
||||||
|
};
|
||||||
|
|
||||||
|
using (this.httpClient)
|
||||||
|
{
|
||||||
|
var client = new Client(this.httpClient);
|
||||||
|
var authSchemes = await client.GetAuthMethodsAsync();
|
||||||
|
if (authSchemes is null)
|
||||||
|
{
|
||||||
|
await this.form.Validate();
|
||||||
|
|
||||||
|
Array.Resize(ref this.dataIssues, this.dataIssues.Length + 1);
|
||||||
|
this.dataIssues[^1] = "Failed to connect to the ERI v1 server. The server did not respond.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.availableAuthMethods = authSchemes.Select(n => n.AuthMethod).ToList();
|
||||||
|
|
||||||
|
this.connectionTested = true;
|
||||||
|
this.connectionSuccessfulTested = true;
|
||||||
|
this.Logger.LogInformation("Connection to the ERI v1 server was successful tested.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await this.form.Validate();
|
||||||
|
|
||||||
|
Array.Resize(ref this.dataIssues, this.dataIssues.Length + 1);
|
||||||
|
this.dataIssues[^1] = $"Failed to connect to the ERI v1 server. The message was: {e.Message}";
|
||||||
|
this.Logger.LogError($"Failed to connect to the ERI v1 server. Message: {e.Message}");
|
||||||
|
|
||||||
|
this.connectionTested = true;
|
||||||
|
this.connectionSuccessfulTested = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetTestResultText()
|
||||||
|
{
|
||||||
|
if(!this.connectionTested)
|
||||||
|
return "Not tested yet.";
|
||||||
|
|
||||||
|
return this.connectionSuccessfulTested ? "Connection successful." : "Connection failed.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color GetTestResultColor()
|
||||||
|
{
|
||||||
|
if (!this.connectionTested)
|
||||||
|
return Color.Default;
|
||||||
|
|
||||||
|
return this.connectionSuccessfulTested ? Color.Success : Color.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetTestResultIcon()
|
||||||
|
{
|
||||||
|
if (!this.connectionTested)
|
||||||
|
return Icons.Material.Outlined.HourglassEmpty;
|
||||||
|
|
||||||
|
return this.connectionSuccessfulTested ? Icons.Material.Outlined.CheckCircle : Icons.Material.Outlined.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool NeedsSecret() => this.dataAuthMethod is AuthMethod.TOKEN or AuthMethod.USERNAME_PASSWORD;
|
||||||
|
|
||||||
|
private string GetSecretLabel() => this.dataAuthMethod switch
|
||||||
|
{
|
||||||
|
AuthMethod.TOKEN => "Access Token",
|
||||||
|
AuthMethod.USERNAME_PASSWORD => "Password",
|
||||||
|
_ => "Secret",
|
||||||
|
};
|
||||||
|
|
||||||
|
private async Task Store()
|
||||||
|
{
|
||||||
|
await this.form.Validate();
|
||||||
|
|
||||||
|
var testConnectionValidation = this.dataSourceValidation.ValidateTestedConnection();
|
||||||
|
if(testConnectionValidation is not null)
|
||||||
|
{
|
||||||
|
Array.Resize(ref this.dataIssues, this.dataIssues.Length + 1);
|
||||||
|
this.dataIssues[^1] = testConnectionValidation;
|
||||||
|
this.dataIsValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dataSecretStorageIssue = string.Empty;
|
||||||
|
|
||||||
|
// When the data is not valid, we don't store it:
|
||||||
|
if (!this.dataIsValid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var addedDataSource = this.CreateDataSource();
|
||||||
|
if (!string.IsNullOrWhiteSpace(this.dataSecret))
|
||||||
|
{
|
||||||
|
// Store the secret in the OS secure storage:
|
||||||
|
var storeResponse = await this.RustService.SetSecret(this, this.dataSecret);
|
||||||
|
if (!storeResponse.Success)
|
||||||
|
{
|
||||||
|
this.dataSecretStorageIssue = $"Failed to store the auth. secret in the operating system. The message was: {storeResponse.Issue}. Please try again.";
|
||||||
|
await this.form.Validate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.MudDialog.Close(DialogResult.Ok(addedDataSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cancel() => this.MudDialog.Cancel();
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<MudDialog>
|
||||||
|
<DialogContent>
|
||||||
|
<MudForm @ref="@this.form" @bind-IsValid="@this.dataIsValid" @bind-Errors="@this.dataIssues">
|
||||||
|
@* ReSharper disable once CSharpWarnings::CS8974 *@
|
||||||
|
<MudTextField
|
||||||
|
T="string"
|
||||||
|
@bind-Text="@this.dataName"
|
||||||
|
Label="Data Source Name"
|
||||||
|
Class="mb-6"
|
||||||
|
MaxLength="40"
|
||||||
|
Counter="40"
|
||||||
|
Immediate="@true"
|
||||||
|
Validation="@this.dataSourceValidation.ValidatingName"
|
||||||
|
Adornment="Adornment.Start"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Lightbulb"
|
||||||
|
AdornmentColor="Color.Info"
|
||||||
|
UserAttributes="@SPELLCHECK_ATTRIBUTES"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
Select a root directory for this data source. All data in this directory and all
|
||||||
|
its subdirectories will be processed for this data source.
|
||||||
|
</MudJustifiedText>
|
||||||
|
<SelectDirectory @bind-Directory="@this.dataPath" Label="Selected base directory for this data source" DirectoryDialogTitle="Select the base directory" Validation="@this.dataSourceValidation.ValidatePath" />
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
In order for the AI to be able to determine the appropriate data at any time, you must
|
||||||
|
choose an embedding method.
|
||||||
|
</MudJustifiedText>
|
||||||
|
<MudSelect @bind-Value="@this.dataEmbeddingId" Label="Embedding" Class="mb-3" OpenIcon="@Icons.Material.Filled.ExpandMore" AdornmentColor="Color.Info" Adornment="Adornment.Start" Validation="@this.dataSourceValidation.ValidateEmbeddingId">
|
||||||
|
@foreach (var embedding in this.AvailableEmbeddings)
|
||||||
|
{
|
||||||
|
<MudSelectItem Value="@embedding.Value">@embedding.Name</MudSelectItem>
|
||||||
|
}
|
||||||
|
</MudSelect>
|
||||||
|
|
||||||
|
@if (!string.IsNullOrWhiteSpace(this.dataEmbeddingId))
|
||||||
|
{
|
||||||
|
if (this.SelectedCloudEmbedding)
|
||||||
|
{
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Color="Color.Error" Class="mb-3">
|
||||||
|
@if (string.IsNullOrWhiteSpace(this.dataPath))
|
||||||
|
{
|
||||||
|
@: Please note: the embedding you selected runs in the cloud. All your data will be sent to the cloud.
|
||||||
|
@: Please confirm that you have read and understood this.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@: Please note: the embedding you selected runs in the cloud. All your data from the
|
||||||
|
@: folder '@this.dataPath' and all its subdirectories will be sent to the cloud. Please
|
||||||
|
@: confirm that you have read and understood this.
|
||||||
|
}
|
||||||
|
</MudJustifiedText>
|
||||||
|
<MudTextSwitch @bind-Value="@this.dataUserAcknowledgedCloudEmbedding" Label="I confirm that I have read and understood the above" LabelOn="Yes, please send my data to the cloud" LabelOff="No, I will chose another embedding" Validation="@this.dataSourceValidation.ValidateUserAcknowledgedCloudEmbedding"/>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Color="Color.Tertiary" Class="mb-3">
|
||||||
|
The embedding you selected runs locally or in your organization. Your data is not sent to the cloud.
|
||||||
|
</MudJustifiedText>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</MudForm>
|
||||||
|
<Issues IssuesData="@this.dataIssues"/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton OnClick="@this.Cancel" Variant="Variant.Filled">Cancel</MudButton>
|
||||||
|
<MudButton OnClick="@this.Store" Variant="Variant.Filled" Color="Color.Primary">
|
||||||
|
@if(this.IsEditing)
|
||||||
|
{
|
||||||
|
@:Update
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@:Add
|
||||||
|
}
|
||||||
|
</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
using AIStudio.Settings;
|
||||||
|
using AIStudio.Settings.DataModel;
|
||||||
|
using AIStudio.Tools.Validation;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Dialogs;
|
||||||
|
|
||||||
|
public partial class DataSourceLocalDirectoryDialog : ComponentBase
|
||||||
|
{
|
||||||
|
[CascadingParameter]
|
||||||
|
private MudDialogInstance MudDialog { get; set; } = null!;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool IsEditing { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public DataSourceLocalDirectory DataSource { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public IReadOnlyList<ConfigurationSelectData<string>> AvailableEmbeddings { get; set; } = [];
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private SettingsManager SettingsManager { get; init; } = null!;
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, object?> SPELLCHECK_ATTRIBUTES = new();
|
||||||
|
|
||||||
|
private readonly DataSourceValidation dataSourceValidation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of used data source names. We need this to check for uniqueness.
|
||||||
|
/// </summary>
|
||||||
|
private List<string> UsedDataSourcesNames { get; set; } = [];
|
||||||
|
|
||||||
|
private bool dataIsValid;
|
||||||
|
private string[] dataIssues = [];
|
||||||
|
private string dataEditingPreviousInstanceName = string.Empty;
|
||||||
|
|
||||||
|
private uint dataNum;
|
||||||
|
private string dataId = Guid.NewGuid().ToString();
|
||||||
|
private string dataName = string.Empty;
|
||||||
|
private bool dataUserAcknowledgedCloudEmbedding;
|
||||||
|
private string dataEmbeddingId = string.Empty;
|
||||||
|
private string dataPath = string.Empty;
|
||||||
|
|
||||||
|
// We get the form reference from Blazor code to validate it manually:
|
||||||
|
private MudForm form = null!;
|
||||||
|
|
||||||
|
public DataSourceLocalDirectoryDialog()
|
||||||
|
{
|
||||||
|
this.dataSourceValidation = new()
|
||||||
|
{
|
||||||
|
GetSelectedCloudEmbedding = () => this.SelectedCloudEmbedding,
|
||||||
|
GetPreviousDataSourceName = () => this.dataEditingPreviousInstanceName,
|
||||||
|
GetUsedDataSourceNames = () => this.UsedDataSourcesNames,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
// Configure the spellchecking for the instance name input:
|
||||||
|
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
|
||||||
|
|
||||||
|
// Load the used instance names:
|
||||||
|
this.UsedDataSourcesNames = this.SettingsManager.ConfigurationData.DataSources.Select(x => x.Name.ToLowerInvariant()).ToList();
|
||||||
|
|
||||||
|
// When editing, we need to load the data:
|
||||||
|
if(this.IsEditing)
|
||||||
|
{
|
||||||
|
this.dataEditingPreviousInstanceName = this.DataSource.Name.ToLowerInvariant();
|
||||||
|
this.dataNum = this.DataSource.Num;
|
||||||
|
this.dataId = this.DataSource.Id;
|
||||||
|
this.dataName = this.DataSource.Name;
|
||||||
|
this.dataEmbeddingId = this.DataSource.EmbeddingId;
|
||||||
|
this.dataPath = this.DataSource.Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
// Reset the validation when not editing and on the first render.
|
||||||
|
// We don't want to show validation errors when the user opens the dialog.
|
||||||
|
if(!this.IsEditing && firstRender)
|
||||||
|
this.form.ResetValidation();
|
||||||
|
|
||||||
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private bool SelectedCloudEmbedding => !this.SettingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(x => x.Id == this.dataEmbeddingId).IsSelfHosted;
|
||||||
|
|
||||||
|
private DataSourceLocalDirectory CreateDataSource() => new()
|
||||||
|
{
|
||||||
|
Id = this.dataId,
|
||||||
|
Num = this.dataNum,
|
||||||
|
Name = this.dataName,
|
||||||
|
Type = DataSourceType.LOCAL_DIRECTORY,
|
||||||
|
EmbeddingId = this.dataEmbeddingId,
|
||||||
|
Path = this.dataPath,
|
||||||
|
};
|
||||||
|
|
||||||
|
private async Task Store()
|
||||||
|
{
|
||||||
|
await this.form.Validate();
|
||||||
|
|
||||||
|
// When the data is not valid, we don't store it:
|
||||||
|
if (!this.dataIsValid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var addedDataSource = this.CreateDataSource();
|
||||||
|
this.MudDialog.Close(DialogResult.Ok(addedDataSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cancel() => this.MudDialog.Cancel();
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<MudDialog>
|
||||||
|
<DialogContent>
|
||||||
|
<MudForm @ref="@this.form" @bind-IsValid="@this.dataIsValid" @bind-Errors="@this.dataIssues">
|
||||||
|
@* ReSharper disable once CSharpWarnings::CS8974 *@
|
||||||
|
<MudTextField
|
||||||
|
T="string"
|
||||||
|
@bind-Text="@this.dataName"
|
||||||
|
Label="Data Source Name"
|
||||||
|
Class="mb-6"
|
||||||
|
MaxLength="40"
|
||||||
|
Counter="40"
|
||||||
|
Immediate="@true"
|
||||||
|
Validation="@this.dataSourceValidation.ValidatingName"
|
||||||
|
Adornment="Adornment.Start"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Lightbulb"
|
||||||
|
AdornmentColor="Color.Info"
|
||||||
|
UserAttributes="@SPELLCHECK_ATTRIBUTES"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
Select a file for this data source. The content of this file will be processed for the data source.
|
||||||
|
</MudJustifiedText>
|
||||||
|
<SelectFile @bind-File="@this.dataFilePath" Label="Selected file path for this data source" FileDialogTitle="Select the file" Validation="@this.dataSourceValidation.ValidateFilePath" />
|
||||||
|
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
||||||
|
In order for the AI to be able to determine the appropriate data at any time, you must
|
||||||
|
choose an embedding method.
|
||||||
|
</MudJustifiedText>
|
||||||
|
<MudSelect @bind-Value="@this.dataEmbeddingId" Label="Embedding" Class="mb-3" OpenIcon="@Icons.Material.Filled.ExpandMore" AdornmentColor="Color.Info" Adornment="Adornment.Start" Validation="@this.dataSourceValidation.GetSelectedCloudEmbedding">
|
||||||
|
@foreach (var embedding in this.AvailableEmbeddings)
|
||||||
|
{
|
||||||
|
<MudSelectItem Value="@embedding.Value">@embedding.Name</MudSelectItem>
|
||||||
|
}
|
||||||
|
</MudSelect>
|
||||||
|
|
||||||
|
@if (!string.IsNullOrWhiteSpace(this.dataEmbeddingId))
|
||||||
|
{
|
||||||
|
if (this.SelectedCloudEmbedding)
|
||||||
|
{
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Color="Color.Error" Class="mb-3">
|
||||||
|
@if (string.IsNullOrWhiteSpace(this.dataFilePath))
|
||||||
|
{
|
||||||
|
@: Please note: the embedding you selected runs in the cloud. All your data will be sent to the cloud.
|
||||||
|
@: Please confirm that you have read and understood this.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@: Please note: the embedding you selected runs in the cloud. All your data within the
|
||||||
|
@: file '@this.dataFilePath' will be sent to the cloud. Please confirm that you have read
|
||||||
|
@: and understood this.
|
||||||
|
}
|
||||||
|
</MudJustifiedText>
|
||||||
|
<MudTextSwitch @bind-Value="@this.dataUserAcknowledgedCloudEmbedding" Label="I confirm that I have read and understood the above" LabelOn="Yes, please send my data to the cloud" LabelOff="No, I will chose another embedding" Validation="@this.dataSourceValidation.ValidateUserAcknowledgedCloudEmbedding"/>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MudJustifiedText Typo="Typo.body1" Color="Color.Tertiary" Class="mb-3">
|
||||||
|
The embedding you selected runs locally or in your organization. Your data is not sent to the cloud.
|
||||||
|
</MudJustifiedText>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</MudForm>
|
||||||
|
<Issues IssuesData="@this.dataIssues"/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton OnClick="@this.Cancel" Variant="Variant.Filled">Cancel</MudButton>
|
||||||
|
<MudButton OnClick="@this.Store" Variant="Variant.Filled" Color="Color.Primary">
|
||||||
|
@if(this.IsEditing)
|
||||||
|
{
|
||||||
|
@:Update
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@:Add
|
||||||
|
}
|
||||||
|
</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
using AIStudio.Settings;
|
||||||
|
using AIStudio.Settings.DataModel;
|
||||||
|
using AIStudio.Tools.Validation;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
|
namespace AIStudio.Dialogs;
|
||||||
|
|
||||||
|
public partial class DataSourceLocalFileDialog : ComponentBase
|
||||||
|
{
|
||||||
|
[CascadingParameter]
|
||||||
|
private MudDialogInstance MudDialog { get; set; } = null!;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool IsEditing { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public DataSourceLocalFile DataSource { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public IReadOnlyList<ConfigurationSelectData<string>> AvailableEmbeddings { get; set; } = [];
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private SettingsManager SettingsManager { get; init; } = null!;
|
||||||
|
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, object?> SPELLCHECK_ATTRIBUTES = new();
|
||||||
|
|
||||||
|
private readonly DataSourceValidation dataSourceValidation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of used data source names. We need this to check for uniqueness.
|
||||||
|
/// </summary>
|
||||||
|
private List<string> UsedDataSourcesNames { get; set; } = [];
|
||||||
|
|
||||||
|
private bool dataIsValid;
|
||||||
|
private string[] dataIssues = [];
|
||||||
|
private string dataEditingPreviousInstanceName = string.Empty;
|
||||||
|
|
||||||
|
private uint dataNum;
|
||||||
|
private string dataId = Guid.NewGuid().ToString();
|
||||||
|
private string dataName = string.Empty;
|
||||||
|
private bool dataUserAcknowledgedCloudEmbedding;
|
||||||
|
private string dataEmbeddingId = string.Empty;
|
||||||
|
private string dataFilePath = string.Empty;
|
||||||
|
|
||||||
|
// We get the form reference from Blazor code to validate it manually:
|
||||||
|
private MudForm form = null!;
|
||||||
|
|
||||||
|
public DataSourceLocalFileDialog()
|
||||||
|
{
|
||||||
|
this.dataSourceValidation = new()
|
||||||
|
{
|
||||||
|
GetSelectedCloudEmbedding = () => this.SelectedCloudEmbedding,
|
||||||
|
GetPreviousDataSourceName = () => this.dataEditingPreviousInstanceName,
|
||||||
|
GetUsedDataSourceNames = () => this.UsedDataSourcesNames,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
// Configure the spellchecking for the instance name input:
|
||||||
|
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
|
||||||
|
|
||||||
|
// Load the used instance names:
|
||||||
|
this.UsedDataSourcesNames = this.SettingsManager.ConfigurationData.DataSources.Select(x => x.Name.ToLowerInvariant()).ToList();
|
||||||
|
|
||||||
|
// When editing, we need to load the data:
|
||||||
|
if(this.IsEditing)
|
||||||
|
{
|
||||||
|
this.dataEditingPreviousInstanceName = this.DataSource.Name.ToLowerInvariant();
|
||||||
|
this.dataNum = this.DataSource.Num;
|
||||||
|
this.dataId = this.DataSource.Id;
|
||||||
|
this.dataName = this.DataSource.Name;
|
||||||
|
this.dataEmbeddingId = this.DataSource.EmbeddingId;
|
||||||
|
this.dataFilePath = this.DataSource.FilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
// Reset the validation when not editing and on the first render.
|
||||||
|
// We don't want to show validation errors when the user opens the dialog.
|
||||||
|
if(!this.IsEditing && firstRender)
|
||||||
|
this.form.ResetValidation();
|
||||||
|
|
||||||
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private bool SelectedCloudEmbedding => !this.SettingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(x => x.Id == this.dataEmbeddingId).IsSelfHosted;
|
||||||
|
|
||||||
|
private DataSourceLocalFile CreateDataSource() => new()
|
||||||
|
{
|
||||||
|
Id = this.dataId,
|
||||||
|
Num = this.dataNum,
|
||||||
|
Name = this.dataName,
|
||||||
|
Type = DataSourceType.LOCAL_FILE,
|
||||||
|
EmbeddingId = this.dataEmbeddingId,
|
||||||
|
FilePath = this.dataFilePath,
|
||||||
|
};
|
||||||
|
|
||||||
|
private async Task Store()
|
||||||
|
{
|
||||||
|
await this.form.Validate();
|
||||||
|
|
||||||
|
// When the data is not valid, we don't store it:
|
||||||
|
if (!this.dataIsValid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var addedDataSource = this.CreateDataSource();
|
||||||
|
this.MudDialog.Close(DialogResult.Ok(addedDataSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cancel() => this.MudDialog.Cancel();
|
||||||
|
}
|
||||||
@@ -112,13 +112,24 @@ public partial class EmbeddingProviderDialog : ComponentBase, ISecretId
|
|||||||
private EmbeddingProvider CreateEmbeddingProviderSettings()
|
private EmbeddingProvider CreateEmbeddingProviderSettings()
|
||||||
{
|
{
|
||||||
var cleanedHostname = this.DataHostname.Trim();
|
var cleanedHostname = this.DataHostname.Trim();
|
||||||
|
Model model = default;
|
||||||
|
if(this.DataLLMProvider is LLMProviders.SELF_HOSTED)
|
||||||
|
{
|
||||||
|
if (this.DataHost is Host.OLLAMA)
|
||||||
|
model = new Model(this.dataManuallyModel, null);
|
||||||
|
else if (this.DataHost is Host.LM_STUDIO)
|
||||||
|
model = this.DataModel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
model = this.DataModel;
|
||||||
|
|
||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
Num = this.DataNum,
|
Num = this.DataNum,
|
||||||
Id = this.DataId,
|
Id = this.DataId,
|
||||||
Name = this.DataName,
|
Name = this.DataName,
|
||||||
UsedLLMProvider = this.DataLLMProvider,
|
UsedLLMProvider = this.DataLLMProvider,
|
||||||
Model = this.DataLLMProvider is LLMProviders.SELF_HOSTED ? new Model(this.dataManuallyModel, null) : this.DataModel,
|
Model = model,
|
||||||
IsSelfHosted = this.DataLLMProvider is LLMProviders.SELF_HOSTED,
|
IsSelfHosted = this.DataLLMProvider is LLMProviders.SELF_HOSTED,
|
||||||
Hostname = cleanedHostname.EndsWith('/') ? cleanedHostname[..^1] : cleanedHostname,
|
Hostname = cleanedHostname.EndsWith('/') ? cleanedHostname[..^1] : cleanedHostname,
|
||||||
Host = this.DataHost,
|
Host = this.DataHost,
|
||||||
@@ -197,8 +208,7 @@ public partial class EmbeddingProviderDialog : ComponentBase, ISecretId
|
|||||||
private async Task Store()
|
private async Task Store()
|
||||||
{
|
{
|
||||||
await this.form.Validate();
|
await this.form.Validate();
|
||||||
if (!string.IsNullOrWhiteSpace(this.dataAPIKeyStorageIssue))
|
this.dataAPIKeyStorageIssue = string.Empty;
|
||||||
this.dataAPIKeyStorageIssue = string.Empty;
|
|
||||||
|
|
||||||
// When the data is not valid, we don't store it:
|
// When the data is not valid, we don't store it:
|
||||||
if (!this.dataIsValid)
|
if (!this.dataIsValid)
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public partial class ProviderDialog : ComponentBase, ISecretId
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Settings.Provider CreateProviderSettings()
|
private AIStudio.Settings.Provider CreateProviderSettings()
|
||||||
{
|
{
|
||||||
var cleanedHostname = this.DataHostname.Trim();
|
var cleanedHostname = this.DataHostname.Trim();
|
||||||
return new()
|
return new()
|
||||||
|
|||||||
@@ -53,6 +53,10 @@
|
|||||||
<PackageReference Include="ReverseMarkdown" Version="4.6.0" />
|
<PackageReference Include="ReverseMarkdown" Version="4.6.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ERIClientV1\ERIClientV1.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Read the meta data file -->
|
<!-- Read the meta data file -->
|
||||||
<Target Name="ReadMetaData" BeforeTargets="BeforeBuild">
|
<Target Name="ReadMetaData" BeforeTargets="BeforeBuild">
|
||||||
<Error Text="The ../../metadata.txt file was not found!" Condition="!Exists('../../metadata.txt')" />
|
<Error Text="The ../../metadata.txt file was not found!" Condition="!Exists('../../metadata.txt')" />
|
||||||
|
|||||||
@@ -1,545 +1,31 @@
|
|||||||
@attribute [Route(Routes.SETTINGS)]
|
@attribute [Route(Routes.SETTINGS)]
|
||||||
@using AIStudio.Assistants.Coding
|
@using AIStudio.Components.Settings
|
||||||
@using AIStudio.Assistants.TextSummarizer
|
|
||||||
@using AIStudio.Provider
|
|
||||||
@using AIStudio.Settings
|
|
||||||
@using AIStudio.Settings.DataModel
|
|
||||||
@using Host = AIStudio.Provider.SelfHosted.Host
|
|
||||||
|
|
||||||
<MudText Typo="Typo.h3" Class="mb-12">Settings</MudText>
|
<MudText Typo="Typo.h3" Class="mb-12">Settings</MudText>
|
||||||
|
|
||||||
<InnerScrolling HeaderHeight="10em">
|
<InnerScrolling HeaderHeight="10em">
|
||||||
<MudExpansionPanels Class="mb-3" MultiExpansion="@false">
|
<MudExpansionPanels Class="mb-3" MultiExpansion="@false">
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Layers" HeaderText="Configure Providers">
|
<SettingsPanelProviders @bind-AvailableLLMProviders="@this.availableLLMProviders" />
|
||||||
<MudText Typo="Typo.h4" Class="mb-3">Configured Providers</MudText>
|
<SettingsPanelEmbeddings AvailableLLMProvidersFunc="() => this.availableLLMProviders" @bind-AvailableEmbeddingProviders="@this.availableEmbeddingProviders" />
|
||||||
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
<SettingsPanelDataSources AvailableLLMProvidersFunc="() => this.availableLLMProviders" AvailableEmbeddingsFunc="() => this.availableEmbeddingProviders" @bind-AvailableDataSources="@this.availableDataSources" />
|
||||||
What we call a provider is the combination of an LLM provider such as OpenAI and a model like GPT-4o.
|
<SettingsPanelProfiles AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
You can configure as many providers as you want. This way, you can use the appropriate model for each
|
<SettingsPanelApp AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
task. As an LLM provider, you can also choose local providers. However, to use this app, you must
|
<SettingsPanelChat AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
configure at least one provider.
|
<SettingsPanelWorkspaces AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
</MudJustifiedText>
|
<SettingsPanelIconFinder AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<MudTable Items="@this.SettingsManager.ConfigurationData.Providers" Hover="@true" Class="border-dashed border rounded-lg">
|
<SettingsPanelTranslation AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<ColGroup>
|
<SettingsPanelCoding AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<col style="width: 3em;"/>
|
<SettingsPanelERIServer AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<col style="width: 12em;"/>
|
<SettingsPanelTextSummarizer AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<col style="width: 12em;"/>
|
<SettingsPanelAgenda AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<col/>
|
<SettingsPanelGrammarSpelling AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<col style="width: 34em;"/>
|
<SettingsPanelRewrite AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
</ColGroup>
|
<SettingsPanelWritingEMails AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<HeaderContent>
|
<SettingsPanelJobPostings AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<MudTh>#</MudTh>
|
<SettingsPanelLegalCheck AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<MudTh>Instance Name</MudTh>
|
<SettingsPanelSynonyms AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<MudTh>Provider</MudTh>
|
<SettingsPanelMyTasks AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<MudTh>Model</MudTh>
|
<SettingsPanelAssistantBias AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
<MudTh Style="text-align: left;">Actions</MudTh>
|
<SettingsPanelAgentContentCleaner AvailableLLMProvidersFunc="() => this.availableLLMProviders" />
|
||||||
</HeaderContent>
|
|
||||||
<RowTemplate>
|
|
||||||
<MudTd>@context.Num</MudTd>
|
|
||||||
<MudTd>@context.InstanceName</MudTd>
|
|
||||||
<MudTd>@context.UsedLLMProvider</MudTd>
|
|
||||||
<MudTd>
|
|
||||||
@if (context.UsedLLMProvider is not LLMProviders.SELF_HOSTED)
|
|
||||||
{
|
|
||||||
@this.GetLLMProviderModelName(context)
|
|
||||||
}
|
|
||||||
else if (context.UsedLLMProvider is LLMProviders.SELF_HOSTED && context.Host is not Host.LLAMACPP)
|
|
||||||
{
|
|
||||||
@this.GetLLMProviderModelName(context)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@("as selected by provider")
|
|
||||||
}
|
|
||||||
</MudTd>
|
|
||||||
<MudTd Style="text-align: left;">
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.OpenInBrowser" Class="ma-2" Href="@context.UsedLLMProvider.GetDashboardURL()" Target="_blank" Disabled="@(!context.UsedLLMProvider.HasDashboard())">
|
|
||||||
Open Dashboard
|
|
||||||
</MudButton>
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditLLMProvider(context)">
|
|
||||||
Edit
|
|
||||||
</MudButton>
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteLLMProvider(context)">
|
|
||||||
Delete
|
|
||||||
</MudButton>
|
|
||||||
</MudTd>
|
|
||||||
</RowTemplate>
|
|
||||||
</MudTable>
|
|
||||||
|
|
||||||
@if(this.SettingsManager.ConfigurationData.Providers.Count == 0)
|
|
||||||
{
|
|
||||||
<MudText Typo="Typo.h6" Class="mt-3">No providers configured yet.</MudText>
|
|
||||||
}
|
|
||||||
|
|
||||||
<MudButton Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddLLMProvider">
|
|
||||||
Add Provider
|
|
||||||
</MudButton>
|
|
||||||
|
|
||||||
<MudText Typo="Typo.h4" Class="mb-3">LLM Provider Confidence</MudText>
|
|
||||||
<MudJustifiedText Class="mb-3">
|
|
||||||
Do you want to always be able to recognize how trustworthy your LLM providers are? This way,
|
|
||||||
you keep control over which provider you send your data to. You have two options for this:
|
|
||||||
Either you choose a common schema, or you configure the trust levels for each LLM provider yourself.
|
|
||||||
</MudJustifiedText>
|
|
||||||
|
|
||||||
<ConfigurationOption OptionDescription="Do you want to enforce an app-wide minimum confidence level?" LabelOn="Yes, enforce a minimum confidence level" LabelOff="No, do not enforce a minimum confidence level" State="@(() => this.SettingsManager.ConfigurationData.LLMProviders.EnforceGlobalMinimumConfidence)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LLMProviders.EnforceGlobalMinimumConfidence = updatedState)" OptionHelp="When enabled, you can enforce a minimum confidence level for all LLM providers. This way, you can ensure that only trustworthy providers are used."/>
|
|
||||||
@if(this.SettingsManager.ConfigurationData.LLMProviders.EnforceGlobalMinimumConfidence)
|
|
||||||
{
|
|
||||||
<ConfigurationMinConfidenceSelection RestrictToGlobalMinimumConfidence="@false" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LLMProviders.GlobalMinimumConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LLMProviders.GlobalMinimumConfidence = selectedValue)"/>
|
|
||||||
}
|
|
||||||
|
|
||||||
<ConfigurationOption OptionDescription="Show provider's confidence level?" LabelOn="Yes, show me the confidence level" LabelOff="No, please hide the confidence level" State="@(() => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence = updatedState)" OptionHelp="When enabled, we show you the confidence level for the selected provider in the app. This helps you assess where you are sending your data at any time. Example: are you currently working with sensitive data? Then choose a particularly trustworthy provider, etc."/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)
|
|
||||||
{
|
|
||||||
<ConfigurationSelect OptionDescription="Select a confidence scheme" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LLMProviders.ConfidenceScheme)" Data="@ConfigurationSelectDataFactory.GetConfidenceSchemesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LLMProviders.ConfidenceScheme = selectedValue)" OptionHelp="Choose the scheme that best suits you and your life. Do you trust any western provider? Or only providers from the USA or exclusively European providers? Then choose the appropriate scheme. Alternatively, you can assign the confidence levels to each provider yourself."/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.LLMProviders.ConfidenceScheme is ConfidenceSchemes.CUSTOM)
|
|
||||||
{
|
|
||||||
<MudTable Items="@(Enum.GetValues<LLMProviders>().Where(x => x is not LLMProviders.NONE))" Hover="@true" Class="border-dashed border rounded-lg">
|
|
||||||
<ColGroup>
|
|
||||||
<col style="width: 12em;"/>
|
|
||||||
<col/>
|
|
||||||
<col style="width: 22em;"/>
|
|
||||||
</ColGroup>
|
|
||||||
<HeaderContent>
|
|
||||||
<MudTh>LLM Provider</MudTh>
|
|
||||||
<MudTh>Description</MudTh>
|
|
||||||
<MudTh>Confidence Level</MudTh>
|
|
||||||
</HeaderContent>
|
|
||||||
<RowTemplate>
|
|
||||||
<MudTd Style="vertical-align: top;">
|
|
||||||
@context.ToName()
|
|
||||||
</MudTd>
|
|
||||||
<MudTd>
|
|
||||||
<MudMarkdown Value="@context.GetConfidence(this.SettingsManager).Description"/>
|
|
||||||
</MudTd>
|
|
||||||
<MudTd Style="vertical-align: top;">
|
|
||||||
<MudMenu StartIcon="@Icons.Material.Filled.Security" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="@this.GetCurrentConfidenceLevelName(context)" Variant="Variant.Filled" Style="@this.SetCurrentConfidenceLevelColorStyle(context)">
|
|
||||||
@foreach (var confidenceLevel in Enum.GetValues<ConfidenceLevel>().OrderBy(n => n))
|
|
||||||
{
|
|
||||||
if(confidenceLevel is ConfidenceLevel.NONE or ConfidenceLevel.UNKNOWN)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
<MudMenuItem OnClick="@(async () => await this.ChangeCustomConfidenceLevel(context, confidenceLevel))">
|
|
||||||
@confidenceLevel.GetName()
|
|
||||||
</MudMenuItem>
|
|
||||||
}
|
|
||||||
</MudMenu>
|
|
||||||
</MudTd>
|
|
||||||
</RowTemplate>
|
|
||||||
</MudTable>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
|
|
||||||
{
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.IntegrationInstructions" HeaderText="Configure Embeddings">
|
|
||||||
<PreviewPrototype/>
|
|
||||||
<MudText Typo="Typo.h4" Class="mb-3">
|
|
||||||
Configured Embeddings
|
|
||||||
</MudText>
|
|
||||||
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
|
||||||
Embeddings are a way to represent words, sentences, entire documents, or even images and videos as digital
|
|
||||||
fingerprints. Just like each person has a unique fingerprint, embedding models create unique digital patterns
|
|
||||||
that capture the meaning and characteristics of the content they analyze. When two things are similar in meaning
|
|
||||||
or content, their digital fingerprints will look very similar. For example, the fingerprints for 'happy' and
|
|
||||||
'joyful' would be more alike than those for 'happy' and 'sad'.
|
|
||||||
</MudJustifiedText>
|
|
||||||
|
|
||||||
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
|
||||||
This helps AI Studio understand and compare things in a way that's similar to how humans do. When you're working on
|
|
||||||
something, AI Studio can automatically identify related documents and data by comparing their digital fingerprints.
|
|
||||||
For instance, if you're writing about customer service, AI Studio can instantly find other documents in your data that
|
|
||||||
discuss similar topics or experiences, even if they use different words.
|
|
||||||
</MudJustifiedText>
|
|
||||||
<MudTable Items="@this.SettingsManager.ConfigurationData.EmbeddingProviders" Hover="@true" Class="border-dashed border rounded-lg">
|
|
||||||
<ColGroup>
|
|
||||||
<col style="width: 3em;"/>
|
|
||||||
<col style="width: 12em;"/>
|
|
||||||
<col style="width: 12em;"/>
|
|
||||||
<col/>
|
|
||||||
<col style="width: 40em;"/>
|
|
||||||
</ColGroup>
|
|
||||||
<HeaderContent>
|
|
||||||
<MudTh>#</MudTh>
|
|
||||||
<MudTh>Name</MudTh>
|
|
||||||
<MudTh>Provider</MudTh>
|
|
||||||
<MudTh>Model</MudTh>
|
|
||||||
<MudTh Style="text-align: left;">Actions</MudTh>
|
|
||||||
</HeaderContent>
|
|
||||||
<RowTemplate>
|
|
||||||
<MudTd>@context.Num</MudTd>
|
|
||||||
<MudTd>@context.Name</MudTd>
|
|
||||||
<MudTd>@context.UsedLLMProvider</MudTd>
|
|
||||||
<MudTd>@this.GetEmbeddingProviderModelName(context)</MudTd>
|
|
||||||
|
|
||||||
<MudTd Style="text-align: left;">
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.OpenInBrowser" Class="ma-2" Href="@context.UsedLLMProvider.GetDashboardURL()" Target="_blank" Disabled="@(!context.UsedLLMProvider.HasDashboard())">
|
|
||||||
Open Dashboard
|
|
||||||
</MudButton>
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditEmbeddingProvider(context)">
|
|
||||||
Edit
|
|
||||||
</MudButton>
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteEmbeddingProvider(context)">
|
|
||||||
Delete
|
|
||||||
</MudButton>
|
|
||||||
</MudTd>
|
|
||||||
</RowTemplate>
|
|
||||||
</MudTable>
|
|
||||||
|
|
||||||
@if (this.SettingsManager.ConfigurationData.EmbeddingProviders.Count == 0)
|
|
||||||
{
|
|
||||||
<MudText Typo="Typo.h6" Class="mt-3">No embeddings configured yet.</MudText>
|
|
||||||
}
|
|
||||||
|
|
||||||
<MudButton Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddEmbeddingProvider">
|
|
||||||
Add Embedding
|
|
||||||
</MudButton>
|
|
||||||
</ExpansionPanel>
|
|
||||||
}
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Person4" HeaderText="Configure Profiles">
|
|
||||||
<MudText Typo="Typo.h4" Class="mb-3">Your Profiles</MudText>
|
|
||||||
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
|
||||||
Store personal data about yourself in various profiles so that the AIs know your personal context.
|
|
||||||
This saves you from having to explain your context each time, for example, in every chat. When you
|
|
||||||
have different roles, you can create a profile for each role.
|
|
||||||
</MudJustifiedText>
|
|
||||||
|
|
||||||
<MudJustifiedText Typo="Typo.body1" Class="mb-3">
|
|
||||||
Are you a project manager in a research facility? You might want to create a profile for your project
|
|
||||||
management activities, one for your scientific work, and a profile for when you need to write program
|
|
||||||
code. In these profiles, you can record how much experience you have or which methods you like or
|
|
||||||
dislike using. Later, you can choose when and where you want to use each profile.
|
|
||||||
</MudJustifiedText>
|
|
||||||
<MudTable Items="@this.SettingsManager.ConfigurationData.Profiles" Hover="@true" Class="border-dashed border rounded-lg">
|
|
||||||
<ColGroup>
|
|
||||||
<col style="width: 3em;"/>
|
|
||||||
<col/>
|
|
||||||
<col style="width: 40em;"/>
|
|
||||||
</ColGroup>
|
|
||||||
<HeaderContent>
|
|
||||||
<MudTh>#</MudTh>
|
|
||||||
<MudTh>Profile Name</MudTh>
|
|
||||||
<MudTh Style="text-align: left;">Actions</MudTh>
|
|
||||||
</HeaderContent>
|
|
||||||
<RowTemplate>
|
|
||||||
<MudTd>@context.Num</MudTd>
|
|
||||||
<MudTd>@context.Name</MudTd>
|
|
||||||
<MudTd Style="text-align: left;">
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditProfile(context)">
|
|
||||||
Edit
|
|
||||||
</MudButton>
|
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteProfile(context)">
|
|
||||||
Delete
|
|
||||||
</MudButton>
|
|
||||||
</MudTd>
|
|
||||||
</RowTemplate>
|
|
||||||
</MudTable>
|
|
||||||
|
|
||||||
@if(this.SettingsManager.ConfigurationData.Profiles.Count == 0)
|
|
||||||
{
|
|
||||||
<MudText Typo="Typo.h6" Class="mt-3">No profiles configured yet.</MudText>
|
|
||||||
}
|
|
||||||
|
|
||||||
<MudButton Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddProfile">
|
|
||||||
Add Profile
|
|
||||||
</MudButton>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Apps" HeaderText="App Options">
|
|
||||||
<ConfigurationSelect OptionDescription="Color theme" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreferredTheme)" Data="@ConfigurationSelectDataFactory.GetThemesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreferredTheme = selectedValue)" OptionHelp="Choose the color theme that best suits for you."/>
|
|
||||||
<ConfigurationOption OptionDescription="Save energy?" LabelOn="Energy saving is enabled" LabelOff="Energy saving is disabled" State="@(() => this.SettingsManager.ConfigurationData.App.IsSavingEnergy)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.App.IsSavingEnergy = updatedState)" OptionHelp="When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available."/>
|
|
||||||
<ConfigurationOption OptionDescription="Enable spellchecking?" LabelOn="Spellchecking is enabled" LabelOff="Spellchecking is disabled" State="@(() => this.SettingsManager.ConfigurationData.App.EnableSpellchecking)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.App.EnableSpellchecking = updatedState)" OptionHelp="When enabled, spellchecking will be active in all input fields. Depending on your operating system, errors may not be visually highlighted, but right-clicking may still offer possible corrections." />
|
|
||||||
<ConfigurationSelect OptionDescription="Check for updates" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UpdateBehavior)" Data="@ConfigurationSelectDataFactory.GetUpdateBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UpdateBehavior = selectedValue)" OptionHelp="How often should we check for app updates?"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Navigation bar behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.NavigationBehavior)" Data="@ConfigurationSelectDataFactory.GetNavBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.NavigationBehavior = selectedValue)" OptionHelp="Select the desired behavior for the navigation bar."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preview feature visibility" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreviewVisibility)" Data="@ConfigurationSelectDataFactory.GetPreviewVisibility()" SelectionUpdate="@this.UpdatePreviewFeatures" OptionHelp="Do you want to show preview features in the app?"/>
|
|
||||||
|
|
||||||
@if(this.SettingsManager.ConfigurationData.App.PreviewVisibility > PreviewVisibility.NONE)
|
|
||||||
{
|
|
||||||
var availablePreviewFeatures = ConfigurationSelectDataFactory.GetPreviewFeaturesData(this.SettingsManager).ToList();
|
|
||||||
if (availablePreviewFeatures.Count > 0)
|
|
||||||
{
|
|
||||||
<ConfigurationMultiSelect OptionDescription="Select preview features" SelectedValues="@(() => this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures)" Data="@availablePreviewFeatures" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures = selectedValue)" OptionHelp="Which preview features would you like to enable?"/>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<ConfigurationProviderSelection Data="@this.availableLLMProviders" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreselectedProvider = selectedValue)" HelpText="@(() => "Would you like to set one provider as the default for the entire app? When you configure a different provider for an assistant, it will always take precedence.")"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.PreselectedProfile = selectedValue)" OptionHelp="Would you like to set one of your profiles as the default for the entire app? When you configure a different profile for an assistant, it will always take precedence."/>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Chat" HeaderText="Chat Options">
|
|
||||||
<ConfigurationSelect OptionDescription="Shortcut to send input" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.ShortcutSendBehavior)" Data="@ConfigurationSelectDataFactory.GetSendBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.ShortcutSendBehavior = selectedValue)" OptionHelp="Do you want to use any shortcut to send your input?"/>
|
|
||||||
<ConfigurationOption OptionDescription="Show the latest message after loading?" LabelOn="Latest message is shown, after loading a chat" LabelOff="First (oldest) message is shown, after loading a chat" State="@(() => this.SettingsManager.ConfigurationData.Chat.ShowLatestMessageAfterLoading)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Chat.ShowLatestMessageAfterLoading = updatedState)" OptionHelp="When enabled, the latest message is shown after loading a chat. When disabled, the first (oldest) message is shown."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Provider selection when creating new chats" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.AddChatProviderBehavior)" Data="@ConfigurationSelectDataFactory.GetAddChatProviderBehavior()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.AddChatProviderBehavior = selectedValue)" OptionHelp="Control how the LLM provider for added chats is selected."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Provider selection when loading a chat and sending assistant results to chat" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.LoadingProviderBehavior)" Data="@ConfigurationSelectDataFactory.GetLoadingChatProviderBehavior()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.LoadingProviderBehavior = selectedValue)" OptionHelp="Control how the LLM provider for loaded chats is selected and when assistant results are sent to chat."/>
|
|
||||||
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect chat options?" LabelOn="Chat options are preselected" LabelOff="No chat options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Chat.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Chat.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect chat options. This is might be useful when you prefer a specific provider."/>
|
|
||||||
<ConfigurationProviderSelection Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Chat.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.PreselectedProvider = selectedValue)"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Chat.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.PreselectedProfile = selectedValue)" OptionHelp="Would you like to set one of your profiles as the default for chats?"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Work" HeaderText="Workspace Options">
|
|
||||||
<ConfigurationSelect OptionDescription="Workspace behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Workspace.StorageBehavior)" Data="@ConfigurationSelectDataFactory.GetWorkspaceStorageBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Workspace.StorageBehavior = selectedValue)" OptionHelp="Should we store your chats?"/>
|
|
||||||
|
|
||||||
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES)
|
|
||||||
{
|
|
||||||
<ConfigurationSelect OptionDescription="Workspace maintenance" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy)" Data="@ConfigurationSelectDataFactory.GetWorkspaceStorageTemporaryMaintenancePolicyData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy = selectedValue)" OptionHelp="If and when should we delete your temporary chats?"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Workspace display behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior)" Data="@ConfigurationSelectDataFactory.GetWorkspaceDisplayBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior = selectedValue)" OptionHelp="How should we display your workspaces?"/>
|
|
||||||
}
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.FindInPage" HeaderText="Assistant: Icon Finder Options">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect icon options?" LabelOn="Icon options are preselected" LabelOff="No icon options are preselected" State="@(() => this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the icon options. This is might be useful when you prefer a specific icon source or LLM model."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the icon source" Disabled="@(() => !this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource)" Data="@ConfigurationSelectDataFactory.GetIconSourcesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource = selectedValue)" OptionHelp="Which icon source should be preselected?"/>
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.IconFinder.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.IconFinder.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.ICON_FINDER_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Translate" HeaderText="Assistant: Translator Options">
|
|
||||||
<ConfigurationSlider T="int" OptionDescription="How fast should the live translation react?" Min="500" Max="3_000" Step="100" Unit="milliseconds" Value="@(() => this.SettingsManager.ConfigurationData.Translation.DebounceIntervalMilliseconds)" ValueUpdate="@(updatedValue => this.SettingsManager.ConfigurationData.Translation.DebounceIntervalMilliseconds = updatedValue)"/>
|
|
||||||
<ConfigurationOption OptionDescription="Hide the web content reader?" LabelOn="Web content reader is hidden" LabelOff="Web content reader is shown" State="@(() => this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.HideWebContentReader = updatedState)" OptionHelp="When activated, the web content reader is hidden and cannot be used. As a result, the user interface becomes a bit easier to use."/>
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect translator options?" LabelOn="Translator options are preselected" LabelOff="No translator options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the translator options. This is might be useful when you prefer a specific target language or LLM model."/>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect the web content reader?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions || this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)" LabelOn="Web content reader is preselected" LabelOff="Web content reader is not preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectWebContentReader = updatedState)" OptionHelp="When enabled, the web content reader is preselected. This is might be useful when you prefer to load content from the web very often."/>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect the content cleaner agent?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions || this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)" LabelOn="Content cleaner agent is preselected" LabelOff="Content cleaner agent is not preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectContentCleanerAgent)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectContentCleanerAgent = updatedState)" OptionHelp="When enabled, the content cleaner agent is preselected. This is might be useful when you prefer to clean up the content before translating it."/>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect live translation?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" LabelOn="Live translation is preselected" LabelOff="Live translation is not preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectLiveTranslation)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectLiveTranslation = updatedState)" />
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.TRANSLATION_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.PreselectedProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Code" HeaderText="Assistant: Coding Options">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect coding options?" LabelOn="Coding options are preselected" LabelOff="No coding options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Coding.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the coding options. This is might be useful when you prefer a specific programming language or LLM model."/>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect compiler messages?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" LabelOn="Compiler messages are preselected" LabelOff="Compiler messages are not preselected" State="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectCompilerMessages)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Coding.PreselectCompilerMessages = updatedState)" />
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect a programming language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonCodingLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage = selectedValue)" OptionHelp="Which programming language should be preselected for added contexts?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage is CommonCodingLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another programming language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" Icon="@Icons.Material.Filled.Code" Text="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedOtherProgrammingLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Coding.PreselectedOtherProgrammingLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.CODING_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.PreselectedProvider = selectedValue)"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.PrivateConnectivity" HeaderText="Assistant: ERI Server Options">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect ERI server options?" LabelOn="ERI server options are preselected" LabelOff="No ERI server options are preselected" State="@(() => this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.ERI.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect some ERI server options."/>
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.ERI.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.ERI.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.ERI.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.ERI.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
|
||||||
|
|
||||||
<MudText Typo="Typo.body1" Class="mb-3">
|
|
||||||
Most ERI server options can be customized and saved directly in the ERI server assistant.
|
|
||||||
For this, the ERI server assistant has an auto-save function.
|
|
||||||
</MudText>
|
|
||||||
|
|
||||||
<MudButton Size="Size.Large" Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.PrivateConnectivity" Color="Color.Default" Href="@Routes.ASSISTANT_ERI">
|
|
||||||
Switch to ERI server assistant
|
|
||||||
</MudButton>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TextSnippet" HeaderText="Assistant: Text Summarizer Options">
|
|
||||||
<ConfigurationOption OptionDescription="Hide the web content reader?" LabelOn="Web content reader is hidden" LabelOff="Web content reader is shown" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader = updatedState)" OptionHelp="When activated, the web content reader is hidden and cannot be used. As a result, the user interface becomes a bit easier to use."/>
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect summarizer options?" LabelOn="Summarizer options are preselected" LabelOff="No summarizer options are preselected" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the text summarizer options. This is might be useful when you prefer a specific language, complexity, or LLM."/>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect the web content reader?" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions || this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)" LabelOn="Web content reader is preselected" LabelOff="Web content reader is not preselected" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectWebContentReader = updatedState)" OptionHelp="When enabled, the web content reader is preselected. This is might be useful when you prefer to load content from the web very often."/>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect the content cleaner agent?" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions || this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)" LabelOn="Content cleaner agent is preselected" LabelOff="Content cleaner agent is not preselected" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectContentCleanerAgent)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectContentCleanerAgent = updatedState)" OptionHelp="When enabled, the content cleaner agent is preselected. This is might be useful when you prefer to clean up the content before summarize it."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the summarizer complexity" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity)" Data="@ConfigurationSelectDataFactory.GetComplexityData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity = selectedValue)" OptionHelp="Which summarizer complexity should be preselected?"/>
|
|
||||||
@if(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity is Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect your expertise" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" Icon="@Icons.Material.Filled.Person" Text="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedExpertInField)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedExpertInField = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.TEXT_SUMMARIZER_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.CalendarToday" HeaderText="Assistant: Agenda Options">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect agenda options?" LabelOn="Agenda options are preselected" LabelOff="No agenda options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect most agenda options. This is might be useful when you need to create similar agendas often."/>
|
|
||||||
<ConfigurationText OptionDescription="Preselect a name?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Tag" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectName)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectName = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect a topic?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.EventNote" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectTopic)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectTopic = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect an objective?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Flag" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectObjective)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectObjective = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect a moderator?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Person3" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectModerator)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectModerator = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect a duration?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Schedule" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectDuration)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectDuration = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect a start time?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Schedule" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime = updatedText)" />
|
|
||||||
<ConfigurationOption OptionDescription="Preselect whether the participants should get to know each other" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Participants should get to know each other" LabelOff="Participants do not need to get to know each other" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants = updatedState)" />
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the number of participants" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants)" Data="@ConfigurationSelectDataFactory.GetNumberParticipantsData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants = selectedValue)" OptionHelp="How many participants should be preselected?"/>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect whether the participants should actively involved" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Participants should be actively involved" LabelOff="Participants do not need to be actively involved" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation = updatedState)" />
|
|
||||||
<ConfigurationOption OptionDescription="Preselect whether the meeting is virtual" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Meeting is virtual" LabelOff="Meeting is in person" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual = updatedState)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect a location?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.MyLocation" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectLocation)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectLocation = updatedText)" />
|
|
||||||
<ConfigurationOption OptionDescription="Preselect whether there is a joint dinner" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="There is a joint dinner" LabelOff="There is no joint dinner" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner = updatedState)" />
|
|
||||||
<ConfigurationOption OptionDescription="Preselect whether there is a social event" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="There is a social event" LabelOff="There is no social event" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity = updatedState)" />
|
|
||||||
<ConfigurationOption OptionDescription="Preselect whether participants needs to arrive and depart" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Participants need to arrive and depart" LabelOff="Participants do not need to arrive and depart" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart = updatedState)" />
|
|
||||||
<ConfigurationSlider T="int" OptionDescription="Preselect the approx. lunch time" Min="30" Max="120" Step="5" Unit="minutes" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Value="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime)" ValueUpdate="@(updatedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime = updatedValue)" />
|
|
||||||
<ConfigurationSlider T="int" OptionDescription="Preselect the approx. break time" Min="10" Max="60" Step="5" Unit="minutes" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Value="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime)" ValueUpdate="@(updatedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime = updatedValue)" />
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the agenda language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which agenda language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another agenda language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.AGENDA_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider = selectedValue)"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Edit" HeaderText="Assistant: Grammar & Spelling Checker">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect grammar & spell checker options?" LabelOn="Grammar & spell checker options are preselected" LabelOff="No grammar & spell checker options are preselected" State="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the grammar & spell checker options. This is might be useful when you prefer a specific language or LLM model."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.GRAMMAR_SPELLING_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Edit" HeaderText="Assistant: Rewrite & Improve Text">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect rewrite & improve text options?" LabelOn="Rewrite & improve text options are preselected" LabelOff="No rewrite & improve text options are preselected" State="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the rewrite & improve text options. This is might be useful when you prefer a specific language or LLM model."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect a writing style" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle)" Data="@ConfigurationSelectDataFactory.GetWritingStyles4RewriteData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle = selectedValue)" OptionHelp="Which writing style should be preselected?"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect a sentence structure" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedSentenceStructure)" Data="@ConfigurationSelectDataFactory.GetSentenceStructureData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedSentenceStructure = selectedValue)" OptionHelp="Which voice should be preselected for the sentence structure?"/>
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.REWRITE_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Email" HeaderText="Assistant: Writing E-Mails">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect e-mail options?" LabelOn="E-Mail options are preselected" LabelOff="No e-mail options are preselected" State="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.EMail.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the e-mail options. This is might be useful when you prefer a specific language or LLM model."/>
|
|
||||||
<ConfigurationText OptionDescription="Preselect a greeting?" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" Icon="@Icons.Material.Filled.Person" Text="@(() => this.SettingsManager.ConfigurationData.EMail.Greeting)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.EMail.Greeting = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect your name for the closing salutation?" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" Icon="@Icons.Material.Filled.Person" Text="@(() => this.SettingsManager.ConfigurationData.EMail.SenderName)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.EMail.SenderName = updatedText)" />
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.EMail.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.EMail.PreselectOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect a writing style" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectedWritingStyle)" Data="@ConfigurationSelectDataFactory.GetWritingStyles4EMailData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.PreselectedWritingStyle = selectedValue)" OptionHelp="Which writing style should be preselected?"/>
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.EMAIL_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.PreselectedProvider = selectedValue)"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.EMail.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.EMail.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.EMail.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Work" HeaderText="Assistant: Job Postings">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect job posting options?" LabelOn="Job posting options are preselected" LabelOff="No job posting options are preselected" State="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect some job posting options. This is might be useful when you prefer a specific LLM model."/>
|
|
||||||
<ConfigurationText OptionDescription="Preselect the company name?" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Warehouse" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedCompanyName)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedCompanyName = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect some mandatory information about the job posting?" NumLines="6" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.TextSnippet" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedMandatoryInformation)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedMandatoryInformation = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect the job description?" NumLines="3" MaxLines="6" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Settings" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedJobDescription)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedJobDescription = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect the job qualifications?" NumLines="3" MaxLines="6" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Settings" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedQualifications)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedQualifications = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect the job responsibilities?" NumLines="3" MaxLines="6" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Settings" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedResponsibilities)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedResponsibilities = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect the work location?" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.MyLocation" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedWorkLocation)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedWorkLocation = updatedText)" />
|
|
||||||
<ConfigurationText OptionDescription="Preselect the country (legal framework)?" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Flag" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedCountryLegalFramework)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectedCountryLegalFramework = updatedText)" />
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the language" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.JobPostings.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.JobPostings.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.JobPostings.PreselectOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.JobPostings.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.JobPostings.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.JOB_POSTING_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.JobPostings.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.JobPostings.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.JobPostings.PreselectedProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Gavel" HeaderText="Assistant: Legal Check">
|
|
||||||
<ConfigurationOption OptionDescription="Hide the web content reader?" LabelOn="Web content reader is hidden" LabelOff="Web content reader is shown" State="@(() => this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader = updatedState)" OptionHelp="When activated, the web content reader is hidden and cannot be used. As a result, the user interface becomes a bit easier to use."/>
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect legal check options?" LabelOn="Legal check options are preselected" LabelOff="No legal check options are preselected" State="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect some legal check options. This is might be useful when you prefer a specific LLM model."/>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect the web content reader?" Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions || this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader)" LabelOn="Web content reader is preselected" LabelOff="Web content reader is not preselected" State="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LegalCheck.PreselectWebContentReader = updatedState)" OptionHelp="When enabled, the web content reader is preselected. This is might be useful when you prefer to load legal content from the web very often."/>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect the content cleaner agent?" Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions || this.SettingsManager.ConfigurationData.LegalCheck.HideWebContentReader)" LabelOn="Content cleaner agent is preselected" LabelOff="Content cleaner agent is not preselected" State="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectContentCleanerAgent)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.LegalCheck.PreselectContentCleanerAgent = updatedState)" OptionHelp="When enabled, the content cleaner agent is preselected. This is might be useful when you prefer to clean up the legal content before translating it."/>
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LegalCheck.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LegalCheck.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.LEGAL_CHECK_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LegalCheck.PreselectedProvider = selectedValue)"/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.LegalCheck.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.LegalCheck.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.LegalCheck.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Spellcheck" HeaderText="Assistant: Synonyms">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect synonym options?" LabelOn="Synonym options are preselected" LabelOff="No synonym options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect synonym options. This is might be useful when you prefer a specific language or LLM model."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Synonyms.PreselectedLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Synonyms.PreselectedLanguage = selectedValue)" OptionHelp="Which language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.Synonyms.PreselectedLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Synonyms.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Synonyms.PreselectedOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Synonyms.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Synonyms.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.SYNONYMS_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Synonyms.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Synonyms.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Synonyms.PreselectedProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Task" HeaderText="Assistant: My Tasks">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect options?" LabelOn="Options are preselected" LabelOff="No options are preselected" State="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect options. This is might be useful when you prefer a specific language or LLM model."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the language" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another language" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.MyTasks.PreselectOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.MY_TASKS_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.MyTasks.PreselectedProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Psychology" HeaderText="Assistant: Bias of the Day">
|
|
||||||
|
|
||||||
<ConfigurationOption OptionDescription="Restrict to one bias a day?" LabelOn="Yes, you can only retrieve one bias per day" LabelOff="No restriction. You can retrieve as many biases as you want per day." State="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.RestrictOneBiasPerDay)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.BiasOfTheDay.RestrictOneBiasPerDay = updatedState)"/>
|
|
||||||
|
|
||||||
<MudField Label="Statistics" Variant="Variant.Outlined" Class="mb-2">
|
|
||||||
<MudText Typo="Typo.body1">
|
|
||||||
You have learned about @this.SettingsManager.ConfigurationData.BiasOfTheDay.UsedBias.Count out of @BiasCatalog.ALL_BIAS.Count biases.
|
|
||||||
</MudText>
|
|
||||||
<MudButton Size="Size.Small" Variant="Variant.Filled" StartIcon="@Icons.Material.Filled.Restore" Color="Color.Error" OnClick="@(() => this.ResetBiasOfTheDayHistory())">
|
|
||||||
Reset
|
|
||||||
</MudButton>
|
|
||||||
</MudField>
|
|
||||||
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<ConfigurationOption OptionDescription="Preselect options?" LabelOn="Options are preselected" LabelOff="No options are preselected" State="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect options. This is might be useful when you prefer a specific language or LLM model."/>
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect the language" Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesOptionalData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which language should be preselected?"/>
|
|
||||||
@if (this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
|
||||||
{
|
|
||||||
<ConfigurationText OptionDescription="Preselect another language" Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedOtherLanguage = updatedText)"/>
|
|
||||||
}
|
|
||||||
<ConfigurationSelect OptionDescription="Preselect one of your profiles?" Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedProfile = selectedValue)" OptionHelp="Would you like to preselect one of your profiles?"/>
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" RestrictToGlobalMinimumConfidence="@true" SelectedValue="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.MinimumProviderConfidence)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.BiasOfTheDay.MinimumProviderConfidence = selectedValue)"/>
|
|
||||||
<ConfigurationProviderSelection Component="Components.BIAS_DAY_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.BiasOfTheDay.PreselectedProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
|
|
||||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TextFields" HeaderText="Agent: Text Content Cleaner Options">
|
|
||||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
|
||||||
<MudText Typo="Typo.body1" Class="mb-3">
|
|
||||||
Use Case: this agent is used to clean up text content. It extracts the main content, removes advertisements and other irrelevant things,
|
|
||||||
and attempts to convert relative links into absolute links so that they can be used.
|
|
||||||
</MudText>
|
|
||||||
<ConfigurationOption OptionDescription="Preselect text content cleaner options?" LabelOn="Options are preselected" LabelOff="No options are preselected" State="@(() => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions = updatedState)" OptionHelp="When enabled, you can preselect some agent options. This is might be useful when you prefer a LLM."/>
|
|
||||||
<ConfigurationProviderSelection Data="@this.availableLLMProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider = selectedValue)"/>
|
|
||||||
</MudPaper>
|
|
||||||
</ExpansionPanel>
|
|
||||||
</MudExpansionPanels>
|
</MudExpansionPanels>
|
||||||
</InnerScrolling>
|
</InnerScrolling>
|
||||||
@@ -1,33 +1,17 @@
|
|||||||
using AIStudio.Dialogs;
|
|
||||||
using AIStudio.Provider;
|
|
||||||
using AIStudio.Settings;
|
using AIStudio.Settings;
|
||||||
using AIStudio.Settings.DataModel;
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
|
||||||
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
|
||||||
using RustService = AIStudio.Tools.RustService;
|
|
||||||
|
|
||||||
// ReSharper disable ClassNeverInstantiated.Global
|
|
||||||
|
|
||||||
namespace AIStudio.Pages;
|
namespace AIStudio.Pages;
|
||||||
|
|
||||||
public partial class Settings : ComponentBase, IMessageBusReceiver, IDisposable
|
public partial class Settings : ComponentBase, IMessageBusReceiver, IDisposable
|
||||||
{
|
{
|
||||||
[Inject]
|
|
||||||
private SettingsManager SettingsManager { get; init; } = null!;
|
|
||||||
|
|
||||||
[Inject]
|
|
||||||
private IDialogService DialogService { get; init; } = null!;
|
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
private MessageBus MessageBus { get; init; } = null!;
|
private MessageBus MessageBus { get; init; } = null!;
|
||||||
|
|
||||||
[Inject]
|
private List<ConfigurationSelectData<string>> availableLLMProviders = new();
|
||||||
private RustService RustService { get; init; } = null!;
|
private List<ConfigurationSelectData<string>> availableEmbeddingProviders = new();
|
||||||
|
private List<ConfigurationSelectData<string>> availableDataSources = new();
|
||||||
private readonly List<ConfigurationSelectData<string>> availableLLMProviders = new();
|
|
||||||
private readonly List<ConfigurationSelectData<string>> availableEmbeddingProviders = new();
|
|
||||||
|
|
||||||
#region Overrides of ComponentBase
|
#region Overrides of ComponentBase
|
||||||
|
|
||||||
@@ -37,326 +21,9 @@ public partial class Settings : ComponentBase, IMessageBusReceiver, IDisposable
|
|||||||
this.MessageBus.RegisterComponent(this);
|
this.MessageBus.RegisterComponent(this);
|
||||||
this.MessageBus.ApplyFilters(this, [], [ Event.CONFIGURATION_CHANGED ]);
|
this.MessageBus.ApplyFilters(this, [], [ Event.CONFIGURATION_CHANGED ]);
|
||||||
|
|
||||||
this.UpdateProviders();
|
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Preview-feature related
|
|
||||||
|
|
||||||
private void UpdatePreviewFeatures(PreviewVisibility previewVisibility)
|
|
||||||
{
|
|
||||||
this.SettingsManager.ConfigurationData.App.PreviewVisibility = previewVisibility;
|
|
||||||
this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures = previewVisibility.FilterPreviewFeatures(this.SettingsManager.ConfigurationData.App.EnabledPreviewFeatures);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Provider related
|
|
||||||
|
|
||||||
private async Task AddLLMProvider()
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters<ProviderDialog>
|
|
||||||
{
|
|
||||||
{ x => x.IsEditing, false },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<ProviderDialog>("Add LLM Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var addedProvider = (AIStudio.Settings.Provider)dialogResult.Data!;
|
|
||||||
addedProvider = addedProvider with { Num = this.SettingsManager.ConfigurationData.NextProviderNum++ };
|
|
||||||
|
|
||||||
this.SettingsManager.ConfigurationData.Providers.Add(addedProvider);
|
|
||||||
this.UpdateProviders();
|
|
||||||
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task EditLLMProvider(AIStudio.Settings.Provider provider)
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters<ProviderDialog>
|
|
||||||
{
|
|
||||||
{ x => x.DataNum, provider.Num },
|
|
||||||
{ x => x.DataId, provider.Id },
|
|
||||||
{ x => x.DataInstanceName, provider.InstanceName },
|
|
||||||
{ x => x.DataLLMProvider, provider.UsedLLMProvider },
|
|
||||||
{ x => x.DataModel, provider.Model },
|
|
||||||
{ x => x.DataHostname, provider.Hostname },
|
|
||||||
{ x => x.IsSelfHosted, provider.IsSelfHosted },
|
|
||||||
{ x => x.IsEditing, true },
|
|
||||||
{ x => x.DataHost, provider.Host },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<ProviderDialog>("Edit LLM Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var editedProvider = (AIStudio.Settings.Provider)dialogResult.Data!;
|
|
||||||
|
|
||||||
// Set the provider number if it's not set. This is important for providers
|
|
||||||
// added before we started saving the provider number.
|
|
||||||
if(editedProvider.Num == 0)
|
|
||||||
editedProvider = editedProvider with { Num = this.SettingsManager.ConfigurationData.NextProviderNum++ };
|
|
||||||
|
|
||||||
this.SettingsManager.ConfigurationData.Providers[this.SettingsManager.ConfigurationData.Providers.IndexOf(provider)] = editedProvider;
|
|
||||||
this.UpdateProviders();
|
|
||||||
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task DeleteLLMProvider(AIStudio.Settings.Provider provider)
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters
|
|
||||||
{
|
|
||||||
{ "Message", $"Are you sure you want to delete the provider '{provider.InstanceName}'?" },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete LLM Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var deleteSecretResponse = await this.RustService.DeleteAPIKey(provider);
|
|
||||||
if(deleteSecretResponse.Success)
|
|
||||||
{
|
|
||||||
this.SettingsManager.ConfigurationData.Providers.Remove(provider);
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.UpdateProviders();
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetLLMProviderModelName(AIStudio.Settings.Provider provider)
|
|
||||||
{
|
|
||||||
const int MAX_LENGTH = 36;
|
|
||||||
var modelName = provider.Model.ToString();
|
|
||||||
return modelName.Length > MAX_LENGTH ? "[...] " + modelName[^Math.Min(MAX_LENGTH, modelName.Length)..] : modelName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateProviders()
|
|
||||||
{
|
|
||||||
this.availableLLMProviders.Clear();
|
|
||||||
foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
|
||||||
this.availableLLMProviders.Add(new (provider.InstanceName, provider.Id));
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetCurrentConfidenceLevelName(LLMProviders llmProvider)
|
|
||||||
{
|
|
||||||
if (this.SettingsManager.ConfigurationData.LLMProviders.CustomConfidenceScheme.TryGetValue(llmProvider, out var level))
|
|
||||||
return level.GetName();
|
|
||||||
|
|
||||||
return "Not yet configured";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string SetCurrentConfidenceLevelColorStyle(LLMProviders llmProvider)
|
|
||||||
{
|
|
||||||
if (this.SettingsManager.ConfigurationData.LLMProviders.CustomConfidenceScheme.TryGetValue(llmProvider, out var level))
|
|
||||||
return $"background-color: {level.GetColor(this.SettingsManager)};";
|
|
||||||
|
|
||||||
return $"background-color: {ConfidenceLevel.UNKNOWN.GetColor(this.SettingsManager)};";
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ChangeCustomConfidenceLevel(LLMProviders llmProvider, ConfidenceLevel level)
|
|
||||||
{
|
|
||||||
this.SettingsManager.ConfigurationData.LLMProviders.CustomConfidenceScheme[llmProvider] = level;
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Embedding provider related
|
|
||||||
|
|
||||||
private string GetEmbeddingProviderModelName(EmbeddingProvider provider)
|
|
||||||
{
|
|
||||||
const int MAX_LENGTH = 36;
|
|
||||||
var modelName = provider.Model.ToString();
|
|
||||||
return modelName.Length > MAX_LENGTH ? "[...] " + modelName[^Math.Min(MAX_LENGTH, modelName.Length)..] : modelName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AddEmbeddingProvider()
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters<EmbeddingProviderDialog>
|
|
||||||
{
|
|
||||||
{ x => x.IsEditing, false },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<EmbeddingProviderDialog>("Add Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var addedEmbedding = (EmbeddingProvider)dialogResult.Data!;
|
|
||||||
addedEmbedding = addedEmbedding with { Num = this.SettingsManager.ConfigurationData.NextEmbeddingNum++ };
|
|
||||||
|
|
||||||
this.SettingsManager.ConfigurationData.EmbeddingProviders.Add(addedEmbedding);
|
|
||||||
this.UpdateEmbeddingProviders();
|
|
||||||
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task EditEmbeddingProvider(EmbeddingProvider embeddingProvider)
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters<EmbeddingProviderDialog>
|
|
||||||
{
|
|
||||||
{ x => x.DataNum, embeddingProvider.Num },
|
|
||||||
{ x => x.DataId, embeddingProvider.Id },
|
|
||||||
{ x => x.DataName, embeddingProvider.Name },
|
|
||||||
{ x => x.DataLLMProvider, embeddingProvider.UsedLLMProvider },
|
|
||||||
{ x => x.DataModel, embeddingProvider.Model },
|
|
||||||
{ x => x.DataHostname, embeddingProvider.Hostname },
|
|
||||||
{ x => x.IsSelfHosted, embeddingProvider.IsSelfHosted },
|
|
||||||
{ x => x.IsEditing, true },
|
|
||||||
{ x => x.DataHost, embeddingProvider.Host },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<EmbeddingProviderDialog>("Edit Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var editedEmbeddingProvider = (EmbeddingProvider)dialogResult.Data!;
|
|
||||||
|
|
||||||
// Set the provider number if it's not set. This is important for providers
|
|
||||||
// added before we started saving the provider number.
|
|
||||||
if(editedEmbeddingProvider.Num == 0)
|
|
||||||
editedEmbeddingProvider = editedEmbeddingProvider with { Num = this.SettingsManager.ConfigurationData.NextEmbeddingNum++ };
|
|
||||||
|
|
||||||
this.SettingsManager.ConfigurationData.EmbeddingProviders[this.SettingsManager.ConfigurationData.EmbeddingProviders.IndexOf(embeddingProvider)] = editedEmbeddingProvider;
|
|
||||||
this.UpdateEmbeddingProviders();
|
|
||||||
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task DeleteEmbeddingProvider(EmbeddingProvider provider)
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters
|
|
||||||
{
|
|
||||||
{ "Message", $"Are you sure you want to delete the embedding provider '{provider.Name}'?" },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Embedding Provider", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var deleteSecretResponse = await this.RustService.DeleteAPIKey(provider);
|
|
||||||
if(deleteSecretResponse.Success)
|
|
||||||
{
|
|
||||||
this.SettingsManager.ConfigurationData.EmbeddingProviders.Remove(provider);
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.UpdateEmbeddingProviders();
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateEmbeddingProviders()
|
|
||||||
{
|
|
||||||
this.availableEmbeddingProviders.Clear();
|
|
||||||
foreach (var provider in this.SettingsManager.ConfigurationData.EmbeddingProviders)
|
|
||||||
this.availableEmbeddingProviders.Add(new (provider.Name, provider.Id));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Profile related
|
|
||||||
|
|
||||||
private async Task AddProfile()
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters<ProfileDialog>
|
|
||||||
{
|
|
||||||
{ x => x.IsEditing, false },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<ProfileDialog>("Add Profile", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var addedProfile = (Profile)dialogResult.Data!;
|
|
||||||
addedProfile = addedProfile with { Num = this.SettingsManager.ConfigurationData.NextProfileNum++ };
|
|
||||||
|
|
||||||
this.SettingsManager.ConfigurationData.Profiles.Add(addedProfile);
|
|
||||||
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task EditProfile(Profile profile)
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters<ProfileDialog>
|
|
||||||
{
|
|
||||||
{ x => x.DataNum, profile.Num },
|
|
||||||
{ x => x.DataId, profile.Id },
|
|
||||||
{ x => x.DataName, profile.Name },
|
|
||||||
{ x => x.DataNeedToKnow, profile.NeedToKnow },
|
|
||||||
{ x => x.DataActions, profile.Actions },
|
|
||||||
{ x => x.IsEditing, true },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<ProfileDialog>("Edit Profile", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var editedProfile = (Profile)dialogResult.Data!;
|
|
||||||
this.SettingsManager.ConfigurationData.Profiles[this.SettingsManager.ConfigurationData.Profiles.IndexOf(profile)] = editedProfile;
|
|
||||||
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task DeleteProfile(Profile profile)
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters
|
|
||||||
{
|
|
||||||
{ "Message", $"Are you sure you want to delete the profile '{profile.Name}'?" },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Profile", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.SettingsManager.ConfigurationData.Profiles.Remove(profile);
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Bias-of-the-day related
|
|
||||||
|
|
||||||
private async Task ResetBiasOfTheDayHistory()
|
|
||||||
{
|
|
||||||
var dialogParameters = new DialogParameters
|
|
||||||
{
|
|
||||||
{ "Message", "Are you sure you want to reset your bias-of-the-day statistics? The system will no longer remember which biases you already know. As a result, biases you are already familiar with may be addressed again." },
|
|
||||||
};
|
|
||||||
|
|
||||||
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Reset your bias-of-the-day statistics", dialogParameters, DialogOptions.FULLSCREEN);
|
|
||||||
var dialogResult = await dialogReference.Result;
|
|
||||||
if (dialogResult is null || dialogResult.Canceled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.SettingsManager.ConfigurationData.BiasOfTheDay.UsedBias.Clear();
|
|
||||||
this.SettingsManager.ConfigurationData.BiasOfTheDay.DateLastBiasDrawn = DateOnly.MinValue;
|
|
||||||
await this.SettingsManager.StoreSettings();
|
|
||||||
|
|
||||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Implementation of IMessageBusReceiver
|
#region Implementation of IMessageBusReceiver
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public static class LLMProvidersExtensions
|
|||||||
/// <param name="providerSettings">The provider settings.</param>
|
/// <param name="providerSettings">The provider settings.</param>
|
||||||
/// <param name="logger">The logger to use.</param>
|
/// <param name="logger">The logger to use.</param>
|
||||||
/// <returns>The provider instance.</returns>
|
/// <returns>The provider instance.</returns>
|
||||||
public static IProvider CreateProvider(this Settings.Provider providerSettings, ILogger logger)
|
public static IProvider CreateProvider(this AIStudio.Settings.Provider providerSettings, ILogger logger)
|
||||||
{
|
{
|
||||||
return providerSettings.UsedLLMProvider.CreateProvider(providerSettings.InstanceName, providerSettings.Host, providerSettings.Hostname, logger);
|
return providerSettings.UsedLLMProvider.CreateProvider(providerSettings.InstanceName, providerSettings.Host, providerSettings.Hostname, logger);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ public sealed class Data
|
|||||||
/// A collection of embedding providers configured.
|
/// A collection of embedding providers configured.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<EmbeddingProvider> EmbeddingProviders { get; init; } = [];
|
public List<EmbeddingProvider> EmbeddingProviders { get; init; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A collection of data sources configured.
|
||||||
|
/// </summary>
|
||||||
|
public List<IDataSource> DataSources { get; set; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of configured profiles.
|
/// List of configured profiles.
|
||||||
@@ -41,6 +46,11 @@ public sealed class Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public uint NextEmbeddingNum { get; set; } = 1;
|
public uint NextEmbeddingNum { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The next data source number to use.
|
||||||
|
/// </summary>
|
||||||
|
public uint NextDataSourceNum { get; set; } = 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The next profile number to use.
|
/// The next profile number to use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using ERI_Client.V1;
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
namespace AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An external data source, accessed via an ERI server, cf. https://github.com/MindWorkAI/ERI.
|
||||||
|
/// </summary>
|
||||||
|
public readonly record struct DataSourceERI_V1 : IERIDataSource
|
||||||
|
{
|
||||||
|
public DataSourceERI_V1()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public uint Num { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Id { get; init; } = Guid.Empty.ToString();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Name { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DataSourceType Type { get; init; } = DataSourceType.NONE;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The hostname of the ERI server.
|
||||||
|
/// </summary>
|
||||||
|
public string Hostname { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The port of the ERI server.
|
||||||
|
/// </summary>
|
||||||
|
public int Port { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The authentication method to use.
|
||||||
|
/// </summary>
|
||||||
|
public AuthMethod AuthMethod { get; init; } = AuthMethod.NONE;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The username to use for authentication, when the auth. method is USERNAME_PASSWORD.
|
||||||
|
/// </summary>
|
||||||
|
public string Username { get; init; } = string.Empty;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
namespace AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a local directory as a data source.
|
||||||
|
/// </summary>
|
||||||
|
public readonly record struct DataSourceLocalDirectory : IInternalDataSource
|
||||||
|
{
|
||||||
|
public DataSourceLocalDirectory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public uint Num { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Id { get; init; } = Guid.Empty.ToString();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Name { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DataSourceType Type { get; init; } = DataSourceType.NONE;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string EmbeddingId { get; init; } = Guid.Empty.ToString();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path to the directory.
|
||||||
|
/// </summary>
|
||||||
|
public string Path { get; init; } = string.Empty;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
namespace AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents one local file as a data source.
|
||||||
|
/// </summary>
|
||||||
|
public readonly record struct DataSourceLocalFile : IInternalDataSource
|
||||||
|
{
|
||||||
|
public DataSourceLocalFile()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public uint Num { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Id { get; init; } = Guid.Empty.ToString();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Name { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DataSourceType Type { get; init; } = DataSourceType.NONE;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string EmbeddingId { get; init; } = Guid.Empty.ToString();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path to the file.
|
||||||
|
/// </summary>
|
||||||
|
public string FilePath { get; init; } = string.Empty;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
namespace AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AI Studio data source types.
|
||||||
|
/// </summary>
|
||||||
|
public enum DataSourceType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// No data source.
|
||||||
|
/// </summary>
|
||||||
|
NONE = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// One file on the local machine (or a network share).
|
||||||
|
/// </summary>
|
||||||
|
LOCAL_FILE,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A directory on the local machine (or a network share).
|
||||||
|
/// </summary>
|
||||||
|
LOCAL_DIRECTORY,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// External data source accessed via an ERI server, cf. https://github.com/MindWorkAI/ERI.
|
||||||
|
/// </summary>
|
||||||
|
ERI_V1,
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
namespace AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for data source types.
|
||||||
|
/// </summary>
|
||||||
|
public static class DataSourceTypeExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the display name of the data source type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The data source type.</param>
|
||||||
|
/// <returns>The display name of the data source type.</returns>
|
||||||
|
public static string GetDisplayName(this DataSourceType type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
DataSourceType.LOCAL_FILE => "Local File",
|
||||||
|
DataSourceType.LOCAL_DIRECTORY => "Local Directory",
|
||||||
|
DataSourceType.ERI_V1 => "External ERI Server (v1)",
|
||||||
|
|
||||||
|
_ => "None",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,12 +2,12 @@ namespace AIStudio.Settings.DataModel.PreviousModels;
|
|||||||
|
|
||||||
public static class ProviderV4Extensions
|
public static class ProviderV4Extensions
|
||||||
{
|
{
|
||||||
public static List<Settings.Provider> MigrateFromV4ToV5(this IEnumerable<Provider> providers)
|
public static List<AIStudio.Settings.Provider> MigrateFromV4ToV5(this IEnumerable<Provider> providers)
|
||||||
{
|
{
|
||||||
return providers.Select(provider => provider.MigrateFromV4ToV5()).ToList();
|
return providers.Select(provider => provider.MigrateFromV4ToV5()).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Settings.Provider MigrateFromV4ToV5(this Provider provider) => new()
|
public static AIStudio.Settings.Provider MigrateFromV4ToV5(this Provider provider) => new()
|
||||||
{
|
{
|
||||||
Num = provider.Num,
|
Num = provider.Num,
|
||||||
Id = provider.Id,
|
Id = provider.Id,
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
using AIStudio.Settings.DataModel;
|
||||||
|
|
||||||
|
namespace AIStudio.Settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The common interface for all data sources.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPolymorphic(TypeDiscriminatorPropertyName = "$type_discriminator")]
|
||||||
|
[JsonDerivedType(typeof(DataSourceLocalDirectory), nameof(DataSourceType.LOCAL_DIRECTORY))]
|
||||||
|
[JsonDerivedType(typeof(DataSourceLocalFile), nameof(DataSourceType.LOCAL_FILE))]
|
||||||
|
[JsonDerivedType(typeof(DataSourceERI_V1), nameof(DataSourceType.ERI_V1))]
|
||||||
|
public interface IDataSource
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The number of the data source.
|
||||||
|
/// </summary>
|
||||||
|
public uint Num { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The unique identifier of the data source.
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the data source.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Which type of data source is this?
|
||||||
|
/// </summary>
|
||||||
|
public DataSourceType Type { get; init; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using ERI_Client.V1;
|
||||||
|
|
||||||
|
namespace AIStudio.Settings;
|
||||||
|
|
||||||
|
public interface IERIDataSource : IExternalDataSource
|
||||||
|
{
|
||||||
|
public string Hostname { get; init; }
|
||||||
|
|
||||||
|
public int Port { get; init; }
|
||||||
|
|
||||||
|
public AuthMethod AuthMethod { get; init; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace AIStudio.Settings;
|
||||||
|
|
||||||
|
public interface IExternalDataSource : IDataSource, ISecretId
|
||||||
|
{
|
||||||
|
#region Implementation of ISecretId
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
string ISecretId.SecretId => this.Id;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
string ISecretId.SecretName => this.Name;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace AIStudio.Settings;
|
||||||
|
|
||||||
|
public interface IInternalDataSource : IDataSource
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The unique identifier of the embedding method used by this internal data source.
|
||||||
|
/// </summary>
|
||||||
|
public string EmbeddingId { get; init; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using ERI_Client.V1;
|
||||||
|
|
||||||
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
|
public static class AuthMethodsV1Extensions
|
||||||
|
{
|
||||||
|
public static string DisplayName(this AuthMethod authMethod) => authMethod switch
|
||||||
|
{
|
||||||
|
AuthMethod.NONE => "None",
|
||||||
|
AuthMethod.USERNAME_PASSWORD => "Username & Password",
|
||||||
|
AuthMethod.KERBEROS => "SSO (Kerberos)",
|
||||||
|
AuthMethod.TOKEN => "Access Token",
|
||||||
|
|
||||||
|
_ => "Unknown authentication method",
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -75,7 +75,7 @@ public static class ComponentsExtensions
|
|||||||
_ => default,
|
_ => default,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Settings.Provider PreselectedProvider(this Components component, SettingsManager settingsManager) => component switch
|
public static AIStudio.Settings.Provider PreselectedProvider(this Components component, SettingsManager settingsManager) => component switch
|
||||||
{
|
{
|
||||||
Components.GRAMMAR_SPELLING_ASSISTANT => settingsManager.ConfigurationData.GrammarSpelling.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider) : default,
|
Components.GRAMMAR_SPELLING_ASSISTANT => settingsManager.ConfigurationData.GrammarSpelling.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider) : default,
|
||||||
Components.ICON_FINDER_ASSISTANT => settingsManager.ConfigurationData.IconFinder.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.IconFinder.PreselectedProvider) : default,
|
Components.ICON_FINDER_ASSISTANT => settingsManager.ConfigurationData.IconFinder.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.IconFinder.PreselectedProvider) : default,
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace AIStudio.Tools.Rust;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data structure for selecting a file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="UserCancelled">Was the file selection canceled?</param>
|
||||||
|
/// <param name="SelectedFilePath">The selected file, if any.</param>
|
||||||
|
public readonly record struct FileSelectionResponse(bool UserCancelled, string SelectedFilePath);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace AIStudio.Tools.Rust;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data structure for selecting a file when a previous file was selected.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="FilePath">The path of the previous file.</param>
|
||||||
|
public readonly record struct PreviousFile(string FilePath);
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
using AIStudio.Tools.Rust;
|
||||||
|
|
||||||
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
|
public sealed partial class RustService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Try to get the API key for the given secret ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="secretId">The secret ID to get the API key for.</param>
|
||||||
|
/// <param name="isTrying">Indicates if we are trying to get the API key. In that case, we don't log errors.</param>
|
||||||
|
/// <returns>The requested secret.</returns>
|
||||||
|
public async Task<RequestedSecret> GetAPIKey(ISecretId secretId, bool isTrying = false)
|
||||||
|
{
|
||||||
|
var secretRequest = new SelectSecretRequest($"provider::{secretId.SecretId}::{secretId.SecretName}::api_key", Environment.UserName, isTrying);
|
||||||
|
var result = await this.http.PostAsJsonAsync("/secrets/get", secretRequest, this.jsonRustSerializerOptions);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
if(!isTrying)
|
||||||
|
this.logger!.LogError($"Failed to get the API key for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
|
||||||
|
return new RequestedSecret(false, new EncryptedText(string.Empty), "Failed to get the API key due to an API issue.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var secret = await result.Content.ReadFromJsonAsync<RequestedSecret>(this.jsonRustSerializerOptions);
|
||||||
|
if (!secret.Success && !isTrying)
|
||||||
|
this.logger!.LogError($"Failed to get the API key for secret ID '{secretId.SecretId}': '{secret.Issue}'");
|
||||||
|
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to store the API key for the given secret ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="secretId">The secret ID to store the API key for.</param>
|
||||||
|
/// <param name="key">The API key to store.</param>
|
||||||
|
/// <returns>The store secret response.</returns>
|
||||||
|
public async Task<StoreSecretResponse> SetAPIKey(ISecretId secretId, string key)
|
||||||
|
{
|
||||||
|
var encryptedKey = await this.encryptor!.Encrypt(key);
|
||||||
|
var request = new StoreSecretRequest($"provider::{secretId.SecretId}::{secretId.SecretName}::api_key", Environment.UserName, encryptedKey);
|
||||||
|
var result = await this.http.PostAsJsonAsync("/secrets/store", request, this.jsonRustSerializerOptions);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to store the API key for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
|
||||||
|
return new StoreSecretResponse(false, "Failed to get the API key due to an API issue.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = await result.Content.ReadFromJsonAsync<StoreSecretResponse>(this.jsonRustSerializerOptions);
|
||||||
|
if (!state.Success)
|
||||||
|
this.logger!.LogError($"Failed to store the API key for secret ID '{secretId.SecretId}': '{state.Issue}'");
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to delete the API key for the given secret ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="secretId">The secret ID to delete the API key for.</param>
|
||||||
|
/// <returns>The delete secret response.</returns>
|
||||||
|
public async Task<DeleteSecretResponse> DeleteAPIKey(ISecretId secretId)
|
||||||
|
{
|
||||||
|
var request = new SelectSecretRequest($"provider::{secretId.SecretId}::{secretId.SecretName}::api_key", Environment.UserName, false);
|
||||||
|
var result = await this.http.PostAsJsonAsync("/secrets/delete", request, this.jsonRustSerializerOptions);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to delete the API key for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
|
||||||
|
return new DeleteSecretResponse{Success = false, WasEntryFound = false, Issue = "Failed to delete the API key due to an API issue."};
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = await result.Content.ReadFromJsonAsync<DeleteSecretResponse>(this.jsonRustSerializerOptions);
|
||||||
|
if (!state.Success)
|
||||||
|
this.logger!.LogError($"Failed to delete the API key for secret ID '{secretId.SecretId}': '{state.Issue}'");
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
|
public sealed partial class RustService
|
||||||
|
{
|
||||||
|
public async Task<int> GetAppPort()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Trying to get app port from Rust runtime...");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Note I: In the production environment, the Rust runtime is already running
|
||||||
|
// and listening on the given port. In the development environment, the IDE
|
||||||
|
// starts the Rust runtime in parallel with the .NET runtime. Since the
|
||||||
|
// Rust runtime needs some time to start, we have to wait for it to be ready.
|
||||||
|
//
|
||||||
|
const int MAX_TRIES = 160;
|
||||||
|
var tris = 0;
|
||||||
|
var wait4Try = TimeSpan.FromMilliseconds(250);
|
||||||
|
var url = new Uri($"https://127.0.0.1:{this.apiPort}/system/dotnet/port");
|
||||||
|
while (tris++ < MAX_TRIES)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Note II: We use a new HttpClient instance for each try to avoid
|
||||||
|
// .NET is caching the result. When we use the same HttpClient
|
||||||
|
// instance, we would always get the same result (403 forbidden),
|
||||||
|
// without even trying to connect to the Rust server.
|
||||||
|
//
|
||||||
|
|
||||||
|
using var initialHttp = new HttpClient(new HttpClientHandler
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Note III: We have to create also a new HttpClientHandler instance
|
||||||
|
// for each try to avoid .NET is caching the result. This is necessary
|
||||||
|
// because it gets disposed when the HttpClient instance gets disposed.
|
||||||
|
//
|
||||||
|
ServerCertificateCustomValidationCallback = (_, certificate, _, _) =>
|
||||||
|
{
|
||||||
|
if(certificate is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var currentCertificateFingerprint = certificate.GetCertHashString(HashAlgorithmName.SHA256);
|
||||||
|
return currentCertificateFingerprint == this.certificateFingerprint;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
initialHttp.DefaultRequestVersion = Version.Parse("2.0");
|
||||||
|
initialHttp.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher;
|
||||||
|
initialHttp.DefaultRequestHeaders.AddApiToken();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await initialHttp.GetAsync(url);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Try {tris}/{MAX_TRIES} to get the app port from Rust runtime");
|
||||||
|
await Task.Delay(wait4Try);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var appPortContent = await response.Content.ReadAsStringAsync();
|
||||||
|
var appPort = int.Parse(appPortContent);
|
||||||
|
Console.WriteLine($"Received app port from Rust runtime: '{appPort}'");
|
||||||
|
return appPort;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error: Was not able to get the app port from Rust runtime: '{e.Message}'");
|
||||||
|
Console.WriteLine(e.InnerException);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Failed to receive the app port from Rust runtime.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AppIsReady()
|
||||||
|
{
|
||||||
|
const string URL = "/system/dotnet/ready";
|
||||||
|
this.logger!.LogInformation("Notifying Rust runtime that the app is ready.");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await this.http.GetAsync(URL);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to notify Rust runtime that the app is ready: '{response.StatusCode}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
this.logger!.LogError(e, "Failed to notify the Rust runtime that the app is ready.");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetConfigDirectory()
|
||||||
|
{
|
||||||
|
var response = await this.http.GetAsync("/system/directories/config");
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to get the config directory from Rust: '{response.StatusCode}'");
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetDataDirectory()
|
||||||
|
{
|
||||||
|
var response = await this.http.GetAsync("/system/directories/data");
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to get the data directory from Rust: '{response.StatusCode}'");
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using AIStudio.Tools.Rust;
|
||||||
|
|
||||||
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
|
public sealed partial class RustService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to copy the given text to the clipboard.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="snackbar">The snackbar to show the result.</param>
|
||||||
|
/// <param name="text">The text to copy to the clipboard.</param>
|
||||||
|
public async Task CopyText2Clipboard(ISnackbar snackbar, string text)
|
||||||
|
{
|
||||||
|
var message = "Successfully copied the text to your clipboard";
|
||||||
|
var iconColor = Color.Error;
|
||||||
|
var severity = Severity.Error;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var encryptedText = await text.Encrypt(this.encryptor!);
|
||||||
|
var response = await this.http.PostAsync("/clipboard/set", new StringContent(encryptedText.EncryptedData));
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to copy the text to the clipboard due to an network error: '{response.StatusCode}'");
|
||||||
|
message = "Failed to copy the text to your clipboard.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = await response.Content.ReadFromJsonAsync<SetClipboardResponse>(this.jsonRustSerializerOptions);
|
||||||
|
if (!state.Success)
|
||||||
|
{
|
||||||
|
this.logger!.LogError("Failed to copy the text to the clipboard.");
|
||||||
|
message = "Failed to copy the text to your clipboard.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iconColor = Color.Success;
|
||||||
|
severity = Severity.Success;
|
||||||
|
this.logger!.LogDebug("Successfully copied the text to the clipboard.");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
snackbar.Add(message, severity, config =>
|
||||||
|
{
|
||||||
|
config.Icon = Icons.Material.Filled.ContentCopy;
|
||||||
|
config.IconSize = Size.Large;
|
||||||
|
config.IconColor = iconColor;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using AIStudio.Tools.Rust;
|
||||||
|
|
||||||
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
|
public sealed partial class RustService
|
||||||
|
{
|
||||||
|
public async Task<DirectorySelectionResponse> SelectDirectory(string title, string? initialDirectory = null)
|
||||||
|
{
|
||||||
|
PreviousDirectory? previousDirectory = initialDirectory is null ? null : new (initialDirectory);
|
||||||
|
var result = await this.http.PostAsJsonAsync($"/select/directory?title={title}", previousDirectory, this.jsonRustSerializerOptions);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to select a directory: '{result.StatusCode}'");
|
||||||
|
return new DirectorySelectionResponse(true, string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await result.Content.ReadFromJsonAsync<DirectorySelectionResponse>(this.jsonRustSerializerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<FileSelectionResponse> SelectFile(string title, string? initialFile = null)
|
||||||
|
{
|
||||||
|
PreviousFile? previousFile = initialFile is null ? null : new (initialFile);
|
||||||
|
var result = await this.http.PostAsJsonAsync($"/select/file?title={title}", previousFile, this.jsonRustSerializerOptions);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to select a file: '{result.StatusCode}'");
|
||||||
|
return new FileSelectionResponse(true, string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await result.Content.ReadFromJsonAsync<FileSelectionResponse>(this.jsonRustSerializerOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
using AIStudio.Tools.Rust;
|
||||||
|
|
||||||
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
|
public sealed partial class RustService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Try to get the secret data for the given secret ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="secretId">The secret ID to get the data for.</param>
|
||||||
|
/// <param name="isTrying">Indicates if we are trying to get the data. In that case, we don't log errors.</param>
|
||||||
|
/// <returns>The requested secret.</returns>
|
||||||
|
public async Task<RequestedSecret> GetSecret(ISecretId secretId, bool isTrying = false)
|
||||||
|
{
|
||||||
|
var secretRequest = new SelectSecretRequest($"secret::{secretId.SecretId}::{secretId.SecretName}", Environment.UserName, isTrying);
|
||||||
|
var result = await this.http.PostAsJsonAsync("/secrets/get", secretRequest, this.jsonRustSerializerOptions);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
if(!isTrying)
|
||||||
|
this.logger!.LogError($"Failed to get the secret data for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
|
||||||
|
return new RequestedSecret(false, new EncryptedText(string.Empty), "Failed to get the secret data due to an API issue.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var secret = await result.Content.ReadFromJsonAsync<RequestedSecret>(this.jsonRustSerializerOptions);
|
||||||
|
if (!secret.Success && !isTrying)
|
||||||
|
this.logger!.LogError($"Failed to get the secret data for secret ID '{secretId.SecretId}': '{secret.Issue}'");
|
||||||
|
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to store the secret data for the given secret ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="secretId">The secret ID to store the data for.</param>
|
||||||
|
/// <param name="secretData">The data to store.</param>
|
||||||
|
/// <returns>The store secret response.</returns>
|
||||||
|
public async Task<StoreSecretResponse> SetSecret(ISecretId secretId, string secretData)
|
||||||
|
{
|
||||||
|
var encryptedSecret = await this.encryptor!.Encrypt(secretData);
|
||||||
|
var request = new StoreSecretRequest($"secret::{secretId.SecretId}::{secretId.SecretName}", Environment.UserName, encryptedSecret);
|
||||||
|
var result = await this.http.PostAsJsonAsync("/secrets/store", request, this.jsonRustSerializerOptions);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to store the secret data for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
|
||||||
|
return new StoreSecretResponse(false, "Failed to get the secret data due to an API issue.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = await result.Content.ReadFromJsonAsync<StoreSecretResponse>(this.jsonRustSerializerOptions);
|
||||||
|
if (!state.Success)
|
||||||
|
this.logger!.LogError($"Failed to store the secret data for secret ID '{secretId.SecretId}': '{state.Issue}'");
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to delete the secret data for the given secret ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="secretId">The secret ID to delete the data for.</param>
|
||||||
|
/// <returns>The delete secret response.</returns>
|
||||||
|
public async Task<DeleteSecretResponse> DeleteSecret(ISecretId secretId)
|
||||||
|
{
|
||||||
|
var request = new SelectSecretRequest($"secret::{secretId.SecretId}::{secretId.SecretName}", Environment.UserName, false);
|
||||||
|
var result = await this.http.PostAsJsonAsync("/secrets/delete", request, this.jsonRustSerializerOptions);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to delete the secret data for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
|
||||||
|
return new DeleteSecretResponse{Success = false, WasEntryFound = false, Issue = "Failed to delete the secret data due to an API issue."};
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = await result.Content.ReadFromJsonAsync<DeleteSecretResponse>(this.jsonRustSerializerOptions);
|
||||||
|
if (!state.Success)
|
||||||
|
this.logger!.LogError($"Failed to delete the secret data for secret ID '{secretId.SecretId}': '{state.Issue}'");
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using AIStudio.Tools.Rust;
|
||||||
|
|
||||||
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
|
public sealed partial class RustService
|
||||||
|
{
|
||||||
|
public async Task<UpdateResponse> CheckForUpdate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(45));
|
||||||
|
var response = await this.http.GetFromJsonAsync<UpdateResponse>("/updates/check", this.jsonRustSerializerOptions, cts.Token);
|
||||||
|
this.logger!.LogInformation($"Checked for an update: update available='{response.UpdateIsAvailable}'; error='{response.Error}'; next version='{response.NewVersion}'; changelog len='{response.Changelog.Length}'");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
this.logger!.LogError(e, "Failed to check for an update.");
|
||||||
|
return new UpdateResponse
|
||||||
|
{
|
||||||
|
Error = true,
|
||||||
|
UpdateIsAvailable = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InstallUpdate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
await this.http.GetAsync("/updates/install", cts.Token);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
using AIStudio.Tools.Rust;
|
|
||||||
|
|
||||||
// ReSharper disable NotAccessedPositionalProperty.Local
|
// ReSharper disable NotAccessedPositionalProperty.Local
|
||||||
|
|
||||||
namespace AIStudio.Tools;
|
namespace AIStudio.Tools;
|
||||||
@@ -10,7 +8,7 @@ namespace AIStudio.Tools;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calling Rust functions.
|
/// Calling Rust functions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class RustService : IDisposable
|
public sealed partial class RustService : IDisposable
|
||||||
{
|
{
|
||||||
private readonly HttpClient http;
|
private readonly HttpClient http;
|
||||||
|
|
||||||
@@ -60,281 +58,6 @@ public sealed class RustService : IDisposable
|
|||||||
{
|
{
|
||||||
this.encryptor = encryptionService;
|
this.encryptor = encryptionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GetAppPort()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Trying to get app port from Rust runtime...");
|
|
||||||
|
|
||||||
//
|
|
||||||
// Note I: In the production environment, the Rust runtime is already running
|
|
||||||
// and listening on the given port. In the development environment, the IDE
|
|
||||||
// starts the Rust runtime in parallel with the .NET runtime. Since the
|
|
||||||
// Rust runtime needs some time to start, we have to wait for it to be ready.
|
|
||||||
//
|
|
||||||
const int MAX_TRIES = 160;
|
|
||||||
var tris = 0;
|
|
||||||
var wait4Try = TimeSpan.FromMilliseconds(250);
|
|
||||||
var url = new Uri($"https://127.0.0.1:{this.apiPort}/system/dotnet/port");
|
|
||||||
while (tris++ < MAX_TRIES)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Note II: We use a new HttpClient instance for each try to avoid
|
|
||||||
// .NET is caching the result. When we use the same HttpClient
|
|
||||||
// instance, we would always get the same result (403 forbidden),
|
|
||||||
// without even trying to connect to the Rust server.
|
|
||||||
//
|
|
||||||
|
|
||||||
using var initialHttp = new HttpClient(new HttpClientHandler
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Note III: We have to create also a new HttpClientHandler instance
|
|
||||||
// for each try to avoid .NET is caching the result. This is necessary
|
|
||||||
// because it gets disposed when the HttpClient instance gets disposed.
|
|
||||||
//
|
|
||||||
ServerCertificateCustomValidationCallback = (_, certificate, _, _) =>
|
|
||||||
{
|
|
||||||
if(certificate is null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var currentCertificateFingerprint = certificate.GetCertHashString(HashAlgorithmName.SHA256);
|
|
||||||
return currentCertificateFingerprint == this.certificateFingerprint;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
initialHttp.DefaultRequestVersion = Version.Parse("2.0");
|
|
||||||
initialHttp.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher;
|
|
||||||
initialHttp.DefaultRequestHeaders.AddApiToken();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = await initialHttp.GetAsync(url);
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Try {tris}/{MAX_TRIES} to get the app port from Rust runtime");
|
|
||||||
await Task.Delay(wait4Try);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var appPortContent = await response.Content.ReadAsStringAsync();
|
|
||||||
var appPort = int.Parse(appPortContent);
|
|
||||||
Console.WriteLine($"Received app port from Rust runtime: '{appPort}'");
|
|
||||||
return appPort;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Error: Was not able to get the app port from Rust runtime: '{e.Message}'");
|
|
||||||
Console.WriteLine(e.InnerException);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("Failed to receive the app port from Rust runtime.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task AppIsReady()
|
|
||||||
{
|
|
||||||
const string URL = "/system/dotnet/ready";
|
|
||||||
this.logger!.LogInformation("Notifying Rust runtime that the app is ready.");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = await this.http.GetAsync(URL);
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
this.logger!.LogError($"Failed to notify Rust runtime that the app is ready: '{response.StatusCode}'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
this.logger!.LogError(e, "Failed to notify the Rust runtime that the app is ready.");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> GetConfigDirectory()
|
|
||||||
{
|
|
||||||
var response = await this.http.GetAsync("/system/directories/config");
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
this.logger!.LogError($"Failed to get the config directory from Rust: '{response.StatusCode}'");
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await response.Content.ReadAsStringAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> GetDataDirectory()
|
|
||||||
{
|
|
||||||
var response = await this.http.GetAsync("/system/directories/data");
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
this.logger!.LogError($"Failed to get the data directory from Rust: '{response.StatusCode}'");
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await response.Content.ReadAsStringAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to copy the given text to the clipboard.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="snackbar">The snackbar to show the result.</param>
|
|
||||||
/// <param name="text">The text to copy to the clipboard.</param>
|
|
||||||
public async Task CopyText2Clipboard(ISnackbar snackbar, string text)
|
|
||||||
{
|
|
||||||
var message = "Successfully copied the text to your clipboard";
|
|
||||||
var iconColor = Color.Error;
|
|
||||||
var severity = Severity.Error;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var encryptedText = await text.Encrypt(this.encryptor!);
|
|
||||||
var response = await this.http.PostAsync("/clipboard/set", new StringContent(encryptedText.EncryptedData));
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
this.logger!.LogError($"Failed to copy the text to the clipboard due to an network error: '{response.StatusCode}'");
|
|
||||||
message = "Failed to copy the text to your clipboard.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var state = await response.Content.ReadFromJsonAsync<SetClipboardResponse>(this.jsonRustSerializerOptions);
|
|
||||||
if (!state.Success)
|
|
||||||
{
|
|
||||||
this.logger!.LogError("Failed to copy the text to the clipboard.");
|
|
||||||
message = "Failed to copy the text to your clipboard.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
iconColor = Color.Success;
|
|
||||||
severity = Severity.Success;
|
|
||||||
this.logger!.LogDebug("Successfully copied the text to the clipboard.");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
snackbar.Add(message, severity, config =>
|
|
||||||
{
|
|
||||||
config.Icon = Icons.Material.Filled.ContentCopy;
|
|
||||||
config.IconSize = Size.Large;
|
|
||||||
config.IconColor = iconColor;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<UpdateResponse> CheckForUpdate()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(45));
|
|
||||||
var response = await this.http.GetFromJsonAsync<UpdateResponse>("/updates/check", this.jsonRustSerializerOptions, cts.Token);
|
|
||||||
this.logger!.LogInformation($"Checked for an update: update available='{response.UpdateIsAvailable}'; error='{response.Error}'; next version='{response.NewVersion}'; changelog len='{response.Changelog.Length}'");
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
this.logger!.LogError(e, "Failed to check for an update.");
|
|
||||||
return new UpdateResponse
|
|
||||||
{
|
|
||||||
Error = true,
|
|
||||||
UpdateIsAvailable = false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task InstallUpdate()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var cts = new CancellationTokenSource();
|
|
||||||
await this.http.GetAsync("/updates/install", cts.Token);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Try to get the API key for the given secret ID.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="secretId">The secret ID to get the API key for.</param>
|
|
||||||
/// <param name="isTrying">Indicates if we are trying to get the API key. In that case, we don't log errors.</param>
|
|
||||||
/// <returns>The requested secret.</returns>
|
|
||||||
public async Task<RequestedSecret> GetAPIKey(ISecretId secretId, bool isTrying = false)
|
|
||||||
{
|
|
||||||
var secretRequest = new SelectSecretRequest($"provider::{secretId.SecretId}::{secretId.SecretName}::api_key", Environment.UserName, isTrying);
|
|
||||||
var result = await this.http.PostAsJsonAsync("/secrets/get", secretRequest, this.jsonRustSerializerOptions);
|
|
||||||
if (!result.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
if(!isTrying)
|
|
||||||
this.logger!.LogError($"Failed to get the API key for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
|
|
||||||
return new RequestedSecret(false, new EncryptedText(string.Empty), "Failed to get the API key due to an API issue.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var secret = await result.Content.ReadFromJsonAsync<RequestedSecret>(this.jsonRustSerializerOptions);
|
|
||||||
if (!secret.Success && !isTrying)
|
|
||||||
this.logger!.LogError($"Failed to get the API key for secret ID '{secretId.SecretId}': '{secret.Issue}'");
|
|
||||||
|
|
||||||
return secret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Try to store the API key for the given secret ID.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="secretId">The secret ID to store the API key for.</param>
|
|
||||||
/// <param name="key">The API key to store.</param>
|
|
||||||
/// <returns>The store secret response.</returns>
|
|
||||||
public async Task<StoreSecretResponse> SetAPIKey(ISecretId secretId, string key)
|
|
||||||
{
|
|
||||||
var encryptedKey = await this.encryptor!.Encrypt(key);
|
|
||||||
var request = new StoreSecretRequest($"provider::{secretId.SecretId}::{secretId.SecretName}::api_key", Environment.UserName, encryptedKey);
|
|
||||||
var result = await this.http.PostAsJsonAsync("/secrets/store", request, this.jsonRustSerializerOptions);
|
|
||||||
if (!result.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
this.logger!.LogError($"Failed to store the API key for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
|
|
||||||
return new StoreSecretResponse(false, "Failed to get the API key due to an API issue.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var state = await result.Content.ReadFromJsonAsync<StoreSecretResponse>(this.jsonRustSerializerOptions);
|
|
||||||
if (!state.Success)
|
|
||||||
this.logger!.LogError($"Failed to store the API key for secret ID '{secretId.SecretId}': '{state.Issue}'");
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to delete the API key for the given secret ID.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="secretId">The secret ID to delete the API key for.</param>
|
|
||||||
/// <returns>The delete secret response.</returns>
|
|
||||||
public async Task<DeleteSecretResponse> DeleteAPIKey(ISecretId secretId)
|
|
||||||
{
|
|
||||||
var request = new SelectSecretRequest($"provider::{secretId.SecretId}::{secretId.SecretName}::api_key", Environment.UserName, false);
|
|
||||||
var result = await this.http.PostAsJsonAsync("/secrets/delete", request, this.jsonRustSerializerOptions);
|
|
||||||
if (!result.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
this.logger!.LogError($"Failed to delete the API key for secret ID '{secretId.SecretId}' due to an API issue: '{result.StatusCode}'");
|
|
||||||
return new DeleteSecretResponse{Success = false, WasEntryFound = false, Issue = "Failed to delete the API key due to an API issue."};
|
|
||||||
}
|
|
||||||
|
|
||||||
var state = await result.Content.ReadFromJsonAsync<DeleteSecretResponse>(this.jsonRustSerializerOptions);
|
|
||||||
if (!state.Success)
|
|
||||||
this.logger!.LogError($"Failed to delete the API key for secret ID '{secretId.SecretId}': '{state.Issue}'");
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<DirectorySelectionResponse> SelectDirectory(string title, string? initialDirectory = null)
|
|
||||||
{
|
|
||||||
PreviousDirectory? previousDirectory = initialDirectory is null ? null : new (initialDirectory);
|
|
||||||
var result = await this.http.PostAsJsonAsync($"/select/directory?title={title}", previousDirectory, this.jsonRustSerializerOptions);
|
|
||||||
if (!result.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
this.logger!.LogError($"Failed to select a directory: '{result.StatusCode}'");
|
|
||||||
return new DirectorySelectionResponse(true, string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await result.Content.ReadFromJsonAsync<DirectorySelectionResponse>(this.jsonRustSerializerOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
using ERI_Client.V1;
|
||||||
|
|
||||||
|
namespace AIStudio.Tools.Validation;
|
||||||
|
|
||||||
|
public sealed class DataSourceValidation
|
||||||
|
{
|
||||||
|
public Func<string> GetSecretStorageIssue { get; init; } = () => string.Empty;
|
||||||
|
|
||||||
|
public Func<string> GetPreviousDataSourceName { get; init; } = () => string.Empty;
|
||||||
|
|
||||||
|
public Func<IEnumerable<string>> GetUsedDataSourceNames { get; init; } = () => [];
|
||||||
|
|
||||||
|
public Func<AuthMethod> GetAuthMethod { get; init; } = () => AuthMethod.NONE;
|
||||||
|
|
||||||
|
public Func<bool> GetSelectedCloudEmbedding { get; init; } = () => false;
|
||||||
|
|
||||||
|
public Func<bool> GetTestedConnection { get; init; } = () => false;
|
||||||
|
|
||||||
|
public Func<bool> GetTestedConnectionResult { get; init; } = () => false;
|
||||||
|
|
||||||
|
public Func<IReadOnlyList<AuthMethod>> GetAvailableAuthMethods { get; init; } = () => [];
|
||||||
|
|
||||||
|
public string? ValidatingHostname(string hostname)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(hostname))
|
||||||
|
return "Please enter a hostname, e.g., http://localhost:1234";
|
||||||
|
|
||||||
|
if(!hostname.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) && !hostname.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return "The hostname must start with either http:// or https://";
|
||||||
|
|
||||||
|
if(!Uri.TryCreate(hostname, UriKind.Absolute, out _))
|
||||||
|
return "The hostname is not a valid HTTP(S) URL.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidatePort(int port)
|
||||||
|
{
|
||||||
|
if(port is < 1 or > 65535)
|
||||||
|
return "The port must be between 1 and 65535.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidateUsername(string username)
|
||||||
|
{
|
||||||
|
if(this.GetAuthMethod() is not AuthMethod.USERNAME_PASSWORD)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(username))
|
||||||
|
return "The username must not be empty.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidatingSecret(string secret)
|
||||||
|
{
|
||||||
|
var authMethod = this.GetAuthMethod();
|
||||||
|
if(authMethod is AuthMethod.NONE or AuthMethod.KERBEROS)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var secretStorageIssue = this.GetSecretStorageIssue();
|
||||||
|
if(!string.IsNullOrWhiteSpace(secretStorageIssue))
|
||||||
|
return secretStorageIssue;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(secret))
|
||||||
|
return authMethod switch
|
||||||
|
{
|
||||||
|
AuthMethod.TOKEN => "Please enter your secure access token.",
|
||||||
|
AuthMethod.USERNAME_PASSWORD => "Please enter your password.",
|
||||||
|
|
||||||
|
_ => "Please enter the secret necessary for authentication."
|
||||||
|
};
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidatingName(string dataSourceName)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(dataSourceName))
|
||||||
|
return "The name must not be empty.";
|
||||||
|
|
||||||
|
if (dataSourceName.Length > 40)
|
||||||
|
return "The name must not exceed 40 characters.";
|
||||||
|
|
||||||
|
var lowerName = dataSourceName.ToLowerInvariant();
|
||||||
|
if(lowerName != this.GetPreviousDataSourceName() && this.GetUsedDataSourceNames().Contains(lowerName))
|
||||||
|
return "The name is already used by another data source. Please choose a different name.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidatePath(string path)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(path))
|
||||||
|
return "The path must not be empty. Please select a directory.";
|
||||||
|
|
||||||
|
if(!Directory.Exists(path))
|
||||||
|
return "The path does not exist. Please select a valid directory.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidateFilePath(string filePath)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(filePath))
|
||||||
|
return "The file path must not be empty. Please select a file.";
|
||||||
|
|
||||||
|
if(!File.Exists(filePath))
|
||||||
|
return "The file does not exist. Please select a valid file.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidateEmbeddingId(string embeddingId)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(embeddingId))
|
||||||
|
return "Please select an embedding provider.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidateUserAcknowledgedCloudEmbedding(bool value)
|
||||||
|
{
|
||||||
|
if(this.GetSelectedCloudEmbedding() && !value)
|
||||||
|
return "Please acknowledge that you are aware of the cloud embedding implications.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidateTestedConnection()
|
||||||
|
{
|
||||||
|
if(!this.GetTestedConnection())
|
||||||
|
return "Please test the connection before saving.";
|
||||||
|
|
||||||
|
if(!this.GetTestedConnectionResult())
|
||||||
|
return "The connection test failed. Please check the connection settings.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? ValidateAuthMethod(AuthMethod authMethod)
|
||||||
|
{
|
||||||
|
if(!this.GetAvailableAuthMethods().Contains(authMethod))
|
||||||
|
return "Please select one valid authentication method.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -205,8 +205,11 @@
|
|||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "0.16.9",
|
"resolved": "0.16.9",
|
||||||
"contentHash": "7WaVMHklpT3Ye2ragqRIwlFRsb6kOk63BOGADV0fan3ulVfGLUYkDi5yNUsZS/7FVNkWbtHAlDLmu4WnHGfqvQ=="
|
"contentHash": "7WaVMHklpT3Ye2ragqRIwlFRsb6kOk63BOGADV0fan3ulVfGLUYkDi5yNUsZS/7FVNkWbtHAlDLmu4WnHGfqvQ=="
|
||||||
|
},
|
||||||
|
"ericlientv1": {
|
||||||
|
"type": "Project"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"net8.0/osx-arm64": {}
|
"net8.0/osx-x64": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# v0.9.26, build 201 (2025-01-13 19:11 UTC)
|
||||||
|
- Added the ability to configure local and remote (ERI) data sources in the settings as a preview feature behind the RAG feature flag.
|
||||||
|
- Fixed the ERI server assistant to ask for confirmation before deleting a ERI server preset.
|
||||||
|
- Fixed a bug in the ERI server assistant that allowed an empty directory as a base directory for the code generation.
|
||||||
|
- Fixed the embedding dialog to store the selected embedding model when using LM Studio as host.
|
||||||
+5
-5
@@ -1,9 +1,9 @@
|
|||||||
0.9.25
|
0.9.26
|
||||||
2025-01-04 18:33:07 UTC
|
2025-01-13 19:11:57 UTC
|
||||||
200
|
201
|
||||||
8.0.111 (commit f3835a7fb4)
|
8.0.111 (commit f3835a7fb4)
|
||||||
8.0.11 (commit 9cb3b725e3)
|
8.0.11 (commit 9cb3b725e3)
|
||||||
1.83.0 (commit 90b35a623)
|
1.84.0 (commit 9fc6b4312)
|
||||||
7.15.0
|
7.15.0
|
||||||
1.8.1
|
1.8.1
|
||||||
e4b1ea32fb6, release
|
ae72c50236f, release
|
||||||
Generated
+1
-1
@@ -2319,7 +2319,7 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mindwork-ai-studio"
|
name = "mindwork-ai-studio"
|
||||||
version = "0.9.25"
|
version = "0.9.26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"arboard",
|
"arboard",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mindwork-ai-studio"
|
name = "mindwork-ai-studio"
|
||||||
version = "0.9.25"
|
version = "0.9.26"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "MindWork AI Studio"
|
description = "MindWork AI Studio"
|
||||||
authors = ["Thorsten Sommer"]
|
authors = ["Thorsten Sommer"]
|
||||||
|
|||||||
Loaded 100 of 103 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user