diff --git a/app/ERIClientV1/Client.Generated.cs b/app/ERIClientV1/Client.Generated.cs
deleted file mode 100644
index 96698e1..0000000
--- a/app/ERIClientV1/Client.Generated.cs
+++ /dev/null
@@ -1,1277 +0,0 @@
-//----------------------
-//
-// Generated using the NSwag toolchain v14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org)
-//
-//----------------------
-
-#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended."
-#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword."
-#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?'
-#pragma warning disable 612 // Disable "CS0612 '...' is obsolete"
-#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ...
-#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..."
-#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'"
-#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant"
-#pragma warning disable 8603 // Disable "CS8603 Possible null reference return"
-#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter"
-#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type"
-
-namespace ERI_Client.V1
-{
- using System = global::System;
-
- [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class Client
- {
- private System.Net.Http.HttpClient _httpClient;
- private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true);
-
- public Client(System.Net.Http.HttpClient httpClient)
- {
- _httpClient = httpClient;
- }
-
- private static System.Text.Json.JsonSerializerOptions CreateSerializerSettings()
- {
- var settings = new System.Text.Json.JsonSerializerOptions();
- UpdateJsonSerializerSettings(settings);
- return settings;
- }
-
- protected System.Text.Json.JsonSerializerOptions JsonSerializerSettings { get { return _settings.Value; } }
-
- static partial void UpdateJsonSerializerSettings(System.Text.Json.JsonSerializerOptions settings);
-
- partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url);
- partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
- partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response);
-
- ///
- /// Get the available authentication methods.
- ///
- /// OK
- /// A server side error occurred.
- public virtual System.Threading.Tasks.Task> GetAuthMethodsAsync()
- {
- return GetAuthMethodsAsync(System.Threading.CancellationToken.None);
- }
-
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- /// Get the available authentication methods.
- ///
- /// OK
- /// A server side error occurred.
- public virtual async System.Threading.Tasks.Task> GetAuthMethodsAsync(System.Threading.CancellationToken cancellationToken)
- {
- var client_ = _httpClient;
- var disposeClient_ = false;
- try
- {
- using (var request_ = new System.Net.Http.HttpRequestMessage())
- {
- request_.Method = new System.Net.Http.HttpMethod("GET");
- request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
-
- var urlBuilder_ = new System.Text.StringBuilder();
-
- // Operation Path: "auth/methods"
- urlBuilder_.Append("auth/methods");
-
- PrepareRequest(client_, request_, urlBuilder_);
-
- var url_ = urlBuilder_.ToString();
- request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
-
- PrepareRequest(client_, request_, url_);
-
- var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- var disposeResponse_ = true;
- try
- {
- var headers_ = new System.Collections.Generic.Dictionary>();
- foreach (var item_ in response_.Headers)
- headers_[item_.Key] = item_.Value;
- if (response_.Content != null && response_.Content.Headers != null)
- {
- foreach (var item_ in response_.Content.Headers)
- headers_[item_.Key] = item_.Value;
- }
-
- ProcessResponse(client_, response_);
-
- var status_ = (int)response_.StatusCode;
- if (status_ == 200)
- {
- var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false);
- if (objectResponse_.Object == null)
- {
- throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
- }
- return objectResponse_.Object;
- }
- else
- {
- var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
- }
- }
- finally
- {
- if (disposeResponse_)
- response_.Dispose();
- }
- }
- }
- finally
- {
- if (disposeClient_)
- client_.Dispose();
- }
- }
-
- ///
- /// Authenticate with the data source to get a token for further requests.
- ///
- /// OK
- /// A server side error occurred.
- public virtual System.Threading.Tasks.Task AuthenticateAsync(AuthMethod authMethod)
- {
- return AuthenticateAsync(authMethod, System.Threading.CancellationToken.None);
- }
-
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- /// Authenticate with the data source to get a token for further requests.
- ///
- /// OK
- /// A server side error occurred.
- public virtual async System.Threading.Tasks.Task AuthenticateAsync(AuthMethod authMethod, System.Threading.CancellationToken cancellationToken)
- {
- if (authMethod == null)
- throw new System.ArgumentNullException("authMethod");
-
- var client_ = _httpClient;
- var disposeClient_ = false;
- try
- {
- using (var request_ = new System.Net.Http.HttpRequestMessage())
- {
- request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
- request_.Method = new System.Net.Http.HttpMethod("POST");
- request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
-
- var urlBuilder_ = new System.Text.StringBuilder();
-
- // Operation Path: "auth"
- urlBuilder_.Append("auth");
- urlBuilder_.Append('?');
- urlBuilder_.Append(System.Uri.EscapeDataString("authMethod")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(authMethod, System.Globalization.CultureInfo.InvariantCulture))).Append('&');
- urlBuilder_.Length--;
-
- PrepareRequest(client_, request_, urlBuilder_);
-
- var url_ = urlBuilder_.ToString();
- request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
-
- PrepareRequest(client_, request_, url_);
-
- var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- var disposeResponse_ = true;
- try
- {
- var headers_ = new System.Collections.Generic.Dictionary>();
- foreach (var item_ in response_.Headers)
- headers_[item_.Key] = item_.Value;
- if (response_.Content != null && response_.Content.Headers != null)
- {
- foreach (var item_ in response_.Content.Headers)
- headers_[item_.Key] = item_.Value;
- }
-
- ProcessResponse(client_, response_);
-
- var status_ = (int)response_.StatusCode;
- if (status_ == 200)
- {
- var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false);
- if (objectResponse_.Object == null)
- {
- throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
- }
- return objectResponse_.Object;
- }
- else
- {
- var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
- }
- }
- finally
- {
- if (disposeResponse_)
- response_.Dispose();
- }
- }
- }
- finally
- {
- if (disposeClient_)
- client_.Dispose();
- }
- }
-
- ///
- /// Get information about the data source.
- ///
- /// OK
- /// A server side error occurred.
- public virtual System.Threading.Tasks.Task GetDataSourceInfoAsync()
- {
- return GetDataSourceInfoAsync(System.Threading.CancellationToken.None);
- }
-
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- /// Get information about the data source.
- ///
- /// OK
- /// A server side error occurred.
- public virtual async System.Threading.Tasks.Task GetDataSourceInfoAsync(System.Threading.CancellationToken cancellationToken)
- {
- var client_ = _httpClient;
- var disposeClient_ = false;
- try
- {
- using (var request_ = new System.Net.Http.HttpRequestMessage())
- {
- request_.Method = new System.Net.Http.HttpMethod("GET");
- request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
-
- var urlBuilder_ = new System.Text.StringBuilder();
-
- // Operation Path: "dataSource"
- urlBuilder_.Append("dataSource");
-
- PrepareRequest(client_, request_, urlBuilder_);
-
- var url_ = urlBuilder_.ToString();
- request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
-
- PrepareRequest(client_, request_, url_);
-
- var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- var disposeResponse_ = true;
- try
- {
- var headers_ = new System.Collections.Generic.Dictionary>();
- foreach (var item_ in response_.Headers)
- headers_[item_.Key] = item_.Value;
- if (response_.Content != null && response_.Content.Headers != null)
- {
- foreach (var item_ in response_.Content.Headers)
- headers_[item_.Key] = item_.Value;
- }
-
- ProcessResponse(client_, response_);
-
- var status_ = (int)response_.StatusCode;
- if (status_ == 200)
- {
- var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false);
- if (objectResponse_.Object == null)
- {
- throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
- }
- return objectResponse_.Object;
- }
- else
- {
- var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
- }
- }
- finally
- {
- if (disposeResponse_)
- response_.Dispose();
- }
- }
- }
- finally
- {
- if (disposeClient_)
- client_.Dispose();
- }
- }
-
- ///
- /// Get information about the used embedding(s).
- ///
- /// OK
- /// A server side error occurred.
- public virtual System.Threading.Tasks.Task> GetEmbeddingInfoAsync()
- {
- return GetEmbeddingInfoAsync(System.Threading.CancellationToken.None);
- }
-
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- /// Get information about the used embedding(s).
- ///
- /// OK
- /// A server side error occurred.
- public virtual async System.Threading.Tasks.Task> GetEmbeddingInfoAsync(System.Threading.CancellationToken cancellationToken)
- {
- var client_ = _httpClient;
- var disposeClient_ = false;
- try
- {
- using (var request_ = new System.Net.Http.HttpRequestMessage())
- {
- request_.Method = new System.Net.Http.HttpMethod("GET");
- request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
-
- var urlBuilder_ = new System.Text.StringBuilder();
-
- // Operation Path: "embedding/info"
- urlBuilder_.Append("embedding/info");
-
- PrepareRequest(client_, request_, urlBuilder_);
-
- var url_ = urlBuilder_.ToString();
- request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
-
- PrepareRequest(client_, request_, url_);
-
- var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- var disposeResponse_ = true;
- try
- {
- var headers_ = new System.Collections.Generic.Dictionary>();
- foreach (var item_ in response_.Headers)
- headers_[item_.Key] = item_.Value;
- if (response_.Content != null && response_.Content.Headers != null)
- {
- foreach (var item_ in response_.Content.Headers)
- headers_[item_.Key] = item_.Value;
- }
-
- ProcessResponse(client_, response_);
-
- var status_ = (int)response_.StatusCode;
- if (status_ == 200)
- {
- var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false);
- if (objectResponse_.Object == null)
- {
- throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
- }
- return objectResponse_.Object;
- }
- else
- {
- var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
- }
- }
- finally
- {
- if (disposeResponse_)
- response_.Dispose();
- }
- }
- }
- finally
- {
- if (disposeClient_)
- client_.Dispose();
- }
- }
-
- ///
- /// Get information about the retrieval processes implemented by this data source.
- ///
- /// OK
- /// A server side error occurred.
- public virtual System.Threading.Tasks.Task> GetRetrievalInfoAsync()
- {
- return GetRetrievalInfoAsync(System.Threading.CancellationToken.None);
- }
-
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- /// Get information about the retrieval processes implemented by this data source.
- ///
- /// OK
- /// A server side error occurred.
- public virtual async System.Threading.Tasks.Task> GetRetrievalInfoAsync(System.Threading.CancellationToken cancellationToken)
- {
- var client_ = _httpClient;
- var disposeClient_ = false;
- try
- {
- using (var request_ = new System.Net.Http.HttpRequestMessage())
- {
- request_.Method = new System.Net.Http.HttpMethod("GET");
- request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
-
- var urlBuilder_ = new System.Text.StringBuilder();
-
- // Operation Path: "retrieval/info"
- urlBuilder_.Append("retrieval/info");
-
- PrepareRequest(client_, request_, urlBuilder_);
-
- var url_ = urlBuilder_.ToString();
- request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
-
- PrepareRequest(client_, request_, url_);
-
- var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- var disposeResponse_ = true;
- try
- {
- var headers_ = new System.Collections.Generic.Dictionary>();
- foreach (var item_ in response_.Headers)
- headers_[item_.Key] = item_.Value;
- if (response_.Content != null && response_.Content.Headers != null)
- {
- foreach (var item_ in response_.Content.Headers)
- headers_[item_.Key] = item_.Value;
- }
-
- ProcessResponse(client_, response_);
-
- var status_ = (int)response_.StatusCode;
- if (status_ == 200)
- {
- var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false);
- if (objectResponse_.Object == null)
- {
- throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
- }
- return objectResponse_.Object;
- }
- else
- {
- var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
- }
- }
- finally
- {
- if (disposeResponse_)
- response_.Dispose();
- }
- }
- }
- finally
- {
- if (disposeClient_)
- client_.Dispose();
- }
- }
-
- ///
- /// Retrieve information from the data source.
- ///
- /// OK
- /// A server side error occurred.
- public virtual System.Threading.Tasks.Task> RetrieveAsync(RetrievalRequest body)
- {
- return RetrieveAsync(body, System.Threading.CancellationToken.None);
- }
-
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- /// Retrieve information from the data source.
- ///
- /// OK
- /// A server side error occurred.
- public virtual async System.Threading.Tasks.Task> RetrieveAsync(RetrievalRequest body, System.Threading.CancellationToken cancellationToken)
- {
- if (body == null)
- throw new System.ArgumentNullException("body");
-
- var client_ = _httpClient;
- var disposeClient_ = false;
- try
- {
- using (var request_ = new System.Net.Http.HttpRequestMessage())
- {
- var json_ = System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(body, _settings.Value);
- var content_ = new System.Net.Http.ByteArrayContent(json_);
- content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
- request_.Content = content_;
- request_.Method = new System.Net.Http.HttpMethod("POST");
- request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
-
- var urlBuilder_ = new System.Text.StringBuilder();
-
- // Operation Path: "retrieval"
- urlBuilder_.Append("retrieval");
-
- PrepareRequest(client_, request_, urlBuilder_);
-
- var url_ = urlBuilder_.ToString();
- request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
-
- PrepareRequest(client_, request_, url_);
-
- var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- var disposeResponse_ = true;
- try
- {
- var headers_ = new System.Collections.Generic.Dictionary>();
- foreach (var item_ in response_.Headers)
- headers_[item_.Key] = item_.Value;
- if (response_.Content != null && response_.Content.Headers != null)
- {
- foreach (var item_ in response_.Content.Headers)
- headers_[item_.Key] = item_.Value;
- }
-
- ProcessResponse(client_, response_);
-
- var status_ = (int)response_.StatusCode;
- if (status_ == 200)
- {
- var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false);
- if (objectResponse_.Object == null)
- {
- throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
- }
- return objectResponse_.Object;
- }
- else
- {
- var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
- }
- }
- finally
- {
- if (disposeResponse_)
- response_.Dispose();
- }
- }
- }
- finally
- {
- if (disposeClient_)
- client_.Dispose();
- }
- }
-
- ///
- /// Get the security requirements for this data source.
- ///
- /// OK
- /// A server side error occurred.
- public virtual System.Threading.Tasks.Task GetSecurityRequirementsAsync()
- {
- return GetSecurityRequirementsAsync(System.Threading.CancellationToken.None);
- }
-
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- /// Get the security requirements for this data source.
- ///
- /// OK
- /// A server side error occurred.
- public virtual async System.Threading.Tasks.Task GetSecurityRequirementsAsync(System.Threading.CancellationToken cancellationToken)
- {
- var client_ = _httpClient;
- var disposeClient_ = false;
- try
- {
- using (var request_ = new System.Net.Http.HttpRequestMessage())
- {
- request_.Method = new System.Net.Http.HttpMethod("GET");
- request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
-
- var urlBuilder_ = new System.Text.StringBuilder();
-
- // Operation Path: "security/requirements"
- urlBuilder_.Append("security/requirements");
-
- PrepareRequest(client_, request_, urlBuilder_);
-
- var url_ = urlBuilder_.ToString();
- request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
-
- PrepareRequest(client_, request_, url_);
-
- var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- var disposeResponse_ = true;
- try
- {
- var headers_ = new System.Collections.Generic.Dictionary>();
- foreach (var item_ in response_.Headers)
- headers_[item_.Key] = item_.Value;
- if (response_.Content != null && response_.Content.Headers != null)
- {
- foreach (var item_ in response_.Content.Headers)
- headers_[item_.Key] = item_.Value;
- }
-
- ProcessResponse(client_, response_);
-
- var status_ = (int)response_.StatusCode;
- if (status_ == 200)
- {
- var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false);
- if (objectResponse_.Object == null)
- {
- throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
- }
- return objectResponse_.Object;
- }
- else
- {
- var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
- }
- }
- finally
- {
- if (disposeResponse_)
- response_.Dispose();
- }
- }
- }
- finally
- {
- if (disposeClient_)
- client_.Dispose();
- }
- }
-
- protected struct ObjectResponseResult
- {
- public ObjectResponseResult(T responseObject, string responseText)
- {
- this.Object = responseObject;
- this.Text = responseText;
- }
-
- public T Object { get; }
-
- public string Text { get; }
- }
-
- public bool ReadResponseAsString { get; set; }
-
- protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Threading.CancellationToken cancellationToken)
- {
- if (response == null || response.Content == null)
- {
- return new ObjectResponseResult(default(T), string.Empty);
- }
-
- if (ReadResponseAsString)
- {
- var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
- try
- {
- var typedBody = System.Text.Json.JsonSerializer.Deserialize(responseText, JsonSerializerSettings);
- return new ObjectResponseResult(typedBody, responseText);
- }
- catch (System.Text.Json.JsonException exception)
- {
- var message = "Could not deserialize the response body string as " + typeof(T).FullName + ".";
- throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception);
- }
- }
- else
- {
- try
- {
- using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
- {
- var typedBody = await System.Text.Json.JsonSerializer.DeserializeAsync(responseStream, JsonSerializerSettings, cancellationToken).ConfigureAwait(false);
- return new ObjectResponseResult(typedBody, string.Empty);
- }
- }
- catch (System.Text.Json.JsonException exception)
- {
- var message = "Could not deserialize the response body stream as " + typeof(T).FullName + ".";
- throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception);
- }
- }
- }
-
- private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo)
- {
- if (value == null)
- {
- return "";
- }
-
- if (value is System.Enum)
- {
- var name = System.Enum.GetName(value.GetType(), value);
- if (name != null)
- {
- var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name);
- if (field != null)
- {
- var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute))
- as System.Runtime.Serialization.EnumMemberAttribute;
- if (attribute != null)
- {
- return attribute.Value != null ? attribute.Value : name;
- }
- }
-
- var converted = System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo));
- return converted == null ? string.Empty : converted;
- }
- }
- else if (value is bool)
- {
- return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant();
- }
- else if (value is byte[])
- {
- return System.Convert.ToBase64String((byte[]) value);
- }
- else if (value is string[])
- {
- return string.Join(",", (string[])value);
- }
- else if (value.GetType().IsArray)
- {
- var valueArray = (System.Array)value;
- var valueTextArray = new string[valueArray.Length];
- for (var i = 0; i < valueArray.Length; i++)
- {
- valueTextArray[i] = ConvertToString(valueArray.GetValue(i), cultureInfo);
- }
- return string.Join(",", valueTextArray);
- }
-
- var result = System.Convert.ToString(value, cultureInfo);
- return result == null ? "" : result;
- }
- }
-
- ///
- /// An authentication field.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public enum AuthField
- {
-
- [System.Runtime.Serialization.EnumMember(Value = @"NONE")]
- NONE = 0,
-
- [System.Runtime.Serialization.EnumMember(Value = @"USERNAME")]
- USERNAME = 1,
-
- [System.Runtime.Serialization.EnumMember(Value = @"PASSWORD")]
- PASSWORD = 2,
-
- [System.Runtime.Serialization.EnumMember(Value = @"TOKEN")]
- TOKEN = 3,
-
- [System.Runtime.Serialization.EnumMember(Value = @"KERBEROS_TICKET")]
- KERBEROS_TICKET = 4,
-
- }
-
- ///
- /// The mapping between an AuthField and the field name in the authentication request.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class AuthFieldMapping
- {
-
- [System.Text.Json.Serialization.JsonPropertyName("authField")]
- [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
- public AuthField AuthField { get; set; }
-
- ///
- /// The field name in the authentication request.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("fieldName")]
- public string FieldName { get; set; }
-
- }
-
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public enum AuthMethod
- {
-
- [System.Runtime.Serialization.EnumMember(Value = @"NONE")]
- NONE = 0,
-
- [System.Runtime.Serialization.EnumMember(Value = @"KERBEROS")]
- KERBEROS = 1,
-
- [System.Runtime.Serialization.EnumMember(Value = @"USERNAME_PASSWORD")]
- USERNAME_PASSWORD = 2,
-
- [System.Runtime.Serialization.EnumMember(Value = @"TOKEN")]
- TOKEN = 3,
-
- }
-
- ///
- /// The response to an authentication request.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class AuthResponse
- {
- ///
- /// True, when the authentication was successful.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("success")]
- public bool Success { get; set; }
-
- ///
- /// The token to use for further requests.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("token")]
- public string Token { get; set; }
-
- ///
- /// When the authentication was not successful, this contains the reason.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("message")]
- public string Message { get; set; }
-
- }
-
- ///
- /// Describes one authentication scheme for this data source.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class AuthScheme
- {
-
- [System.Text.Json.Serialization.JsonPropertyName("authMethod")]
- [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
- public AuthMethod AuthMethod { get; set; }
-
- ///
- /// A list of field mappings for the authentication method. The client must know,
- ///
e.g., how the password field is named in the request.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("authFieldMappings")]
- public System.Collections.Generic.ICollection AuthFieldMappings { get; set; }
-
- }
-
- ///
- /// A chat thread, which is a list of content blocks.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class ChatThread
- {
- ///
- /// The content blocks in this chat thread.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("contentBlocks")]
- public System.Collections.Generic.ICollection ContentBlocks { get; set; }
-
- }
-
- ///
- /// A block of content of a chat thread.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class ContentBlock
- {
- ///
- /// The content of the block. Remember that images and other media are base64 encoded.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("content")]
- public string Content { get; set; }
-
- [System.Text.Json.Serialization.JsonPropertyName("role")]
- [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
- public Role Role { get; set; }
-
- [System.Text.Json.Serialization.JsonPropertyName("type")]
- [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
- public ContentType Type { get; set; }
-
- }
-
- ///
- /// The type of content.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public enum ContentType
- {
-
- [System.Runtime.Serialization.EnumMember(Value = @"NONE")]
- NONE = 0,
-
- [System.Runtime.Serialization.EnumMember(Value = @"UNKNOWN")]
- UNKNOWN = 1,
-
- [System.Runtime.Serialization.EnumMember(Value = @"TEXT")]
- TEXT = 2,
-
- [System.Runtime.Serialization.EnumMember(Value = @"IMAGE")]
- IMAGE = 3,
-
- [System.Runtime.Serialization.EnumMember(Value = @"VIDEO")]
- VIDEO = 4,
-
- [System.Runtime.Serialization.EnumMember(Value = @"AUDIO")]
- AUDIO = 5,
-
- [System.Runtime.Serialization.EnumMember(Value = @"SPEECH")]
- SPEECH = 6,
-
- }
-
- ///
- /// Matching context returned by the data source as a result of a retrieval request.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class Context
- {
- ///
- /// The name of the source, e.g., a document name, database name,
- ///
collection name, etc.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("name")]
- public string Name { get; set; }
-
- ///
- /// What are the contents of the source? For example, is it a
- ///
dictionary, a book chapter, business concept, a paper, etc.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("category")]
- public string Category { get; set; }
-
- ///
- /// The path to the content, e.g., a URL, a file path, a path in a
- ///
graph database, etc.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("path")]
- public string Path { get; set; }
-
- [System.Text.Json.Serialization.JsonPropertyName("type")]
- [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
- public ContentType Type { get; set; }
-
- ///
- /// The content that matched the user prompt. For text, you
- ///
return the matched text and, e.g., three words before and after it.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("matchedContent")]
- public string MatchedContent { get; set; }
-
- ///
- /// The surrounding content of the matched content.
- ///
For text, you may return, e.g., one sentence or paragraph before and after
- ///
the matched content.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("surroundingContent")]
- public System.Collections.Generic.ICollection SurroundingContent { get; set; }
-
- ///
- /// Links to related content, e.g., links to Wikipedia articles,
- ///
links to sources, etc.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("links")]
- public System.Collections.Generic.ICollection Links { get; set; }
-
- }
-
- ///
- /// Information about the data source.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class DataSourceInfo
- {
- ///
- /// The name of the data source, e.g., "Internal Organization Documents."
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("name")]
- public string Name { get; set; }
-
- ///
- /// A short description of the data source. What kind of data does it contain?
- ///
What is the data source used for?
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("description")]
- public string Description { get; set; }
-
- }
-
- ///
- /// Represents information about the used embedding for this data source. The purpose of this information is to give the
- ///
interested user an idea of what kind of embedding is used and what it does.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class EmbeddingInfo
- {
- ///
- /// What kind of embedding is used. For example, "Transformer Embedding," "Contextual Word
- ///
Embedding," "Graph Embedding," etc.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("embeddingType")]
- public string EmbeddingType { get; set; }
-
- ///
- /// Name the embedding used. This can be a library, a framework, or the name of the used
- ///
algorithm.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("embeddingName")]
- public string EmbeddingName { get; set; }
-
- ///
- /// A short description of the embedding. Describe what the embedding is doing.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("description")]
- public string Description { get; set; }
-
- ///
- /// Describe when the embedding is used. For example, when the user prompt contains certain
- ///
keywords, or anytime?
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("usedWhen")]
- public string UsedWhen { get; set; }
-
- ///
- /// A link to the embedding's documentation or the source code. Might be null.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("link")]
- public string Link { get; set; }
-
- }
-
- ///
- /// Known types of providers that can process data.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public enum ProviderType
- {
-
- [System.Runtime.Serialization.EnumMember(Value = @"NONE")]
- NONE = 0,
-
- [System.Runtime.Serialization.EnumMember(Value = @"ANY")]
- ANY = 1,
-
- [System.Runtime.Serialization.EnumMember(Value = @"SELF_HOSTED")]
- SELF_HOSTED = 2,
-
- }
-
- ///
- /// Information about a retrieval process, which this data source implements.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class RetrievalInfo
- {
- ///
- /// A unique identifier for the retrieval process. This can be a GUID, a unique name, or an increasing integer.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("id")]
- public string Id { get; set; }
-
- ///
- /// The name of the retrieval process, e.g., "Keyword-Based Wikipedia Article Retrieval".
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("name")]
- public string Name { get; set; }
-
- ///
- /// A short description of the retrieval process. What kind of retrieval process is it?
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("description")]
- public string Description { get; set; }
-
- ///
- /// A link to the retrieval process's documentation, paper, Wikipedia article, or the source code. Might be null.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("link")]
- public string Link { get; set; }
-
- ///
- /// A dictionary that describes the parameters of the retrieval process. The key is the parameter name,
- ///
and the value is a description of the parameter. Although each parameter will be sent as a string, the description should indicate the
- ///
expected type and range, e.g., 0.0 to 1.0 for a float parameter.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("parametersDescription")]
- public System.Collections.Generic.IDictionary ParametersDescription { get; set; }
-
- ///
- /// A list of embeddings used in this retrieval process. It might be empty in case no embedding is used.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("embeddings")]
- public System.Collections.Generic.ICollection Embeddings { get; set; }
-
- }
-
- ///
- /// The retrieval request sent by AI Studio.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class RetrievalRequest
- {
- ///
- /// The latest user prompt that AI Studio received.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("latestUserPrompt")]
- public string LatestUserPrompt { get; set; }
-
- [System.Text.Json.Serialization.JsonPropertyName("latestUserPromptType")]
- [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
- public ContentType LatestUserPromptType { get; set; }
-
- [System.Text.Json.Serialization.JsonPropertyName("thread")]
- public ChatThread Thread { get; set; }
-
- ///
- /// Optional. The ID of the retrieval process that the data source should use.
- ///
When null, the data source chooses an appropriate retrieval process. Selecting a retrieval process is optional
- ///
for AI Studio users. Most users do not specify a retrieval process.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("retrievalProcessId")]
- public string RetrievalProcessId { get; set; }
-
- ///
- /// A dictionary of parameters that the data source should use for the retrieval process.
- ///
Although each parameter will be sent as a string, the retrieval process specifies the expected type and range.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("parameters")]
- public System.Collections.Generic.IDictionary Parameters { get; set; }
-
- ///
- /// The maximum number of matches that the data source should return. AI Studio uses
- ///
any value below 1 to indicate that the data source should return as many matches as appropriate.
- ///
-
- [System.Text.Json.Serialization.JsonPropertyName("maxMatches")]
- public int MaxMatches { get; set; }
-
- }
-
- ///
- /// Possible roles of any chat thread.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public enum Role
- {
-
- [System.Runtime.Serialization.EnumMember(Value = @"NONE")]
- NONE = 0,
-
- [System.Runtime.Serialization.EnumMember(Value = @"UNKNOW")]
- UNKNOW = 1,
-
- [System.Runtime.Serialization.EnumMember(Value = @"SYSTEM")]
- SYSTEM = 2,
-
- [System.Runtime.Serialization.EnumMember(Value = @"USER")]
- USER = 3,
-
- [System.Runtime.Serialization.EnumMember(Value = @"AI")]
- AI = 4,
-
- [System.Runtime.Serialization.EnumMember(Value = @"AGENT")]
- AGENT = 5,
-
- }
-
- ///
- /// Represents the security requirements for this data source.
- ///
- [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class SecurityRequirements
- {
-
- [System.Text.Json.Serialization.JsonPropertyName("allowedProviderType")]
- [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
- public ProviderType AllowedProviderType { get; set; }
-
- }
-
-
-
- [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class ApiException : System.Exception
- {
- public int StatusCode { get; private set; }
-
- public string Response { get; private set; }
-
- public System.Collections.Generic.IReadOnlyDictionary> Headers { get; private set; }
-
- public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Exception innerException)
- : base(message + "\n\nStatus: " + statusCode + "\nResponse: \n" + ((response == null) ? "(null)" : response.Substring(0, response.Length >= 512 ? 512 : response.Length)), innerException)
- {
- StatusCode = statusCode;
- Response = response;
- Headers = headers;
- }
-
- public override string ToString()
- {
- return string.Format("HTTP Response: \n\n{0}\n\n{1}", Response, base.ToString());
- }
- }
-
- [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
- public partial class ApiException : ApiException
- {
- public TResult Result { get; private set; }
-
- public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary> headers, TResult result, System.Exception innerException)
- : base(message, statusCode, response, headers, innerException)
- {
- Result = result;
- }
- }
-
-}
-
-#pragma warning restore 108
-#pragma warning restore 114
-#pragma warning restore 472
-#pragma warning restore 612
-#pragma warning restore 1573
-#pragma warning restore 1591
-#pragma warning restore 8073
-#pragma warning restore 3016
-#pragma warning restore 8603
-#pragma warning restore 8604
-#pragma warning restore 8625
\ No newline at end of file
diff --git a/app/ERIClientV1/ERIClientV1.csproj b/app/ERIClientV1/ERIClientV1.csproj
deleted file mode 100644
index 8ca0662..0000000
--- a/app/ERIClientV1/ERIClientV1.csproj
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
- net8.0
- latest
- enable
- enable
-
-
-
diff --git a/app/MindWork AI Studio.sln b/app/MindWork AI Studio.sln
index 6bf20b2..ef02b51 100644
--- a/app/MindWork AI Studio.sln
+++ b/app/MindWork AI Studio.sln
@@ -2,10 +2,6 @@
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}"
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
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -16,12 +12,7 @@ Global
{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.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
EndGlobal
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelDataSources.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelDataSources.razor.cs
index 41daae9..53aced4 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelDataSources.razor.cs
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelDataSources.razor.cs
@@ -1,8 +1,7 @@
using AIStudio.Dialogs;
using AIStudio.Settings;
using AIStudio.Settings.DataModel;
-
-using ERI_Client.V1;
+using AIStudio.Tools.ERIClient.DataModel;
using Microsoft.AspNetCore.Components;
diff --git a/app/MindWork AI Studio/MindWork AI Studio.csproj b/app/MindWork AI Studio/MindWork AI Studio.csproj
index ccc96df..0d6fc28 100644
--- a/app/MindWork AI Studio/MindWork AI Studio.csproj
+++ b/app/MindWork AI Studio/MindWork AI Studio.csproj
@@ -53,10 +53,6 @@
-
-
-
-
diff --git a/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs b/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs
index 387accf..acf49ec 100644
--- a/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs
+++ b/app/MindWork AI Studio/Settings/DataModel/DataSourceERI_V1.cs
@@ -1,6 +1,7 @@
-using ERI_Client.V1;
-
// ReSharper disable InconsistentNaming
+
+using AIStudio.Tools.ERIClient.DataModel;
+
namespace AIStudio.Settings.DataModel;
///
diff --git a/app/MindWork AI Studio/Settings/IERIDataSource.cs b/app/MindWork AI Studio/Settings/IERIDataSource.cs
index 34874fc..42cd3f7 100644
--- a/app/MindWork AI Studio/Settings/IERIDataSource.cs
+++ b/app/MindWork AI Studio/Settings/IERIDataSource.cs
@@ -1,4 +1,4 @@
-using ERI_Client.V1;
+using AIStudio.Tools.ERIClient.DataModel;
namespace AIStudio.Settings;
diff --git a/app/MindWork AI Studio/Tools/AuthMethodsV1Extensions.cs b/app/MindWork AI Studio/Tools/AuthMethodsV1Extensions.cs
index e26a20b..4d11017 100644
--- a/app/MindWork AI Studio/Tools/AuthMethodsV1Extensions.cs
+++ b/app/MindWork AI Studio/Tools/AuthMethodsV1Extensions.cs
@@ -1,4 +1,4 @@
-using ERI_Client.V1;
+using AIStudio.Tools.ERIClient.DataModel;
namespace AIStudio.Tools;
diff --git a/app/MindWork AI Studio/Tools/ERIClient/APIResponse.cs b/app/MindWork AI Studio/Tools/ERIClient/APIResponse.cs
new file mode 100644
index 0000000..1f82914
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/APIResponse.cs
@@ -0,0 +1,19 @@
+namespace AIStudio.Tools.ERIClient;
+
+public sealed class APIResponse
+{
+ ///
+ /// Was the API call successful?
+ ///
+ public bool Successful { get; set; }
+
+ ///
+ /// When the API call was not successful, this will contain the error message.
+ ///
+ public string Message { get; set; } = string.Empty;
+
+ ///
+ /// The data returned by the API call.
+ ///
+ public T? Data { get; set; }
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthField.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthField.cs
new file mode 100644
index 0000000..8972743
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthField.cs
@@ -0,0 +1,13 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// An authentication field.
+///
+public enum AuthField
+{
+ NONE,
+ USERNAME,
+ PASSWORD,
+ TOKEN,
+ KERBEROS_TICKET,
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthFieldMapping.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthFieldMapping.cs
new file mode 100644
index 0000000..e11c3d9
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthFieldMapping.cs
@@ -0,0 +1,8 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// The mapping between an AuthField and the field name in the authentication request.
+///
+/// The AuthField that is mapped to the field name.
+/// The field name in the authentication request.
+public record AuthFieldMapping(AuthField AuthField, string FieldName);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthMethod.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthMethod.cs
new file mode 100644
index 0000000..7494ce9
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthMethod.cs
@@ -0,0 +1,9 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+public enum AuthMethod
+{
+ NONE,
+ KERBEROS,
+ USERNAME_PASSWORD,
+ TOKEN,
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthResponse.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthResponse.cs
new file mode 100644
index 0000000..cdc325d
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthResponse.cs
@@ -0,0 +1,9 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// The response to an authentication request.
+///
+/// True, when the authentication was successful.
+/// The token to use for further requests.
+/// When the authentication was not successful, this contains the reason.
+public readonly record struct AuthResponse(bool Success, string? Token, string? Message);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthScheme.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthScheme.cs
new file mode 100644
index 0000000..bde0175
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/AuthScheme.cs
@@ -0,0 +1,9 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// Describes one authentication scheme for this data source.
+///
+/// The method used for authentication, e.g., "API Key," "Username/Password," etc.
+/// A list of field mappings for the authentication method. The client must know,
+/// e.g., how the password field is named in the request.
+public readonly record struct AuthScheme(AuthMethod AuthMethod, List AuthFieldMappings);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/ChatThread.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/ChatThread.cs
new file mode 100644
index 0000000..8d6a098
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/ChatThread.cs
@@ -0,0 +1,7 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// A chat thread, which is a list of content blocks.
+///
+/// The content blocks in this chat thread.
+public readonly record struct ChatThread(List ContentBlocks);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/ContentBlock.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/ContentBlock.cs
new file mode 100644
index 0000000..0a46d3b
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/ContentBlock.cs
@@ -0,0 +1,12 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// A block of content of a chat thread.
+///
+///
+/// Images and other media are base64 encoded.
+///
+/// The content of the block. Remember that images and other media are base64 encoded.
+/// The role of the content in the chat thread.
+/// The type of the content, e.g., text, image, video, etc.
+public readonly record struct ContentBlock(string Content, Role Role, ContentType Type);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/ContentType.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/ContentType.cs
new file mode 100644
index 0000000..1420372
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/ContentType.cs
@@ -0,0 +1,16 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// The type of content.
+///
+public enum ContentType
+{
+ NONE,
+ UNKNOWN,
+
+ TEXT,
+ IMAGE,
+ VIDEO,
+ AUDIO,
+ SPEECH,
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/Context.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/Context.cs
new file mode 100644
index 0000000..fb5c13f
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/Context.cs
@@ -0,0 +1,27 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// Matching context returned by the data source as a result of a retrieval request.
+///
+/// The name of the source, e.g., a document name, database name,
+/// collection name, etc.
+/// What are the contents of the source? For example, is it a
+/// dictionary, a book chapter, business concept, a paper, etc.
+/// The path to the content, e.g., a URL, a file path, a path in a
+/// graph database, etc.
+/// The type of the content, e.g., text, image, video, audio, speech, etc.
+/// The content that matched the user prompt. For text, you
+/// return the matched text and, e.g., three words before and after it.
+/// The surrounding content of the matched content.
+/// For text, you may return, e.g., one sentence or paragraph before and after
+/// the matched content.
+/// Links to related content, e.g., links to Wikipedia articles,
+/// links to sources, etc.
+public readonly record struct Context(
+ string Name,
+ string Category,
+ string? Path,
+ ContentType Type,
+ string MatchedContent,
+ string[] SurroundingContent,
+ string[] Links);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/DataSourceInfo.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/DataSourceInfo.cs
new file mode 100644
index 0000000..07a8f92
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/DataSourceInfo.cs
@@ -0,0 +1,9 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// Information about the data source.
+///
+/// The name of the data source, e.g., "Internal Organization Documents."
+/// A short description of the data source. What kind of data does it contain?
+/// What is the data source used for?
+public readonly record struct DataSourceInfo(string Name, string Description);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/EmbeddingInfo.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/EmbeddingInfo.cs
new file mode 100644
index 0000000..4728512
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/EmbeddingInfo.cs
@@ -0,0 +1,20 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// Represents information about the used embedding for this data source. The purpose of this information is to give the
+/// interested user an idea of what kind of embedding is used and what it does.
+///
+/// What kind of embedding is used. For example, "Transformer Embedding," "Contextual Word
+/// Embedding," "Graph Embedding," etc.
+/// Name the embedding used. This can be a library, a framework, or the name of the used
+/// algorithm.
+/// A short description of the embedding. Describe what the embedding is doing.
+/// Describe when the embedding is used. For example, when the user prompt contains certain
+/// keywords, or anytime?
+/// A link to the embedding's documentation or the source code. Might be null.
+public readonly record struct EmbeddingInfo(
+ string EmbeddingType,
+ string EmbeddingName,
+ string Description,
+ string UsedWhen,
+ string? Link);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/ProviderType.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/ProviderType.cs
new file mode 100644
index 0000000..008811f
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/ProviderType.cs
@@ -0,0 +1,22 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// Known types of providers that can process data.
+///
+public enum ProviderType
+{
+ ///
+ /// The related data is not allowed to be sent to any provider.
+ ///
+ NONE,
+
+ ///
+ /// The related data can be sent to any provider.
+ ///
+ ANY,
+
+ ///
+ /// The related data can be sent to a provider that is hosted by the same organization, either on-premises or locally.
+ ///
+ SELF_HOSTED,
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/RetrievalInfo.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/RetrievalInfo.cs
new file mode 100644
index 0000000..cdd71a6
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/RetrievalInfo.cs
@@ -0,0 +1,20 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// Information about a retrieval process, which this data source implements.
+///
+/// A unique identifier for the retrieval process. This can be a GUID, a unique name, or an increasing integer.
+/// The name of the retrieval process, e.g., "Keyword-Based Wikipedia Article Retrieval".
+/// A short description of the retrieval process. What kind of retrieval process is it?
+/// A link to the retrieval process's documentation, paper, Wikipedia article, or the source code. Might be null.
+/// A dictionary that describes the parameters of the retrieval process. The key is the parameter name,
+/// and the value is a description of the parameter. Although each parameter will be sent as a string, the description should indicate the
+/// expected type and range, e.g., 0.0 to 1.0 for a float parameter.
+/// A list of embeddings used in this retrieval process. It might be empty in case no embedding is used.
+public readonly record struct RetrievalInfo(
+ string Id,
+ string Name,
+ string Description,
+ string? Link,
+ Dictionary? ParametersDescription,
+ List Embeddings);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/RetrievalRequest.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/RetrievalRequest.cs
new file mode 100644
index 0000000..abeac50
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/RetrievalRequest.cs
@@ -0,0 +1,25 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// The retrieval request sent by AI Studio.
+///
+///
+/// Images and other media are base64 encoded.
+///
+/// The latest user prompt that AI Studio received.
+/// The type of the latest user prompt, e.g., text, image, etc.
+/// The chat thread that the user is currently in.
+/// Optional. The ID of the retrieval process that the data source should use.
+/// When null, the data source chooses an appropriate retrieval process. Selecting a retrieval process is optional
+/// for AI Studio users. Most users do not specify a retrieval process.
+/// A dictionary of parameters that the data source should use for the retrieval process.
+/// Although each parameter will be sent as a string, the retrieval process specifies the expected type and range.
+/// The maximum number of matches that the data source should return. AI Studio uses
+/// any value below 1 to indicate that the data source should return as many matches as appropriate.
+public readonly record struct RetrievalRequest(
+ string LatestUserPrompt,
+ ContentType LatestUserPromptType,
+ ChatThread Thread,
+ string? RetrievalProcessId,
+ Dictionary? Parameters,
+ int MaxMatches);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/Role.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/Role.cs
new file mode 100644
index 0000000..f19376f
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/Role.cs
@@ -0,0 +1,15 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// Possible roles of any chat thread.
+///
+public enum Role
+{
+ NONE,
+ UNKNOW,
+
+ SYSTEM,
+ USER,
+ AI,
+ AGENT,
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/DataModel/SecurityRequirements.cs b/app/MindWork AI Studio/Tools/ERIClient/DataModel/SecurityRequirements.cs
new file mode 100644
index 0000000..aa4df1f
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/DataModel/SecurityRequirements.cs
@@ -0,0 +1,7 @@
+namespace AIStudio.Tools.ERIClient.DataModel;
+
+///
+/// Represents the security requirements for this data source.
+///
+/// Which provider types are allowed to process the data?
+public readonly record struct SecurityRequirements(ProviderType AllowedProviderType);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs b/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs
new file mode 100644
index 0000000..66882a1
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/ERIClientBase.cs
@@ -0,0 +1,36 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace AIStudio.Tools.ERIClient;
+
+public abstract class ERIClientBase(string baseAddress) : IDisposable
+{
+ protected static readonly JsonSerializerOptions JSON_OPTIONS = new()
+ {
+ WriteIndented = true,
+ AllowTrailingCommas = true,
+ PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
+ DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
+ PropertyNameCaseInsensitive = true,
+ Converters =
+ {
+ new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseUpper),
+ }
+ };
+
+ protected readonly HttpClient httpClient = new()
+ {
+ BaseAddress = new Uri(baseAddress),
+ };
+
+ protected string securityToken = string.Empty;
+
+ #region Implementation of IDisposable
+
+ public void Dispose()
+ {
+ this.httpClient.Dispose();
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/ERIClientFactory.cs b/app/MindWork AI Studio/Tools/ERIClient/ERIClientFactory.cs
new file mode 100644
index 0000000..2858164
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/ERIClientFactory.cs
@@ -0,0 +1,14 @@
+using AIStudio.Assistants.ERI;
+using AIStudio.Settings;
+
+namespace AIStudio.Tools.ERIClient;
+
+public static class ERIClientFactory
+{
+ public static IERIClient? Get(ERIVersion version, IERIDataSource dataSource) => version switch
+ {
+ ERIVersion.V1 => new ERIClientV1($"{dataSource.Hostname}:{dataSource.Port}"),
+
+ _ => null
+ };
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs b/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs
new file mode 100644
index 0000000..62e3f55
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/ERIClientV1.cs
@@ -0,0 +1,344 @@
+using System.Text;
+using System.Text.Json;
+
+using AIStudio.Settings;
+using AIStudio.Tools.ERIClient.DataModel;
+
+namespace AIStudio.Tools.ERIClient;
+
+public class ERIClientV1(string baseAddress) : ERIClientBase(baseAddress), IERIClient
+{
+ #region Implementation of IERIClient
+
+ public async Task>> GetAuthMethodsAsync(CancellationToken cancellationToken = default)
+ {
+ using var response = await this.httpClient.GetAsync("/auth/methods", cancellationToken);
+ if(!response.IsSuccessStatusCode)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = $"Failed to retrieve the authentication methods: there was an issue communicating with the ERI server. Code: {response.StatusCode}, Reason: {response.ReasonPhrase}"
+ };
+ }
+
+ var authMethods = await response.Content.ReadFromJsonAsync>(JSON_OPTIONS, cancellationToken);
+ if(authMethods is null)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to retrieve the authentication methods: the ERI server did not return a valid response."
+ };
+ }
+
+ return new()
+ {
+ Successful = true,
+ Data = authMethods
+ };
+ }
+
+ public async Task> AuthenticateAsync(IERIDataSource dataSource, RustService rustService, CancellationToken cancellationToken = default)
+ {
+ var authMethod = dataSource.AuthMethod;
+ var username = dataSource.Username;
+ switch (dataSource.AuthMethod)
+ {
+ case AuthMethod.NONE:
+ using (var request = new HttpRequestMessage(HttpMethod.Post, $"auth?authMethod={authMethod}"))
+ {
+ using var noneAuthResponse = await this.httpClient.SendAsync(request, cancellationToken);
+ if(!noneAuthResponse.IsSuccessStatusCode)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = $"Failed to authenticate with the ERI server. Code: {noneAuthResponse.StatusCode}, Reason: {noneAuthResponse.ReasonPhrase}"
+ };
+ }
+
+ var noneAuthResult = await noneAuthResponse.Content.ReadFromJsonAsync(JSON_OPTIONS, cancellationToken);
+ if(noneAuthResult == default)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to authenticate with the ERI server: the response was invalid."
+ };
+ }
+
+ this.securityToken = noneAuthResult.Token ?? string.Empty;
+ return new()
+ {
+ Successful = true,
+ Data = noneAuthResult
+ };
+ }
+
+ case AuthMethod.USERNAME_PASSWORD:
+ var passwordResponse = await rustService.GetSecret(dataSource);
+ if (!passwordResponse.Success)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to retrieve the password."
+ };
+ }
+
+ var password = await passwordResponse.Secret.Decrypt(Program.ENCRYPTION);
+ using (var request = new HttpRequestMessage(HttpMethod.Post, $"auth?authMethod={authMethod}"))
+ {
+ // We must send both values inside the header. The username field is named 'user'.
+ // The password field is named 'password'.
+ request.Headers.Add("user", username);
+ request.Headers.Add("password", password);
+
+ using var usernamePasswordAuthResponse = await this.httpClient.SendAsync(request, cancellationToken);
+ if(!usernamePasswordAuthResponse.IsSuccessStatusCode)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = $"Failed to authenticate with the ERI server. Code: {usernamePasswordAuthResponse.StatusCode}, Reason: {usernamePasswordAuthResponse.ReasonPhrase}"
+ };
+ }
+
+ var usernamePasswordAuthResult = await usernamePasswordAuthResponse.Content.ReadFromJsonAsync(JSON_OPTIONS, cancellationToken);
+ if(usernamePasswordAuthResult == default)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to authenticate with the server: the response was invalid."
+ };
+ }
+
+ this.securityToken = usernamePasswordAuthResult.Token ?? string.Empty;
+ return new()
+ {
+ Successful = true,
+ Data = usernamePasswordAuthResult
+ };
+ }
+
+ case AuthMethod.TOKEN:
+ var tokenResponse = await rustService.GetSecret(dataSource);
+ if (!tokenResponse.Success)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to retrieve the access token."
+ };
+ }
+
+ var token = await tokenResponse.Secret.Decrypt(Program.ENCRYPTION);
+ using (var request = new HttpRequestMessage(HttpMethod.Post, $"auth?authMethod={authMethod}"))
+ {
+ request.Headers.Add("Authorization", $"Bearer {token}");
+
+ using var tokenAuthResponse = await this.httpClient.SendAsync(request, cancellationToken);
+ if(!tokenAuthResponse.IsSuccessStatusCode)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = $"Failed to authenticate with the ERI server. Code: {tokenAuthResponse.StatusCode}, Reason: {tokenAuthResponse.ReasonPhrase}"
+ };
+ }
+
+ var tokenAuthResult = await tokenAuthResponse.Content.ReadFromJsonAsync(JSON_OPTIONS, cancellationToken);
+ if(tokenAuthResult == default)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to authenticate with the ERI server: the response was invalid."
+ };
+ }
+
+ this.securityToken = tokenAuthResult.Token ?? string.Empty;
+ return new()
+ {
+ Successful = true,
+ Data = tokenAuthResult
+ };
+ }
+
+ default:
+ this.securityToken = string.Empty;
+ return new()
+ {
+ Successful = false,
+ Message = "The authentication method is not supported yet."
+ };
+ }
+ }
+
+ public async Task> GetDataSourceInfoAsync(CancellationToken cancellationToken = default)
+ {
+ using var request = new HttpRequestMessage(HttpMethod.Get, "/dataSource");
+ request.Headers.Add("token", this.securityToken);
+
+ using var response = await this.httpClient.SendAsync(request, cancellationToken);
+ if(!response.IsSuccessStatusCode)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = $"Failed to retrieve the data source information: there was an issue communicating with the ERI server. Code: {response.StatusCode}, Reason: {response.ReasonPhrase}"
+ };
+ }
+
+ var dataSourceInfo = await response.Content.ReadFromJsonAsync(JSON_OPTIONS, cancellationToken);
+ if(dataSourceInfo == default)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to retrieve the data source information: the ERI server did not return a valid response."
+ };
+ }
+
+ return new()
+ {
+ Successful = true,
+ Data = dataSourceInfo
+ };
+ }
+
+ public async Task>> GetEmbeddingInfoAsync(CancellationToken cancellationToken = default)
+ {
+ using var request = new HttpRequestMessage(HttpMethod.Get, "/embedding/info");
+ request.Headers.Add("token", this.securityToken);
+
+ using var response = await this.httpClient.SendAsync(request, cancellationToken);
+ if(!response.IsSuccessStatusCode)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = $"Failed to retrieve the embedding information: there was an issue communicating with the ERI server. Code: {response.StatusCode}, Reason: {response.ReasonPhrase}"
+ };
+ }
+
+ var embeddingInfo = await response.Content.ReadFromJsonAsync>(JSON_OPTIONS, cancellationToken);
+ if(embeddingInfo is null)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to retrieve the embedding information: the ERI server did not return a valid response."
+ };
+ }
+
+ return new()
+ {
+ Successful = true,
+ Data = embeddingInfo
+ };
+ }
+
+ public async Task>> GetRetrievalInfoAsync(CancellationToken cancellationToken = default)
+ {
+ using var request = new HttpRequestMessage(HttpMethod.Get, "/retrieval/info");
+ request.Headers.Add("token", this.securityToken);
+
+ using var response = await this.httpClient.SendAsync(request, cancellationToken);
+ if(!response.IsSuccessStatusCode)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = $"Failed to retrieve the retrieval information: there was an issue communicating with the ERI server. Code: {response.StatusCode}, Reason: {response.ReasonPhrase}"
+ };
+ }
+
+ var retrievalInfo = await response.Content.ReadFromJsonAsync>(JSON_OPTIONS, cancellationToken);
+ if(retrievalInfo is null)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to retrieve the retrieval information: the ERI server did not return a valid response."
+ };
+ }
+
+ return new()
+ {
+ Successful = true,
+ Data = retrievalInfo
+ };
+ }
+
+ public async Task>> ExecuteRetrievalAsync(RetrievalRequest request, CancellationToken cancellationToken = default)
+ {
+ using var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/retrieval");
+ requestMessage.Headers.Add("token", this.securityToken);
+
+ using var content = new StringContent(JsonSerializer.Serialize(request, JSON_OPTIONS), Encoding.UTF8, "application/json");
+ requestMessage.Content = content;
+
+ using var response = await this.httpClient.SendAsync(requestMessage, cancellationToken);
+ if(!response.IsSuccessStatusCode)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = $"Failed to execute the retrieval request: there was an issue communicating with the ERI server. Code: {response.StatusCode}, Reason: {response.ReasonPhrase}"
+ };
+ }
+
+ var contexts = await response.Content.ReadFromJsonAsync>(JSON_OPTIONS, cancellationToken);
+ if(contexts is null)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to execute the retrieval request: the ERI server did not return a valid response."
+ };
+ }
+
+ return new()
+ {
+ Successful = true,
+ Data = contexts
+ };
+ }
+
+ public async Task> GetSecurityRequirementsAsync(CancellationToken cancellationToken = default)
+ {
+ using var request = new HttpRequestMessage(HttpMethod.Get, "/security/requirements");
+ request.Headers.Add("token", this.securityToken);
+
+ using var response = await this.httpClient.SendAsync(request, cancellationToken);
+ if(!response.IsSuccessStatusCode)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = $"Failed to retrieve the security requirements: there was an issue communicating with the ERI server. Code: {response.StatusCode}, Reason: {response.ReasonPhrase}"
+ };
+ }
+
+ var securityRequirements = await response.Content.ReadFromJsonAsync(JSON_OPTIONS, cancellationToken);
+ if(securityRequirements == default)
+ {
+ return new()
+ {
+ Successful = false,
+ Message = "Failed to retrieve the security requirements: the ERI server did not return a valid response."
+ };
+ }
+
+ return new()
+ {
+ Successful = true,
+ Data = securityRequirements
+ };
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ERIClient/IERIClient.cs b/app/MindWork AI Studio/Tools/ERIClient/IERIClient.cs
new file mode 100644
index 0000000..9cf27fb
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ERIClient/IERIClient.cs
@@ -0,0 +1,62 @@
+using AIStudio.Settings;
+using AIStudio.Tools.ERIClient.DataModel;
+
+namespace AIStudio.Tools.ERIClient;
+
+public interface IERIClient : IDisposable
+{
+ ///
+ /// Retrieves the available authentication methods from the ERI server.
+ ///
+ ///
+ /// No authentication is required to retrieve the available authentication methods.
+ ///
+ /// The cancellation token.
+ /// The available authentication methods.
+ public Task>> GetAuthMethodsAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Authenticate the user to the ERI server.
+ ///
+ /// The data source to use.
+ /// The Rust service.
+ /// The cancellation token.
+ /// The authentication response.
+ public Task> AuthenticateAsync(IERIDataSource dataSource, RustService rustService, CancellationToken cancellationToken = default);
+
+ ///
+ /// Retrieves the data source information from the ERI server.
+ ///
+ /// The cancellation token.
+ /// The data source information.
+ public Task> GetDataSourceInfoAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Retrieves the embedding information from the ERI server.
+ ///
+ /// The cancellation token.
+ /// A list of embedding information.
+ public Task>> GetEmbeddingInfoAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Retrieves the retrieval information from the ERI server.
+ ///
+ /// The cancellation token.
+ /// A list of retrieval information.
+ public Task>> GetRetrievalInfoAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// Executes a retrieval request on the ERI server.
+ ///
+ /// The retrieval request.
+ /// The cancellation token.
+ /// The retrieved contexts to use for augmentation and generation.
+ public Task>> ExecuteRetrievalAsync(RetrievalRequest request, CancellationToken cancellationToken = default);
+
+ ///
+ /// Retrieves the security requirements from the ERI server.
+ ///
+ /// The cancellation token.
+ /// The security requirements.
+ public Task> GetSecurityRequirementsAsync(CancellationToken cancellationToken = default);
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/Validation/DataSourceValidation.cs b/app/MindWork AI Studio/Tools/Validation/DataSourceValidation.cs
index f55f906..cdd2f13 100644
--- a/app/MindWork AI Studio/Tools/Validation/DataSourceValidation.cs
+++ b/app/MindWork AI Studio/Tools/Validation/DataSourceValidation.cs
@@ -1,4 +1,4 @@
-using ERI_Client.V1;
+using AIStudio.Tools.ERIClient.DataModel;
namespace AIStudio.Tools.Validation;
diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.28.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.28.md
index a833761..29875ad 100644
--- a/app/MindWork AI Studio/wwwroot/changelog/v0.9.28.md
+++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.28.md
@@ -1,3 +1,4 @@
# v0.9.28, build 203 (2025-0x-xx xx:xx UTC)
- Added an information view to all data sources to the data source configuration page. The data source configuration is a preview feature behind the RAG feature flag.
+- Added a ERI ((E)xternal (R)etrieval (I)nterface) client for communication with any ERI server.
- Improved the resource handling when loading models.
\ No newline at end of file