From 0e390f078313bca4892e1175238cdee60ad9df8a Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 9 Feb 2025 12:31:49 +0100 Subject: [PATCH] Implemented the ERI v1 info dialog --- .../SettingsPanelDataSources.razor.cs | 9 + .../Dialogs/DataSourceERI-V1InfoDialog.razor | 101 ++++++++++ .../DataSourceERI-V1InfoDialog.razor.cs | 178 ++++++++++++++++++ 3 files changed, 288 insertions(+) create mode 100644 app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor create mode 100644 app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor.cs diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelDataSources.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelDataSources.razor.cs index 53aced4b..6f7e74b8 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelDataSources.razor.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelDataSources.razor.cs @@ -236,6 +236,15 @@ public partial class SettingsPanelDataSources : SettingsPanelBase await this.DialogService.ShowAsync("Local Directory Data Source Information", localDirectoryDialogParameters, DialogOptions.FULLSCREEN); break; + + case DataSourceERI_V1 eriV1DataSource: + var eriV1DialogParameters = new DialogParameters + { + { x => x.DataSource, eriV1DataSource }, + }; + + await this.DialogService.ShowAsync("ERI v1 Data Source Information", eriV1DialogParameters, DialogOptions.FULLSCREEN); + break; } } diff --git a/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor b/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor new file mode 100644 index 00000000..a1ebe82d --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor @@ -0,0 +1,101 @@ +@using AIStudio.Tools.ERIClient.DataModel + + + + + Common data source information + + + + + + + @if (!this.IsConnectionEncrypted()) + { + + 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. + + } + + @if (this.DataSource.AuthMethod is AuthMethod.USERNAME_PASSWORD) + { + + } + + + + + + Retrieval information + + @if (!this.retrievalInfoformation.Any()) + { + + The data source does not provide any retrieval information. + + } + else + { + + @for (var index = 0; index < this.retrievalInfoformation.Count; index++) + { + var info = this.retrievalInfoformation[index]; + + + + + @if (!string.IsNullOrWhiteSpace(info.Link)) + { + + Open web link, show more information + + } + + + Embeddings + + @if (!info.Embeddings.Any()) + { + + The data source does not provide any embedding information. + + } + else + { + + @for (var embeddingIndex = 0; embeddingIndex < info.Embeddings.Count; embeddingIndex++) + { + var embedding = info.Embeddings[embeddingIndex]; + + + + + + @if (!string.IsNullOrWhiteSpace(embedding.Link)) + { + + Open web link, show more information + + } + + } + + } + + } + + } + + + + + @if (this.IsOperationInProgress) + { + + } + Reload + Close + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor.cs b/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor.cs new file mode 100644 index 00000000..304c4f67 --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/DataSourceERI-V1InfoDialog.razor.cs @@ -0,0 +1,178 @@ +// ReSharper disable InconsistentNaming + +using System.Text; + +using AIStudio.Assistants.ERI; +using AIStudio.Settings.DataModel; +using AIStudio.Tools.ERIClient; +using AIStudio.Tools.ERIClient.DataModel; + +using Microsoft.AspNetCore.Components; + +using RetrievalInfo = AIStudio.Tools.ERIClient.DataModel.RetrievalInfo; + +namespace AIStudio.Dialogs; + +public partial class DataSourceERI_V1InfoDialog : ComponentBase, IAsyncDisposable, ISecretId +{ + [CascadingParameter] + private MudDialogInstance MudDialog { get; set; } = null!; + + [Parameter] + public DataSourceERI_V1 DataSource { get; set; } + + [Inject] + private RustService RustService { get; init; } = null!; + + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + this.eriServerTasks.Add(this.GetERIMetadata()); + await base.OnInitializedAsync(); + } + + #endregion + + private readonly CancellationTokenSource cts = new(); + private readonly List eriServerTasks = new(); + private readonly List dataIssues = []; + + private string serverDescription = string.Empty; + private ProviderType securityRequirements = ProviderType.NONE; + private IReadOnlyList retrievalInfoformation = []; + + private bool IsOperationInProgress { get; set; } = true; + + private bool IsConnectionEncrypted() => this.DataSource.Hostname.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase); + + private string Port => this.DataSource.Port == 0 ? string.Empty : $"{this.DataSource.Port}"; + + private string RetrievalName(RetrievalInfo retrievalInfo) + { + var hasId = !string.IsNullOrWhiteSpace(retrievalInfo.Id); + var hasName = !string.IsNullOrWhiteSpace(retrievalInfo.Name); + + if (hasId && hasName) + return $"[{retrievalInfo.Id}] {retrievalInfo.Name}"; + + if (hasId) + return $"[{retrievalInfo.Id}] Unnamed retrieval process"; + + return hasName ? retrievalInfo.Name : "Unnamed retrieval process"; + } + + private string RetrievalParameters(RetrievalInfo retrievalInfo) + { + var parameters = retrievalInfo.ParametersDescription; + if (parameters is null || parameters.Count == 0) + return "This retrieval process has no parameters."; + + var sb = new StringBuilder(); + foreach (var (paramName, description) in parameters) + { + sb.Append("Parameter: "); + sb.AppendLine(paramName); + sb.AppendLine(description); + sb.AppendLine(); + } + + return sb.ToString(); + } + + private async Task GetERIMetadata() + { + this.dataIssues.Clear(); + + try + { + this.IsOperationInProgress = true; + this.StateHasChanged(); + + using var client = ERIClientFactory.Get(ERIVersion.V1, this.DataSource); + if(client is null) + { + this.dataIssues.Add("Failed to connect to the ERI v1 server. The server is not supported."); + return; + } + + var loginResult = await client.AuthenticateAsync(this.DataSource, this.RustService); + if (!loginResult.Successful) + { + this.dataIssues.Add(loginResult.Message); + return; + } + + var dataSourceInfo = await client.GetDataSourceInfoAsync(this.cts.Token); + if (!dataSourceInfo.Successful) + { + this.dataIssues.Add(dataSourceInfo.Message); + return; + } + + this.serverDescription = dataSourceInfo.Data.Description; + + var securityRequirementsResult = await client.GetSecurityRequirementsAsync(this.cts.Token); + if (!securityRequirementsResult.Successful) + { + this.dataIssues.Add(securityRequirementsResult.Message); + return; + } + + this.securityRequirements = securityRequirementsResult.Data.AllowedProviderType; + + var retrievalInfoResult = await client.GetRetrievalInfoAsync(this.cts.Token); + if (!retrievalInfoResult.Successful) + { + this.dataIssues.Add(retrievalInfoResult.Message); + return; + } + + this.retrievalInfoformation = retrievalInfoResult.Data ?? []; + + this.StateHasChanged(); + } + catch (Exception e) + { + this.dataIssues.Add($"Failed to connect to the ERI v1 server. The message was: {e.Message}"); + } + finally + { + this.IsOperationInProgress = false; + this.StateHasChanged(); + } + } + + private void Close() + { + this.cts.Cancel(); + this.MudDialog.Close(); + } + + #region Implementation of ISecretId + + public string SecretId => this.DataSource.Id; + + public string SecretName => this.DataSource.Name; + + #endregion + + #region Implementation of IDisposable + + public async ValueTask DisposeAsync() + { + try + { + await this.cts.CancelAsync(); + await Task.WhenAll(this.eriServerTasks); + + this.cts.Dispose(); + } + catch + { + // ignored + } + } + + #endregion +} \ No newline at end of file