From 3f7b230e6b26c8812724af4dd125df8a3efe8e16 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:01:16 +0100 Subject: [PATCH 01/10] Formatting --- app/Build/Commands/Qdrant.cs | 5 +++-- app/MindWork AI Studio/Tools/Databases/DatabaseClient.cs | 2 ++ .../Tools/Databases/Qdrant/QdrantClientImplementation.cs | 3 +++ app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs | 4 ++++ runtime/src/qdrant.rs | 8 ++++---- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/Build/Commands/Qdrant.cs b/app/Build/Commands/Qdrant.cs index 4133332e..f51c0fa7 100644 --- a/app/Build/Commands/Qdrant.cs +++ b/app/Build/Commands/Qdrant.cs @@ -44,7 +44,8 @@ public static class Qdrant { using var archive = new ZipArchive(zStream, ZipArchiveMode.Read); archive.ExtractToDirectory(qdrantTmpExtractPath.FullName, overwriteFiles: true); - } else + } + else { await using var uncompressedStream = new GZipStream(zStream, CompressionMode.Decompress); await TarFile.ExtractToDirectoryAsync(uncompressedStream, qdrantTmpExtractPath.FullName, true); @@ -63,7 +64,7 @@ public static class Qdrant } var qdrantDBSourcePath = Path.Join(qdrantTmpExtractPath.FullName, database.Path); - var qdrantDBTargetPath = Path.Join(cwd, "resources", "databases", "qdrant",database.Filename); + var qdrantDBTargetPath = Path.Join(cwd, "resources", "databases", "qdrant", database.Filename); if (!File.Exists(qdrantDBSourcePath)) { Console.WriteLine($" failed to find the database file '{qdrantDBSourcePath}'"); diff --git a/app/MindWork AI Studio/Tools/Databases/DatabaseClient.cs b/app/MindWork AI Studio/Tools/Databases/DatabaseClient.cs index 3881a9fc..5ea457ec 100644 --- a/app/MindWork AI Studio/Tools/Databases/DatabaseClient.cs +++ b/app/MindWork AI Studio/Tools/Databases/DatabaseClient.cs @@ -3,7 +3,9 @@ public abstract class DatabaseClient(string name, string path) { public string Name => name; + private string Path => path; + protected ILogger? logger; public abstract IAsyncEnumerable<(string Label, string Value)> GetDisplayInfo(); diff --git a/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClientImplementation.cs b/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClientImplementation.cs index 4ef49dc1..e4cd5a2c 100644 --- a/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClientImplementation.cs +++ b/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClientImplementation.cs @@ -6,10 +6,13 @@ namespace AIStudio.Tools.Databases.Qdrant; public class QdrantClientImplementation : DatabaseClient { private int HttpPort { get; } + private int GrpcPort { get; } private string IpAddress => "localhost"; private QdrantClient GrpcClient { get; } + private string Fingerprint { get; } + private string ApiToken { get; } public QdrantClientImplementation(string name, string path, int httpPort, int grpcPort, string fingerprint, string apiToken): base(name, path) diff --git a/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs b/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs index 6f9b2e5c..8dac8aa7 100644 --- a/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs +++ b/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs @@ -8,8 +8,12 @@ public record struct QdrantInfo { public string Path { get; init; } + public int PortHttp { get; init; } + public int PortGrpc { get; init; } + public string Fingerprint { get; init; } + public string ApiToken { get; init; } } \ No newline at end of file diff --git a/runtime/src/qdrant.rs b/runtime/src/qdrant.rs index 4a945d5d..0ae5a2ee 100644 --- a/runtime/src/qdrant.rs +++ b/runtime/src/qdrant.rs @@ -106,10 +106,12 @@ pub fn start_qdrant_server() { } else { debug!(Source = "Qdrant Server"; "{line}"); } - } + }, + CommandEvent::Stderr(line) => { error!(Source = "Qdrant Server (stderr)"; "{line}"); - } + }, + _ => {} } } @@ -132,9 +134,7 @@ pub fn stop_qdrant_server() { pub fn create_temp_tls_files(path: PathBuf) -> Result<(PathBuf, PathBuf), Box> { let (certificate, cert_private_key, cert_fingerprint) = generate_certificate(); - let temp_dir = init_tmpdir_in(path); - let cert_path = temp_dir.join("cert.pem"); let key_path = temp_dir.join("key.pem"); From ef3d17de0fbce02292b301968bc871080931ac83 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:01:51 +0100 Subject: [PATCH 02/10] Use a const instead --- .../Tools/Databases/Qdrant/QdrantClientImplementation.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClientImplementation.cs b/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClientImplementation.cs index e4cd5a2c..77ae3636 100644 --- a/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClientImplementation.cs +++ b/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClientImplementation.cs @@ -8,7 +8,7 @@ public class QdrantClientImplementation : DatabaseClient private int HttpPort { get; } private int GrpcPort { get; } - private string IpAddress => "localhost"; + private QdrantClient GrpcClient { get; } private string Fingerprint { get; } @@ -24,9 +24,11 @@ public class QdrantClientImplementation : DatabaseClient this.GrpcClient = this.CreateQdrantClient(); } + private const string IP_ADDRESS = "localhost"; + public QdrantClient CreateQdrantClient() { - var address = "https://" + this.IpAddress + ":" + this.GrpcPort; + var address = "https://" + IP_ADDRESS + ":" + this.GrpcPort; var channel = QdrantChannel.ForAddress(address, new ClientConfiguration { ApiKey = this.ApiToken, From 42d538d2d8881b977ba223531ba32e64b294aad4 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:02:14 +0100 Subject: [PATCH 03/10] Removed not used documentation --- app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs b/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs index 8dac8aa7..4b22837d 100644 --- a/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs +++ b/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs @@ -3,8 +3,6 @@ /// /// The response of the Qdrant information request. /// -/// The port number for HTTP communication with Qdrant. -/// The port number for gRPC communication with Qdrant public record struct QdrantInfo { public string Path { get; init; } From cb453dc51802a30e2382bff534342f4fb6158d02 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:03:20 +0100 Subject: [PATCH 04/10] Use a readonly record struct --- app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs | 2 +- .../Tools/Services/RustService.Databases.cs | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs b/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs index 4b22837d..c847235f 100644 --- a/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs +++ b/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs @@ -3,7 +3,7 @@ /// /// The response of the Qdrant information request. /// -public record struct QdrantInfo +public readonly record struct QdrantInfo { public string Path { get; init; } diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs b/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs index a4e0eade..8f67a1d4 100644 --- a/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs +++ b/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs @@ -15,14 +15,7 @@ public sealed partial class RustService catch (Exception e) { Console.WriteLine(e); - return new QdrantInfo - { - Path = string.Empty, - PortHttp = 0, - PortGrpc = 0, - Fingerprint = string.Empty, - ApiToken = string.Empty, - }; + return default; } } } \ No newline at end of file From d9bec277639d817c079ae8381003ec86bd01908b Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:03:32 +0100 Subject: [PATCH 05/10] Improved logging --- .../Tools/Services/RustService.Databases.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs b/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs index 8f67a1d4..a43f6c61 100644 --- a/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs +++ b/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs @@ -14,7 +14,11 @@ public sealed partial class RustService } catch (Exception e) { - Console.WriteLine(e); + if(this.logger is not null) + this.logger.LogError(e, "Error while fetching Qdrant info from Rust service."); + else + Console.WriteLine($"Error while fetching Qdrant info from Rust service: '{e}'."); + return default; } } From e92b7be5df961a3df9154e2b0c889cdba14e6800 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:03:45 +0100 Subject: [PATCH 06/10] Fixed C# syntax --- app/MindWork AI Studio/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/Program.cs b/app/MindWork AI Studio/Program.cs index b67cdcfe..4c495bb3 100644 --- a/app/MindWork AI Studio/Program.cs +++ b/app/MindWork AI Studio/Program.cs @@ -87,7 +87,7 @@ internal sealed class Program } var qdrantInfo = await rust.GetQdrantInfo(); - if (qdrantInfo.Path == String.Empty) + if (qdrantInfo.Path == string.Empty) { Console.WriteLine("Error: Failed to get the Qdrant path from Rust."); return; From e383072ba6e819724f77b8594d4ed652ac96e5c6 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:03:58 +0100 Subject: [PATCH 07/10] Added Qdrant to dict --- app/MindWork AI Studio.sln.DotSettings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/MindWork AI Studio.sln.DotSettings b/app/MindWork AI Studio.sln.DotSettings index faaedb6b..a304dae6 100644 --- a/app/MindWork AI Studio.sln.DotSettings +++ b/app/MindWork AI Studio.sln.DotSettings @@ -24,4 +24,6 @@ True True True + True + True True \ No newline at end of file From a4e0ee29609d6f920c3433a7ea1d9732c2556a34 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:04:12 +0100 Subject: [PATCH 08/10] Formatting --- runtime/src/qdrant.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/qdrant.rs b/runtime/src/qdrant.rs index 0ae5a2ee..dc0ea153 100644 --- a/runtime/src/qdrant.rs +++ b/runtime/src/qdrant.rs @@ -59,7 +59,7 @@ pub fn qdrant_port(_token: APIToken) -> Json { pub fn start_qdrant_server() { let base_path = DATA_DIRECTORY.get().unwrap(); - let (cert_path, key_path) =create_temp_tls_files(Path::new(base_path).join("databases").join("qdrant")).unwrap(); + let (cert_path, key_path) = create_temp_tls_files(Path::new(base_path).join("databases").join("qdrant")).unwrap(); let storage_path = Path::new(base_path).join("databases").join("qdrant").join("storage").to_str().unwrap().to_string(); let snapshot_path = Path::new(base_path).join("databases").join("qdrant").join("snapshots").to_str().unwrap().to_string(); From f57973148f51eae8983748872170e01fb780f64b Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:04:32 +0100 Subject: [PATCH 09/10] Drop the temp. directory last --- runtime/src/qdrant.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/src/qdrant.rs b/runtime/src/qdrant.rs index dc0ea153..c3f0fa1e 100644 --- a/runtime/src/qdrant.rs +++ b/runtime/src/qdrant.rs @@ -120,7 +120,6 @@ pub fn start_qdrant_server() { /// Stops the Qdrant server process. pub fn stop_qdrant_server() { - drop_tmpdir(); if let Some(server_process) = QDRANT_SERVER.lock().unwrap().take() { let server_kill_result = server_process.kill(); match server_kill_result { @@ -130,6 +129,8 @@ pub fn stop_qdrant_server() { } else { warn!(Source = "Qdrant"; "Qdrant server process was not started or is already stopped."); } + + drop_tmpdir(); } pub fn create_temp_tls_files(path: PathBuf) -> Result<(PathBuf, PathBuf), Box> { From 1a0a6e256bfed0d46dbd17f2f489d6f5e870d759 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 14 Jan 2026 09:04:48 +0100 Subject: [PATCH 10/10] Updated packages --- app/MindWork AI Studio/packages.lock.json | 37 +++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/app/MindWork AI Studio/packages.lock.json b/app/MindWork AI Studio/packages.lock.json index c36716e7..4d61757d 100644 --- a/app/MindWork AI Studio/packages.lock.json +++ b/app/MindWork AI Studio/packages.lock.json @@ -64,6 +64,16 @@ "MudBlazor": "8.11.0" } }, + "Qdrant.Client": { + "type": "Direct", + "requested": "[1.16.1, )", + "resolved": "1.16.1", + "contentHash": "EJo50JXTdjY2JOUphCFLXoHukI/tz/ykLCmMnQHUjsKT22ZfL0XIdEziHOC3vjw2SOoY8WDVQ+AxixEonejOZA==", + "dependencies": { + "Google.Protobuf": "3.31.0", + "Grpc.Net.Client": "2.71.0" + } + }, "ReverseMarkdown": { "type": "Direct", "requested": "[4.7.1, )", @@ -83,6 +93,33 @@ "resolved": "33.0.1", "contentHash": "fev4lynklAU2A9GVMLtwarkwaanjSYB4wUqO2nOJX5hnzObORzUqVLe+bDYCUyIIRQM4o5Bsq3CcyJR89iMmEQ==" }, + "Google.Protobuf": { + "type": "Transitive", + "resolved": "3.31.0", + "contentHash": "OZXSf6igaJBeo+kAzMhYF0R5zp0nRgf4G0Uis/IsGKACc4RGP9bQPLpHLengIFuASl0lY92utMB8rRpTx4TaOg==" + }, + "Grpc.Core.Api": { + "type": "Transitive", + "resolved": "2.71.0", + "contentHash": "QquqUC37yxsDzd1QaDRsH2+uuznWPTS8CVE2Yzwl3CvU4geTNkolQXoVN812M2IwT6zpv3jsZRc9ExJFNFslTg==" + }, + "Grpc.Net.Client": { + "type": "Transitive", + "resolved": "2.71.0", + "contentHash": "U1vr20r5ngoT9nlb7wejF28EKN+taMhJsV9XtK9MkiepTZwnKxxiarriiMfCHuDAfPUm9XUjFMn/RIuJ4YY61w==", + "dependencies": { + "Grpc.Net.Common": "2.71.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0" + } + }, + "Grpc.Net.Common": { + "type": "Transitive", + "resolved": "2.71.0", + "contentHash": "v0c8R97TwRYwNXlC8GyRXwYTCNufpDfUtj9la+wUrZFzVWkFJuNAltU+c0yI3zu0jl54k7en6u2WKgZgd57r2Q==", + "dependencies": { + "Grpc.Core.Api": "2.71.0" + } + }, "Markdig": { "type": "Transitive", "resolved": "0.41.3",