From a79a2996fef04dea31d9df06166069f812814059 Mon Sep 17 00:00:00 2001 From: PaulKoudelka Date: Thu, 11 Dec 2025 14:40:08 +0100 Subject: [PATCH] Added pipeline to retrieve information for .NET runtime to create Qdrant client --- .github/workflows/build-and-release.yml | 8 +-- README.md | 2 +- app/Build/Commands/Qdrant.cs | 10 +-- .../Assistants/I18N/allTexts.lua | 9 ++- app/MindWork AI Studio/Pages/About.razor | 24 ++++++- app/MindWork AI Studio/Pages/About.razor.cs | 13 +++- app/MindWork AI Studio/Program.cs | 23 ++++++ app/MindWork AI Studio/Settings/Profile.cs | 1 - .../Tools/Databases/DatabaseClient.cs | 71 +++++++++++++++++++ .../Tools/Databases/Qdrant/QdrantClient.cs | 15 ++++ .../Metadata/MetaDataDatabasesAttribute.cs | 4 +- .../Tools/Rust/QdrantInfo.cs | 13 ++++ .../Tools/Services/RustService.Databases.cs | 26 +++++++ .../wwwroot/changelog/v0.9.55.md | 1 + metadata.txt | 2 +- .../resources/databases/qdrant/config.yaml | 8 +-- runtime/src/main.rs | 2 +- runtime/src/qdrant.rs | 59 ++++++--------- runtime/src/runtime_api.rs | 1 + 19 files changed, 232 insertions(+), 60 deletions(-) create mode 100644 app/MindWork AI Studio/Tools/Databases/DatabaseClient.cs create mode 100644 app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClient.cs create mode 100644 app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs create mode 100644 app/MindWork AI Studio/Tools/Services/RustService.Databases.cs diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index 0d47e4d2..8cf531b8 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -174,7 +174,7 @@ jobs: pdfium_version=$(echo $pdfium_version | cut -d'.' -f3) # Next line is the Qdrant version: - qdrant_version=$(sed -n '12p' metadata.txt) + qdrant_version="v$(sed -n '12p' metadata.txt)" # Write the metadata to the environment: echo "APP_VERSION=${app_version}" >> $GITHUB_ENV @@ -247,7 +247,7 @@ jobs: $pdfium_version = $pdfium_version.Split('.')[2] # Next line is the necessary Qdrant version: - $qdrant_version = $metadata[12] + $qdrant_version = "v$metadata[12]" # Write the metadata to the environment: Write-Output "APP_VERSION=${app_version}" >> $env:GITHUB_ENV @@ -441,7 +441,7 @@ jobs: ;; esac - QDRANT_URL="https://github.com/qdrant/qdrant/releases/download/${QDRANT_VERSON}/qdrant-{QDRANT_FILE}" + QDRANT_URL="https://github.com/qdrant/qdrant/releases/download/v${QDRANT_VERSION}/qdrant-{QDRANT_FILE}" echo "Download Qdrant $QDRANT_URL ..." TMP=$(mktemp -d) @@ -485,7 +485,7 @@ jobs: } } - QDRANT_URL="https://github.com/qdrant/qdrant/releases/download/${QDRANT_VERSON}/qdrant-{QDRANT_FILE}" + QDRANT_URL="https://github.com/qdrant/qdrant/releases/download/v${QDRANT_VERSION}/qdrant-{QDRANT_FILE}" Write-Host "Download $QDRANT_URL ..." # Create a unique temporary directory (not just a file) diff --git a/README.md b/README.md index d526d2b3..e8489aef 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Since November 2024: Work on RAG (integration of your data and files) has begun. - [x] ~~App: Implement dialog for checking & handling [pandoc](https://pandoc.org/) installation ([PR #393](https://github.com/MindWorkAI/AI-Studio/pull/393), [PR #487](https://github.com/MindWorkAI/AI-Studio/pull/487))~~ - [ ] App: Implement external embedding providers - [ ] App: Implement the process to vectorize one local file using embeddings -- [ ] Runtime: Integration of the vector database [LanceDB](https://github.com/lancedb/lancedb) +- [ ] Runtime: Integration of the vector database [Qdrant](https://github.com/qdrant/qdrant) - [ ] App: Implement the continuous process of vectorizing data - [x] ~~App: Define a common retrieval context interface for the integration of RAG processes in chats (PR [#281](https://github.com/MindWorkAI/AI-Studio/pull/281), [#284](https://github.com/MindWorkAI/AI-Studio/pull/284), [#286](https://github.com/MindWorkAI/AI-Studio/pull/286), [#287](https://github.com/MindWorkAI/AI-Studio/pull/287))~~ - [x] ~~App: Define a common augmentation interface for the integration of RAG processes in chats (PR [#288](https://github.com/MindWorkAI/AI-Studio/pull/288), [#289](https://github.com/MindWorkAI/AI-Studio/pull/289))~~ diff --git a/app/Build/Commands/Qdrant.cs b/app/Build/Commands/Qdrant.cs index cc0bb1e4..9a573823 100644 --- a/app/Build/Commands/Qdrant.cs +++ b/app/Build/Commands/Qdrant.cs @@ -88,11 +88,11 @@ public static class Qdrant private static Database GetDatabasePath(RID rid) => rid switch { - RID.LINUX_ARM64 => new("qdrant", "qdrant-aarch64-apple-darwin"), - RID.LINUX_X64 => new("qdrant", "qdrant-x86_64-apple-darwin"), + RID.OSX_ARM64 => new("qdrant", "qdrant-aarch64-apple-darwin"), + RID.OSX_X64 => new("qdrant", "qdrant-x86_64-apple-darwin"), - RID.OSX_ARM64 => new("qdrant", "qdrant-aarch64-unknown-linux-gnu"), - RID.OSX_X64 => new("qdrant", "qdrant-x86_64-unknown-linux-gnu"), + RID.LINUX_ARM64 => new("qdrant", "qdrant-aarch64-unknown-linux-gnu"), + RID.LINUX_X64 => new("qdrant", "qdrant-x86_64-unknown-linux-gnu"), RID.WIN_X64 => new("qdrant.exe", "qdrant-x86_64-pc-windows-msvc.exe"), @@ -101,7 +101,7 @@ public static class Qdrant private static string GetQdrantDownloadUrl(RID rid, string version) { - var baseUrl = $"https://github.com/qdrant/qdrant/releases/download/{version}/qdrant-"; + var baseUrl = $"https://github.com/qdrant/qdrant/releases/download/v{version}/qdrant-"; return rid switch { RID.LINUX_ARM64 => $"{baseUrl}aarch64-unknown-linux-musl.tar.gz", diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index fd41d6c8..8ffac5d9 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -4462,6 +4462,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1282228996"] = "AI Studio runs with an -- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1388816916"] = "This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat." +-- Database version +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1420062548"] = "Database version" + -- This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1421513382"] = "This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library." @@ -4501,6 +4504,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1924365263"] = "This library is used t -- We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1943216839"] = "We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust." +-- Copies the following to the clipboard +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2029659664"] = "Copies the following to the clipboard" + -- Copies the server URL to the clipboard UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2037899437"] = "Copies the server URL to the clipboard" @@ -4567,9 +4573,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2777988282"] = "Code in the Rust langu -- Show Details UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T27924674"] = "Show Details" --- Used Qdrant version -UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2799791022"] = "Used Qdrant version" - -- View our project roadmap and help shape AI Studio's future development. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2829971158"] = "View our project roadmap and help shape AI Studio's future development." diff --git a/app/MindWork AI Studio/Pages/About.razor b/app/MindWork AI Studio/Pages/About.razor index 92f62f6c..d9fd748b 100644 --- a/app/MindWork AI Studio/Pages/About.razor +++ b/app/MindWork AI Studio/Pages/About.razor @@ -19,7 +19,29 @@ - + + + @this.VersionDatabase + + + + @foreach (var (Label, Value) in DatabaseClient.GetDisplayInfo()) + { +
+ + @Label: @Value + +
+ } +
+
+ + @(this.showDatabaseDetails ? T("Hide Details") : T("Show Details")) + +
diff --git a/app/MindWork AI Studio/Pages/About.razor.cs b/app/MindWork AI Studio/Pages/About.razor.cs index e5d7903f..9371c610 100644 --- a/app/MindWork AI Studio/Pages/About.razor.cs +++ b/app/MindWork AI Studio/Pages/About.razor.cs @@ -2,6 +2,7 @@ using System.Reflection; using AIStudio.Components; using AIStudio.Dialogs; +using AIStudio.Tools.Databases; using AIStudio.Tools.Metadata; using AIStudio.Tools.PluginSystem; using AIStudio.Tools.Rust; @@ -26,6 +27,9 @@ public partial class About : MSGComponentBase [Inject] private ISnackbar Snackbar { get; init; } = null!; + [Inject] + private DatabaseClient DatabaseClient { get; init; } = null!; + private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly(); private static readonly MetaDataAttribute META_DATA = ASSEMBLY.GetCustomAttribute()!; private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute()!; @@ -54,7 +58,7 @@ public partial class About : MSGComponentBase private string VersionPdfium => $"{T("Used PDFium version")}: v{META_DATA_LIBRARIES.PdfiumVersion}"; - private string VersionQdrant => $"{T("Used Qdrant version")}: {META_DATA_DATABASES.QdrantVersion}"; + private string VersionDatabase => $"{T("Database version")}: {this.DatabaseClient.Name} v{META_DATA_DATABASES.DatabaseVersion}"; private string versionPandoc = TB("Determine Pandoc version, please wait..."); private PandocInstallation pandocInstallation; @@ -63,6 +67,8 @@ public partial class About : MSGComponentBase private bool showEnterpriseConfigDetails; + private bool showDatabaseDetails = false; + private IPluginMetadata? configPlug = PluginFactory.AvailablePlugins.FirstOrDefault(x => x.Type is PluginType.CONFIGURATION); /// @@ -173,6 +179,11 @@ public partial class About : MSGComponentBase { this.showEnterpriseConfigDetails = !this.showEnterpriseConfigDetails; } + + private void ToggleDatabaseDetails() + { + this.showDatabaseDetails = !this.showDatabaseDetails; + } private async Task CopyStartupLogPath() { diff --git a/app/MindWork AI Studio/Program.cs b/app/MindWork AI Studio/Program.cs index 2514a67f..07439d06 100644 --- a/app/MindWork AI Studio/Program.cs +++ b/app/MindWork AI Studio/Program.cs @@ -1,6 +1,9 @@ using AIStudio.Agents; using AIStudio.Settings; +using AIStudio.Tools.Databases; +using AIStudio.Tools.Databases.Qdrant; using AIStudio.Tools.PluginSystem; +using AIStudio.Tools.Rust; using AIStudio.Tools.Services; using Microsoft.AspNetCore.Server.Kestrel.Core; @@ -82,6 +85,24 @@ internal sealed class Program return; } + var qdrantInfo = await rust.GetQdrantInfo(); + if (qdrantInfo.Path == String.Empty) + { + Console.WriteLine("Error: Failed to get the Qdrant path from Rust."); + return; + } + if (qdrantInfo.PortHttp == 0) + { + Console.WriteLine("Error: Failed to get the Qdrant HTTP port from Rust."); + return; + } + + if (qdrantInfo.PortGrpc == 0) + { + Console.WriteLine("Error: Failed to get the Qdrant gRPC port from Rust."); + return; + } + var builder = WebApplication.CreateBuilder(); builder.WebHost.ConfigureKestrel(kestrelServerOptions => @@ -133,6 +154,7 @@ internal sealed class Program builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); + builder.Services.AddSingleton(new QdrantClient("Qdrant", qdrantInfo.Path, qdrantInfo.PortHttp, qdrantInfo.PortGrpc)); // ReSharper disable AccessToDisposedClosure builder.Services.AddHostedService(_ => rust); @@ -215,6 +237,7 @@ internal sealed class Program await rust.AppIsReady(); programLogger.LogInformation("The AI Studio server is ready."); + TaskScheduler.UnobservedTaskException += (sender, taskArgs) => { programLogger.LogError(taskArgs.Exception, $"Unobserved task exception by sender '{sender ?? "n/a"}'."); diff --git a/app/MindWork AI Studio/Settings/Profile.cs b/app/MindWork AI Studio/Settings/Profile.cs index 0436beb5..2e9dc80a 100644 --- a/app/MindWork AI Studio/Settings/Profile.cs +++ b/app/MindWork AI Studio/Settings/Profile.cs @@ -77,7 +77,6 @@ public record Profile( public static bool TryParseProfileTable(int idx, LuaTable table, Guid configPluginId, out ConfigurationBaseObject template) { - LOGGER.LogInformation($"\n Profile table parsing {idx}.\n"); template = NO_PROFILE; if (!table.TryGetValue("Id", out var idValue) || !idValue.TryRead(out var idText) || !Guid.TryParse(idText, out var id)) { diff --git a/app/MindWork AI Studio/Tools/Databases/DatabaseClient.cs b/app/MindWork AI Studio/Tools/Databases/DatabaseClient.cs new file mode 100644 index 00000000..0ca84e01 --- /dev/null +++ b/app/MindWork AI Studio/Tools/Databases/DatabaseClient.cs @@ -0,0 +1,71 @@ +namespace AIStudio.Tools.Databases; + +public abstract class DatabaseClient +{ + public string Name { get; } + private string Path { get; } + + public DatabaseClient(string name, string path) + { + this.Name = name; + this.Path = path; + } + + public abstract IEnumerable<(string Label, string Value)> GetDisplayInfo(); + + public string GetStorageSize() + { + if (string.IsNullOrEmpty(this.Path)) + { + Console.WriteLine($"Error: Database path '{this.Path}' cannot be null or empty."); + return "0 B"; + } + + if (!Directory.Exists(this.Path)) + { + Console.WriteLine($"Error: Database path '{this.Path}' does not exist."); + return "0 B"; + } + long size = 0; + var stack = new Stack(); + stack.Push(this.Path); + while (stack.Count > 0) + { + string directory = stack.Pop(); + try + { + var files = Directory.GetFiles(directory); + size += files.Sum(file => new FileInfo(file).Length); + var subDirectories = Directory.GetDirectories(directory); + foreach (var subDirectory in subDirectories) + { + stack.Push(subDirectory); + } + } + catch (UnauthorizedAccessException) + { + Console.WriteLine($"No access to {directory}"); + } + catch (Exception ex) + { + Console.WriteLine($"An error encountered while processing {directory}: "); + Console.WriteLine($"{ ex.Message}"); + } + } + return FormatBytes(size); + } + + public static string FormatBytes(long size) + { + string[] suffixes = { "B", "KB", "MB", "GB", "TB", "PB" }; + int suffixIndex = 0; + + while (size >= 1024 && suffixIndex < suffixes.Length - 1) + { + size /= 1024; + suffixIndex++; + } + + return $"{size:0##} {suffixes[suffixIndex]}"; + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClient.cs b/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClient.cs new file mode 100644 index 00000000..c3a4fabd --- /dev/null +++ b/app/MindWork AI Studio/Tools/Databases/Qdrant/QdrantClient.cs @@ -0,0 +1,15 @@ +namespace AIStudio.Tools.Databases.Qdrant; + +public class QdrantClient(string name, string path, int httpPort, int grpcPort) : DatabaseClient(name, path) +{ + private int HttpPort { get; } = httpPort; + private int GrpcPort { get; } = grpcPort; + private string IpAddress { get; } = "127.0.0.1"; + + public override IEnumerable<(string Label, string Value)> GetDisplayInfo() + { + yield return ("HTTP Port", this.HttpPort.ToString()); + yield return ("gRPC Port", this.GrpcPort.ToString()); + yield return ("Storage Size", $"{base.GetStorageSize()}"); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Metadata/MetaDataDatabasesAttribute.cs b/app/MindWork AI Studio/Tools/Metadata/MetaDataDatabasesAttribute.cs index 9ab92940..5ef6064b 100644 --- a/app/MindWork AI Studio/Tools/Metadata/MetaDataDatabasesAttribute.cs +++ b/app/MindWork AI Studio/Tools/Metadata/MetaDataDatabasesAttribute.cs @@ -1,6 +1,6 @@ namespace AIStudio.Tools.Metadata; -public class MetaDataDatabasesAttribute(string qdrantVersion) : Attribute +public class MetaDataDatabasesAttribute(string databaseVersion) : Attribute { - public string QdrantVersion => qdrantVersion; + public string DatabaseVersion => databaseVersion; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs b/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs new file mode 100644 index 00000000..8cbe5e9c --- /dev/null +++ b/app/MindWork AI Studio/Tools/Rust/QdrantInfo.cs @@ -0,0 +1,13 @@ +namespace AIStudio.Tools.Rust; + +/// +/// 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; } + public int PortHttp { get; init; } + public int PortGrpc { get; init; } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs b/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs new file mode 100644 index 00000000..ae42316d --- /dev/null +++ b/app/MindWork AI Studio/Tools/Services/RustService.Databases.cs @@ -0,0 +1,26 @@ +using AIStudio.Tools.Rust; + +namespace AIStudio.Tools.Services; + +public sealed partial class RustService +{ + public async Task GetQdrantInfo() + { + try + { + var cts = new CancellationTokenSource(TimeSpan.FromSeconds(45)); + var response = await this.http.GetFromJsonAsync("/system/qdrant/port", this.jsonRustSerializerOptions, cts.Token); + return response; + } + catch (Exception e) + { + Console.WriteLine(e); + return new QdrantInfo + { + Path = string.Empty, + PortHttp = 0, + PortGrpc = 0, + }; + } + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.55.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.55.md index e72bca78..acc432fc 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.9.55.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.55.md @@ -1 +1,2 @@ # v0.9.55, build 230 (2025-12-xx xx:xx UTC) +Added functionality to download Qdrant and execute it as a background sidecar. \ No newline at end of file diff --git a/metadata.txt b/metadata.txt index 62e8ccb4..5746ea97 100644 --- a/metadata.txt +++ b/metadata.txt @@ -9,4 +9,4 @@ 009bb33d839, release osx-arm64 137.0.7215.0 -v1.16.1 \ No newline at end of file +1.16.1 \ No newline at end of file diff --git a/runtime/resources/databases/qdrant/config.yaml b/runtime/resources/databases/qdrant/config.yaml index efdb79da..267f81c2 100644 --- a/runtime/resources/databases/qdrant/config.yaml +++ b/runtime/resources/databases/qdrant/config.yaml @@ -235,15 +235,15 @@ service: max_workers: 0 # Host to bind the service on - host: 0.0.0.0 + host: 127.0.0.1 # HTTP(S) port to bind the service on - http_port: 6373 + # http_port: 6333 # gRPC port to bind the service on. # If `null` - gRPC is disabled. Default: null # Comment to disable gRPC: - grpc_port: 6344 + # grpc_port: 6334 # Enable CORS headers in REST API. # If enabled, browsers would be allowed to query REST endpoints regardless of query origin. @@ -326,7 +326,7 @@ cluster: # Set to true to prevent service from sending usage statistics to the developers. # Read more: https://qdrant.tech/documentation/guides/telemetry -telemetry_disabled: false +telemetry_disabled: true # TLS configuration. # Required if either service.enable_tls or cluster.p2p.enable_tls is true. diff --git a/runtime/src/main.rs b/runtime/src/main.rs index 34620a91..bfbe4750 100644 --- a/runtime/src/main.rs +++ b/runtime/src/main.rs @@ -38,7 +38,7 @@ async fn main() { info!(".. MudBlazor: v{mud_blazor_version}", mud_blazor_version = metadata.mud_blazor_version); info!(".. Tauri: v{tauri_version}", tauri_version = metadata.tauri_version); info!(".. PDFium: v{pdfium_version}", pdfium_version = metadata.pdfium_version); - info!(".. Qdrant: {qdrant_version}", qdrant_version = metadata.qdrant_version); + info!(".. Qdrant: v{qdrant_version}", qdrant_version = metadata.qdrant_version); if is_dev() { warn!("Running in development mode."); diff --git a/runtime/src/qdrant.rs b/runtime/src/qdrant.rs index f95ebcd1..3b2b94ce 100644 --- a/runtime/src/qdrant.rs +++ b/runtime/src/qdrant.rs @@ -4,8 +4,9 @@ use std::sync::{Arc, Mutex}; use log::{debug, error, info, warn}; use once_cell::sync::Lazy; use rocket::get; +use rocket::serde::json::Json; +use rocket::serde::Serialize; use tauri::api::process::{Command, CommandChild, CommandEvent}; -use tauri::Url; use crate::api_token::{APIToken}; use crate::environment::DATA_DIRECTORY; @@ -14,16 +15,28 @@ use crate::environment::DATA_DIRECTORY; static QDRANT_SERVER: Lazy>>> = Lazy::new(|| Arc::new(Mutex::new(None))); // Qdrant server port (default is 6333 for HTTP and 6334 for gRPC) -static QDRANT_SERVER_PORT: Lazy = Lazy::new(|| { +static QDRANT_SERVER_PORT_HTTP: Lazy = Lazy::new(|| { crate::network::get_available_port().unwrap_or(6333) -}); +}); -static QDRANT_INITIALIZED: Lazy> = Lazy::new(|| Mutex::new(false)); +static QDRANT_SERVER_PORT_GRPC: Lazy = Lazy::new(|| { + crate::network::get_available_port().unwrap_or(6334) +}); + +#[derive(Serialize)] +pub struct ProvideQdrantInfo { + path: String, + port_http: u16, + port_grpc: u16, +} #[get("/system/qdrant/port")] -pub fn qdrant_port(_token: APIToken) -> String { - let qdrant_port = *QDRANT_SERVER_PORT; - format!("{qdrant_port}") +pub fn qdrant_port(_token: APIToken) -> Json { + return Json(ProvideQdrantInfo { + path: Path::new(DATA_DIRECTORY.get().unwrap()).join("databases").join("qdrant").to_str().unwrap().to_string(), + port_http: *QDRANT_SERVER_PORT_HTTP, + port_grpc: *QDRANT_SERVER_PORT_GRPC, + }); } /// Starts the Qdrant server in a separate process. @@ -35,16 +48,14 @@ pub fn start_qdrant_server() { let snapshot_path = Path::new(base_path).join("databases").join("qdrant").join("snapshots").to_str().unwrap().to_string(); let init_path = Path::new(base_path).join("databases").join("qdrant").join(".qdrant-initalized").to_str().unwrap().to_string(); - println!("{}", storage_path); - println!("{}", snapshot_path); - println!("{}", init_path); - let qdrant_server_environment = HashMap::from_iter([ - (String::from("QDRANT__SERVICE__HTTP_PORT"), QDRANT_SERVER_PORT.to_string()), + (String::from("QDRANT__SERVICE__HTTP_PORT"), QDRANT_SERVER_PORT_HTTP.to_string()), + (String::from("QDRANT__SERVICE__GRPC_PORT"), QDRANT_SERVER_PORT_GRPC.to_string()), (String::from("QDRANT_INIT_FILE_PATH"), init_path), (String::from("QDRANT__STORAGE__STORAGE_PATH"), storage_path), (String::from("QDRANT__STORAGE__SNAPSHOTS_PATH"), snapshot_path), ]); + let server_spawn_clone = QDRANT_SERVER.clone(); tauri::async_runtime::spawn(async move { let (mut rx, child) = Command::new_sidecar("qdrant") @@ -84,30 +95,6 @@ pub fn start_qdrant_server() { }); } -/// This endpoint is called by the Qdrant server or frontend to signal that Qdrant is ready. -#[get("/system/qdrant/ready")] -pub async fn qdrant_ready(_token: APIToken) { - { - let mut initialized = QDRANT_INITIALIZED.lock().unwrap(); - if *initialized { - warn!("Qdrant server was already initialized."); - return; - } - info!("Qdrant server is ready."); - *initialized = true; - } - - let qdrant_port = *QDRANT_SERVER_PORT; - let _url = match Url::parse(format!("http://localhost:{qdrant_port}").as_str()) { - Ok(url) => url, - Err(msg) => { - error!("Error while parsing Qdrant URL: {msg}"); - return; - } - }; - -} - /// Stops the Qdrant server process. pub fn stop_qdrant_server() { if let Some(server_process) = QDRANT_SERVER.lock().unwrap().take() { diff --git a/runtime/src/runtime_api.rs b/runtime/src/runtime_api.rs index 23fc5e33..529d9636 100644 --- a/runtime/src/runtime_api.rs +++ b/runtime/src/runtime_api.rs @@ -67,6 +67,7 @@ pub fn start_runtime_api() { .mount("/", routes![ crate::dotnet::dotnet_port, crate::dotnet::dotnet_ready, + crate::qdrant::qdrant_port, crate::clipboard::set_clipboard, crate::app_window::get_event_stream, crate::app_window::check_for_update,