diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
index b288b48f..d8d0d94d 100644
--- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
+++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
@@ -9538,6 +9538,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2929232062"] = "Copies the confi
-- Copies the root certificate fingerprint to the clipboard
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2989678330"] = "Copies the root certificate fingerprint to the clipboard"
+-- Local RAG index
+UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2990297806"] = "Local RAG index"
+
-- The toml crate parses the embedded prompt-injection phrase catalog when the runtime starts. This keeps the detection rules separate from the Rust implementation and easier to maintain.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2999154325"] = "The toml crate parses the embedded prompt-injection phrase catalog when the runtime starts. This keeps the detection rules separate from the Rust implementation and easier to maintain."
@@ -9700,6 +9703,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T4058524336"] = "Allowed hosts: n
-- This library is used by the Rust runtime to read the current user's username, e.g. when an organization-managed ERI server uses the OS username for authentication.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T4060906280"] = "This library is used by the Rust runtime to read the current user's username, e.g. when an organization-managed ERI server uses the OS username for authentication."
+-- Local RAG index version
+UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T4061134614"] = "Local RAG index version"
+
-- This library is used to create asynchronous streams in Rust. It allows us to work with streams of data that can be produced asynchronously, making it easier to handle events or data that arrive over time. We use this, e.g., to stream arbitrary data from the file system to the embedding system.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T4079152443"] = "This library is used to create asynchronous streams in Rust. It allows us to work with streams of data that can be produced asynchronously, making it easier to handle events or data that arrive over time. We use this, e.g., to stream arbitrary data from the file system to the embedding system."
@@ -10699,33 +10705,96 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T10
-- Starting
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T1233211769"] = "Starting"
+-- unknown
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T2608177081"] = "unknown"
+
+-- Native library path
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T3089048804"] = "Native library path"
+
-- Unavailable
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T3662391977"] = "Unavailable"
+-- Process architecture
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T563161633"] = "Process architecture"
+
-- Status
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T6222351"] = "Status"
+-- Native library
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::NOINDEXSTORECLIENT::T634426545"] = "Native library"
+
+-- no migration applied
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1014567907"] = "no migration applied"
+
-- Database path
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1100578143"] = "Database path"
-- Storage size
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1230141403"] = "Storage size"
+-- Full-text search (FTS5)
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1396060361"] = "Full-text search (FTS5)"
+
+-- Wrapper version
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1469427584"] = "Wrapper version"
+
+-- available
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1727918744"] = "available"
+
+-- not determined
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T1959939977"] = "not determined"
+
-- Indexed files
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2235289713"] = "Indexed files"
+-- {0} ({1} applied)
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2286846332"] = "{0} ({1} applied)"
+
-- Search chunks
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2333737457"] = "Search chunks"
+-- Journal mode
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2411639995"] = "Journal mode"
+
+-- unknown
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T2608177081"] = "unknown"
+
+-- Native library path
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3089048804"] = "Native library path"
+
+-- Database tables
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3279078157"] = "Database tables"
+
-- Indexed data sources
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3524534748"] = "Indexed data sources"
-- Reported version
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3556099842"] = "Reported version"
+-- not available
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3574465749"] = "not available"
+
-- Permanently skipped files
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T3965853089"] = "Permanently skipped files"
+-- Library source ID
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T4168112546"] = "Library source ID"
+
+-- Schema version
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T424290830"] = "Schema version"
+
+-- Process architecture
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T563161633"] = "Process architecture"
+
+-- Native library
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T634426545"] = "Native library"
+
+-- System architecture
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T818259255"] = "System architecture"
+
+-- {0} ({1} applied, {2} pending)
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::INDEXSTORE::SQLITEINDEXSTORECLIENTIMPLEMENTATION::T983802795"] = "{0} ({1} applied, {2} pending)"
+
-- Reason
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::NODATABASECLIENT::T1093747001"] = "Reason"
@@ -10750,6 +10819,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::NOVECTORSTORECLIENT::T
-- Storage size
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T1230141403"] = "Storage size"
+-- unknown
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T2608177081"] = "unknown"
+
-- Number of vector stores
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T2785004838"] = "Number of vector stores"
@@ -10759,6 +10831,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEM
-- Status
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T6222351"] = "Status"
+-- Stored vectors
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T701689894"] = "Stored vectors"
+
-- Qdrant Edge is not available.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::DATABASES::VECTORSTORE::QDRANTEDGECLIENTIMPLEMENTATION::T744445696"] = "Qdrant Edge is not available."
diff --git a/app/MindWork AI Studio/Pages/Information.razor b/app/MindWork AI Studio/Pages/Information.razor
index c7b52ee7..aa81ecb9 100644
--- a/app/MindWork AI Studio/Pages/Information.razor
+++ b/app/MindWork AI Studio/Pages/Information.razor
@@ -22,25 +22,40 @@
- @this.VersionVectorStore
+ @this.DatabaseHeaderText(this.vectorStoreSection)
-
+
- @foreach (var item in this.vectorStoreDisplayInfo)
+ @foreach (var item in this.BuildDatabaseInfoItems(this.vectorStoreSection))
{
-
-
- @item.Label: @item.Value
-
-
+
}
-
- @(this.showVectorStoreDetails ? T("Hide Details") : T("Show Details"))
+ OnClick="@(() => this.ToggleDatabaseDetails(this.vectorStoreSection))">
+ @(this.vectorStoreSection.ShowDetails ? T("Hide Details") : T("Show Details"))
+
+
+
+
+ @this.DatabaseHeaderText(this.indexStoreSection)
+
+
+
+ @foreach (var item in this.BuildDatabaseInfoItems(this.indexStoreSection))
+ {
+
+ }
+
+
+
+ @(this.indexStoreSection.ShowDetails ? T("Hide Details") : T("Show Details"))
diff --git a/app/MindWork AI Studio/Pages/Information.razor.cs b/app/MindWork AI Studio/Pages/Information.razor.cs
index a1614c8b..6ae81bab 100644
--- a/app/MindWork AI Studio/Pages/Information.razor.cs
+++ b/app/MindWork AI Studio/Pages/Information.razor.cs
@@ -4,7 +4,6 @@ using AIStudio.Components;
using AIStudio.Dialogs;
using AIStudio.Settings.DataModel;
using AIStudio.Tools.Databases;
-using AIStudio.Tools.Databases.VectorStore;
using AIStudio.Tools.Metadata;
using AIStudio.Tools.PluginSystem;
using AIStudio.Tools.Rust;
@@ -98,22 +97,40 @@ public partial class Information : MSGComponentBase
private string VersionPdfium => $"{T("Used PDFium version")}: v{META_DATA_LIBRARIES.PdfiumVersion}";
- private string VersionVectorStore
+ ///
+ /// Builds the headline of one database block.
+ ///
+ ///
+ /// The vector store names the version from the build metadata, which is what this page always
+ /// showed. The index store names the one its client read from the running database instead:
+ /// there, which SQLite build actually got loaded is the whole point of showing it.
+ ///
+ private string DatabaseHeaderText(DatabaseSection section)
{
- get
+ var (nameLabel, versionLabel) = section.Role switch
{
- if (this.vectorStore is null)
- return $"{T("Vector store")}: {T("checking availability")}";
+ DatabaseRole.VECTOR_STORE => (T("Vector store"), T("Vector store version")),
+ _ => (T("Local RAG index"), T("Local RAG index version"))
+ };
- return this.vectorStore.Status switch
- {
- DatabaseClientStatus.AVAILABLE => $"{T("Vector store version")}: {this.vectorStore.Name} v{META_DATA_VECTOR_STORE.VectorStoreVersion}",
- DatabaseClientStatus.STARTING => $"{T("Vector store")}: {this.vectorStore.Name} - {T("starting")}",
- _ => $"{T("Vector store")}: {this.vectorStore.Name} - {T("not available")}"
- };
- }
+ if (section.Client is null)
+ return $"{nameLabel}: {T("checking availability")}";
+
+ var version = section.Role switch
+ {
+ DatabaseRole.VECTOR_STORE => META_DATA_VECTOR_STORE.VectorStoreVersion,
+ _ => section.Client.Version
+ };
+
+ return section.Client.Status switch
+ {
+ DatabaseClientStatus.AVAILABLE when !string.IsNullOrWhiteSpace(version) => $"{versionLabel}: {section.Client.Name} v{version}",
+ DatabaseClientStatus.AVAILABLE => $"{nameLabel}: {section.Client.Name}",
+ DatabaseClientStatus.STARTING => $"{nameLabel}: {section.Client.Name} - {T("starting")}",
+ _ => $"{nameLabel}: {section.Client.Name} - {T("not available")}"
+ };
}
-
+
private string versionPandoc = TB("Determine Pandoc version, please wait...");
private PandocInstallation pandocInstallation;
@@ -121,7 +138,6 @@ public partial class Information : MSGComponentBase
private bool showEnterpriseConfigDetails;
- private bool showVectorStoreDetails;
private bool showExternalHttpCustomRootCertificateDetails;
private List configPlugins = [];
@@ -141,10 +157,30 @@ public partial class Information : MSGComponentBase
private sealed record MandatoryInfoPanelData(string HeaderText, string PluginName, DataMandatoryInfo Info, DataMandatoryInfoAcceptance? Acceptance);
- private sealed record VectorStoreDisplayInfo(string Label, string Value);
- private readonly List vectorStoreDisplayInfo = new();
- private DatabaseClient? vectorStore;
- private CancellationTokenSource? vectorStoreRefreshCancellationTokenSource;
+ private sealed record DatabaseDisplayInfo(string Label, string Value);
+
+ ///
+ /// Everything one database block on this page needs to show itself.
+ ///
+ ///
+ /// Both blocks work the same way, so they share their state and their methods and differ only
+ /// in their role. Whoever adds a third database adds one field here, not another set of methods.
+ ///
+ private sealed class DatabaseSection(DatabaseRole role)
+ {
+ public DatabaseRole Role => role;
+
+ public DatabaseClient? Client { get; set; }
+
+ public bool ShowDetails { get; set; }
+
+ public List DisplayInfo { get; } = [];
+
+ public CancellationTokenSource? RefreshCancellationTokenSource { get; set; }
+ }
+
+ private readonly DatabaseSection vectorStoreSection = new(DatabaseRole.VECTOR_STORE);
+ private readonly DatabaseSection indexStoreSection = new(DatabaseRole.INDEX_STORE);
private bool HasAnyActiveEnvironment => this.enterpriseEnvironments.Any(e => e.IsActive);
@@ -191,9 +227,16 @@ public partial class Information : MSGComponentBase
this.updatePolicyMode = this.UpdatePolicy.CurrentMode;
this.logPaths = await this.RustService.GetLogPaths();
- await this.RefreshVectorStoreInfo(CancellationToken.None);
- if (this.vectorStore?.Status is DatabaseClientStatus.STARTING)
- this.StartShortVectorStoreRefreshLoop();
+ // The index store goes first: the vector store asks it for the number of stored vectors,
+ // and this way that client is already cached when it does.
+ await this.RefreshDatabaseInfo(this.indexStoreSection, CancellationToken.None);
+ await this.RefreshDatabaseInfo(this.vectorStoreSection, CancellationToken.None);
+
+ if (this.indexStoreSection.Client?.Status is DatabaseClientStatus.STARTING)
+ this.StartShortDatabaseRefreshLoop(this.indexStoreSection);
+
+ if (this.vectorStoreSection.Client?.Status is DatabaseClientStatus.STARTING)
+ this.StartShortDatabaseRefreshLoop(this.vectorStoreSection);
// Determine the Pandoc version may take some time, so we start it here
// without waiting for the result:
@@ -301,22 +344,31 @@ public partial class Information : MSGComponentBase
this.showExternalHttpCustomRootCertificateDetails = !this.showExternalHttpCustomRootCertificateDetails;
}
- private void ToggleVectorStoreDetails()
+ private void ToggleDatabaseDetails(DatabaseSection section)
{
- this.showVectorStoreDetails = !this.showVectorStoreDetails;
+ section.ShowDetails = !section.ShowDetails;
}
- private async Task RefreshVectorStoreInfo(CancellationToken cancellationToken)
+ private IReadOnlyList BuildDatabaseInfoItems(DatabaseSection section) => section.DisplayInfo
+ .Select((item, index) => new ConfigInfoRowItem(
+ Icons.Material.Filled.ArrowRightAlt,
+ $"{item.Label}: {item.Value}",
+ item.Value,
+ $"{T("Copies the following to the clipboard")}: {item.Value}",
+ index == 0 ? string.Empty : "margin-top: 4px;"))
+ .ToList();
+
+ private async Task RefreshDatabaseInfo(DatabaseSection section, CancellationToken cancellationToken)
{
- var refreshedClient = await this.DatabaseClientProvider.RefreshClientAsync(DatabaseRole.VECTOR_STORE, cancellationToken);
- this.vectorStore = refreshedClient;
- this.vectorStoreDisplayInfo.Clear();
+ var refreshedClient = await this.DatabaseClientProvider.RefreshClientAsync(section.Role, cancellationToken);
+ section.Client = refreshedClient;
+ section.DisplayInfo.Clear();
try
{
await foreach (var (label, value) in refreshedClient.GetDisplayInfo().WithCancellation(cancellationToken))
{
- this.vectorStoreDisplayInfo.Add(new VectorStoreDisplayInfo(label, value));
+ section.DisplayInfo.Add(new DatabaseDisplayInfo(label, value));
}
}
catch (OperationCanceledException)
@@ -325,20 +377,24 @@ public partial class Information : MSGComponentBase
}
catch (Exception e)
{
- this.vectorStore = new NoVectorStoreClient(refreshedClient.Name, e.Message, DatabaseClientStatus.STARTING);
- await foreach (var (label, value) in this.vectorStore.GetDisplayInfo().WithCancellation(cancellationToken))
+ // Drop whatever came in before the failure: those lines would otherwise stand next to
+ // the status and reason of the stand-in client and read like current values.
+ section.DisplayInfo.Clear();
+
+ section.Client = DatabaseClientProvider.CreateUnavailableClient(section.Role, refreshedClient.Name, e.Message, DatabaseClientStatus.STARTING);
+ await foreach (var (label, value) in section.Client.GetDisplayInfo().WithCancellation(cancellationToken))
{
- this.vectorStoreDisplayInfo.Add(new VectorStoreDisplayInfo(label, value));
+ section.DisplayInfo.Add(new DatabaseDisplayInfo(label, value));
}
}
}
- private void StartShortVectorStoreRefreshLoop()
+ private void StartShortDatabaseRefreshLoop(DatabaseSection section)
{
- this.vectorStoreRefreshCancellationTokenSource?.Cancel();
- this.vectorStoreRefreshCancellationTokenSource?.Dispose();
- this.vectorStoreRefreshCancellationTokenSource = new CancellationTokenSource();
- var cancellationToken = this.vectorStoreRefreshCancellationTokenSource.Token;
+ section.RefreshCancellationTokenSource?.Cancel();
+ section.RefreshCancellationTokenSource?.Dispose();
+ section.RefreshCancellationTokenSource = new CancellationTokenSource();
+ var cancellationToken = section.RefreshCancellationTokenSource.Token;
Task.Run(async () =>
{
@@ -350,11 +406,11 @@ public partial class Information : MSGComponentBase
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
await this.InvokeAsync(async () =>
{
- await this.RefreshVectorStoreInfo(cancellationToken);
+ await this.RefreshDatabaseInfo(section, cancellationToken);
this.StateHasChanged();
});
- if (this.vectorStore?.Status is not DatabaseClientStatus.STARTING)
+ if (section.Client?.Status is not DatabaseClientStatus.STARTING)
return;
}
catch (OperationCanceledException)
@@ -366,7 +422,14 @@ public partial class Information : MSGComponentBase
return;
}
}
- }, cancellationToken).Observe($"{nameof(Information)}: refreshing the vector store info");
+ }, cancellationToken).Observe($"{nameof(Information)}: refreshing the {section.Role} info");
+ }
+
+ private void CancelDatabaseRefreshLoop(DatabaseSection section)
+ {
+ section.RefreshCancellationTokenSource?.Cancel();
+ section.RefreshCancellationTokenSource?.Dispose();
+ section.RefreshCancellationTokenSource = null;
}
private IAvailablePlugin? FindManagedConfigurationPlugin(Guid configurationId)
@@ -525,8 +588,8 @@ public partial class Information : MSGComponentBase
protected override void DisposeResources()
{
- this.vectorStoreRefreshCancellationTokenSource?.Cancel();
- this.vectorStoreRefreshCancellationTokenSource?.Dispose();
+ this.CancelDatabaseRefreshLoop(this.vectorStoreSection);
+ this.CancelDatabaseRefreshLoop(this.indexStoreSection);
base.DisposeResources();
}
diff --git a/app/MindWork AI Studio/Tools/Databases/DatabaseClientProvider.cs b/app/MindWork AI Studio/Tools/Databases/DatabaseClientProvider.cs
index 88db7830..73637c5b 100644
--- a/app/MindWork AI Studio/Tools/Databases/DatabaseClientProvider.cs
+++ b/app/MindWork AI Studio/Tools/Databases/DatabaseClientProvider.cs
@@ -69,6 +69,25 @@ public sealed class DatabaseClientProvider(RustService rustService, ILoggerFacto
client.Status);
}
+ ///
+ /// Builds the client which stands in for a database role that cannot serve right now.
+ ///
+ ///
+ /// Callers outside this namespace get their stand-in from here instead of naming the concrete
+ /// type themselves, so a new role does not have to be spelled out in every one of them.
+ ///
+ /// The role the stand-in has to fill.
+ /// The name to show for the database.
+ /// Why the database is not available.
+ /// Whether the database is starting or unavailable.
+ /// A client which answers every operation without a database behind it.
+ public static DatabaseClient CreateUnavailableClient(DatabaseRole databaseRole, string name, string? reason, DatabaseClientStatus status) => databaseRole switch
+ {
+ DatabaseRole.VECTOR_STORE => new NoVectorStoreClient(name, reason, status),
+ DatabaseRole.INDEX_STORE => new NoIndexStoreClient(name, reason, status),
+ _ => new NoDatabaseClient(name, reason, status)
+ };
+
private DatabaseClient CacheIfAvailable(DatabaseRole databaseRole, DatabaseClient client)
{
if (!client.IsAvailable)
diff --git a/app/MindWork AI Studio/Tools/Databases/VectorStore/QdrantEdgeClientImplementation.cs b/app/MindWork AI Studio/Tools/Databases/VectorStore/QdrantEdgeClientImplementation.cs
index 1666329b..ea880a9b 100644
--- a/app/MindWork AI Studio/Tools/Databases/VectorStore/QdrantEdgeClientImplementation.cs
+++ b/app/MindWork AI Studio/Tools/Databases/VectorStore/QdrantEdgeClientImplementation.cs
@@ -1,5 +1,3 @@
-using System.Globalization;
-
using AIStudio.Tools.Databases.IndexStore;
using AIStudio.Tools.PluginSystem;
using AIStudio.Tools.Rust;