From 437da0fd9b7df295160db0a561c61911c67cf53d Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Fri, 30 May 2025 22:39:16 +0200 Subject: [PATCH] Finished the Pandoc integration (#487) --- app/Build/Commands/Pdfium.cs | 2 +- .../Assistants/ERI/AssistantERI.razor | 6 +- .../Assistants/I18N/allTexts.lua | 223 +++++++++++++- .../Components/CodeBlock.razor | 17 +- .../Components/CodeBlock.razor.cs | 5 +- .../Components/CodeTabs.razor | 4 +- .../Components/CodeTabs.razor.cs | 14 +- .../Components/ExpansionPanel.razor | 2 +- .../Components/ExpansionPanel.razor.cs | 6 + .../Components/ManagePandocDependency.razor | 10 + .../ManagePandocDependency.razor.cs | 97 ++++++ .../DataSourceLocalDirectoryDialog.razor | 2 + .../Dialogs/DataSourceLocalFileDialog.razor | 2 + .../Dialogs/PandocDialog.razor | 281 +++++++++++------- .../Dialogs/PandocDialog.razor.cs | 133 +++++---- app/MindWork AI Studio/Pages/About.razor | 12 +- app/MindWork AI Studio/Pages/About.razor.cs | 59 ++++ .../plugin.lua | 227 +++++++++++++- .../plugin.lua | 223 +++++++++++++- app/MindWork AI Studio/Tools/Pandoc.cs | 271 +++++++++-------- .../Tools/PandocExecutable.cs | 3 + .../Tools/PandocInstallation.cs | 3 + .../Tools/PandocPreparedProcess.cs | 10 + .../Tools/PandocProcessBuilder.cs | 135 +++++++++ app/MindWork AI Studio/wwwroot/app.js | 10 - .../wwwroot/changelog/v0.9.46.md | 3 +- .../NamingAnalyzers/LocalConstantsAnalyzer.cs | 2 +- runtime/src/file_data.rs | 15 +- runtime/src/lib.rs | 3 +- runtime/src/pandoc.rs | 169 +++++++++++ 30 files changed, 1600 insertions(+), 349 deletions(-) create mode 100644 app/MindWork AI Studio/Components/ManagePandocDependency.razor create mode 100644 app/MindWork AI Studio/Components/ManagePandocDependency.razor.cs create mode 100644 app/MindWork AI Studio/Tools/PandocExecutable.cs create mode 100644 app/MindWork AI Studio/Tools/PandocInstallation.cs create mode 100644 app/MindWork AI Studio/Tools/PandocPreparedProcess.cs create mode 100644 app/MindWork AI Studio/Tools/PandocProcessBuilder.cs create mode 100644 runtime/src/pandoc.rs diff --git a/app/Build/Commands/Pdfium.cs b/app/Build/Commands/Pdfium.cs index 23902296..12348a4b 100644 --- a/app/Build/Commands/Pdfium.cs +++ b/app/Build/Commands/Pdfium.cs @@ -48,7 +48,7 @@ public static class Pdfium // Console.Write(" deploying ..."); var library = GetLibraryPath(rid); - if (string.IsNullOrEmpty(library.Path)) + if (string.IsNullOrWhiteSpace(library.Path)) { Console.WriteLine($" failed to find the library path for {rid.ToUserFriendlyName()}"); return; diff --git a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor index cd52da4d..bada49bf 100644 --- a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor +++ b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor @@ -154,7 +154,7 @@ else @if (this.dataSourcePort < 1024) { - @((MarkupString)T("Warning: Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user).")) + @T("Warning:") @T("Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user).") } @@ -326,7 +326,7 @@ else - @((MarkupString)T("Important: The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this. However, generating all the files takes a certain amount of time. Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing.")) + @T("Important:") @T("The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this.") @T("However, generating all the files takes a certain amount of time.") @T("Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing.") @@ -340,7 +340,7 @@ else - @((MarkupString)T("When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files. But beware: It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose.")) + @T("When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files.") @T("But beware:") @T("It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose.") diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index c1f07097..46361244 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -484,6 +484,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ALLOWEDLLMPROVIDERSEXTENSIONS::T4096 -- Please describe at least one retrieval process. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1035068989"] = "Please describe at least one retrieval process." +-- Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1047217452"] = "Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing." + -- Please select which types of LLMs users are allowed to use with the data from this ERI server. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1047631678"] = "Please select which types of LLMs users are allowed to use with the data from this ERI server." @@ -511,9 +514,6 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1261836894"] = "Pleas -- You have not yet added any ERI server presets. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1267931972"] = "You have not yet added any ERI server presets." --- Warning: Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user). -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1287629674"] = "Warning: Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user)." - -- The task of writing the ERI server for you is very complex. Therefore, a very powerful LLM is needed to successfully accomplish this task. Small local models will probably not be sufficient. Instead, try using a large cloud-based or a large self-hosted model. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1302705248"] = "The task of writing the ERI server for you is very complex. Therefore, a very powerful LLM is needed to successfully accomplish this task. Small local models will probably not be sufficient. Instead, try using a large cloud-based or a large self-hosted model." @@ -535,12 +535,18 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1456749976"] = "Pleas -- Delete UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1469573738"] = "Delete" +-- When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1531680404"] = "When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files." + -- Related links: UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1565111217"] = "Related links:" -- Please select an ERI specification version for the ERI server. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1612890554"] = "Please select an ERI specification version for the ERI server." +-- Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user). +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T168780641"] = "Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user)." + -- Write code to file system UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1717303021"] = "Write code to file system" @@ -562,6 +568,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T180938091"] = "Delete -- Provider selection for generation UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1840198821"] = "Provider selection for generation" +-- However, generating all the files takes a certain amount of time. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1862007299"] = "However, generating all the files takes a certain amount of time." + -- Should we automatically save any input made? UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1980659256"] = "Should we automatically save any input made?" @@ -577,8 +586,8 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2034620186"] = "Data -- Interactive documentation aka Swagger UI UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2064957876"] = "Interactive documentation aka Swagger UI" --- When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files. But beware: It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2155983785"] = "When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files. But beware: It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose." +-- Warning: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2149175535"] = "Warning:" -- Add Embedding Method UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2176833082"] = "Add Embedding Method" @@ -607,6 +616,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2417944396"] = "Are y -- Data source settings UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2440619931"] = "Data source settings" +-- The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T248288139"] = "The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this." + -- Yes, please write or update all generated code to the file system UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T252707279"] = "Yes, please write or update all generated code to the file system" @@ -682,18 +694,21 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3316699247"] = "No, j -- Other language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3374524465"] = "Other language" +-- Important: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3379345517"] = "Important:" + -- ERI Server {0} UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3443687246"] = "ERI Server {0}" -- You will likely use one or more embedding methods to encode the meaning of your data into a typically high-dimensional vector space. In this case, you will use a vector database to store and search these vectors (called embeddings). However, you don't have to use embedding methods. When your retrieval method works without any embedding, you can ignore this section. An example: You store files on a file server, and your retrieval method works exclusively with file names in the file system, so you don't need embeddings. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3446047228"] = "You will likely use one or more embedding methods to encode the meaning of your data into a typically high-dimensional vector space. In this case, you will use a vector database to store and search these vectors (called embeddings). However, you don't have to use embedding methods. When your retrieval method works without any embedding, you can ignore this section. An example: You store files on a file server, and your retrieval method works exclusively with file names in the file system, so you don't need embeddings." --- Important: The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this. However, generating all the files takes a certain amount of time. Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3485079498"] = "Important: The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this. However, generating all the files takes a certain amount of time. Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing." - -- Type UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3512062061"] = "Type" +-- It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3541842180"] = "It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose." + -- Please describe how the selected authentication methods should be used. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T356079033"] = "Please describe how the selected authentication methods should be used." @@ -733,6 +748,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3865031940"] = "Actio -- ERI specification version UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3897494556"] = "ERI specification version" +-- But beware: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3956615326"] = "But beware:" + -- Please provide a description for your ERI server. What data will the server retrieve? This description will be used to inform users about the purpose of your ERI server. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3973182416"] = "Please provide a description for your ERI server. What data will the server retrieve? This description will be used to inform users about the purpose of your ERI server." @@ -1519,6 +1537,30 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCESELECTION::T86053874"] = "Avail -- Issues UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ISSUES::T3229841001"] = "Issues" +-- Your Pandoc installation meets the requirements. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T1167365374"] = "Your Pandoc installation meets the requirements." + +-- Please wait while we check the availability of Pandoc. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T1336364299"] = "Please wait while we check the availability of Pandoc." + +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T185447014"] = "Pandoc Installation" + +-- Your Pandoc installation is outdated. Please update it to the latest version to ensure compatibility with all features. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T251757907"] = "Your Pandoc installation is outdated. Please update it to the latest version to ensure compatibility with all features." + +-- Pandoc is not installed or not available. Please install it to use the features that require Pandoc. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T3147551473"] = "Pandoc is not installed or not available. Please install it to use the features that require Pandoc." + +-- Update Pandoc +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T3249965383"] = "Update Pandoc" + +-- Check your Pandoc installation +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T527187983"] = "Check your Pandoc installation" + +-- Install Pandoc +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T986578435"] = "Install Pandoc" + -- Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1057189794"] = "Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications." @@ -2437,6 +2479,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2814869210" -- Embedding UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2838542994"] = "Embedding" +-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3359366900"] = "For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc." + -- Yes, please send my data to the cloud UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3572613009"] = "Yes, please send my data to the cloud" @@ -2551,6 +2596,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2814869210"] = " -- Embedding UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2838542994"] = "Embedding" +-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3359366900"] = "For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc." + -- Yes, please send my data to the cloud UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3572613009"] = "Yes, please send my data to the cloud" @@ -2746,6 +2794,96 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900237532"] = "Pro -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900713019"] = "Cancel" +-- Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1001483402"] = "Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system." + +-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and Install," you agree to the terms of the GPL license, and Pandoc will be installed automatically for you. Software under GPL is free of charge and free to use. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1357200670"] = "Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking \"Accept GPL and Install,\" you agree to the terms of the GPL license, and Pandoc will be installed automatically for you. Software under GPL is free of charge and free to use." + +-- View the GNU General Public License v2 (GPL) +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1587398673"] = "View the GNU General Public License v2 (GPL)" + +-- Reject the GPL licence +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1655899051"] = "Reject the GPL licence" + +-- Automatic installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1780479836"] = "Automatic installation" + +-- Manual installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1814127049"] = "Manual installation" + +-- AI Studio uses the free and open-source third-party app Pandoc to process and retrieve data from local Office files (such as Word files) or to generate Office documents. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T205422394"] = "AI Studio uses the free and open-source third-party app Pandoc to process and retrieve data from local Office files (such as Word files) or to generate Office documents." + +-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and download installer," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2084501359"] = "Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking \"Accept GPL and download installer,\" you agree to the terms of the GPL license. Software under GPL is free of charge and free to use." + +-- Extract the archive to a folder of your choice, e.g.: +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2094245964"] = "Extract the archive to a folder of your choice, e.g.:" + +-- Pandoc is open-source and free, but if you reject its license, you can't install it and some MindWork AI Studio features will be limited (like the integration of Office files) or unavailable (like the generation of Office files). You can change your decision anytime. Are you sure you want to reject the license? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2559178004"] = "Pandoc is open-source and free, but if you reject its license, you can't install it and some MindWork AI Studio features will be limited (like the integration of Office files) or unavailable (like the generation of Office files). You can change your decision anytime. Are you sure you want to reject the license?" + +-- Please wait for the installation to complete... +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2606205182"] = "Please wait for the installation to complete..." + +-- Open the folder and copy the full path to the folder where your Pandoc executable file is into your clipboard: +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2946844485"] = "Open the folder and copy the full path to the folder where your Pandoc executable file is into your clipboard:" + +-- Accept the GPL and start the installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2966192331"] = "Accept the GPL and start the installation" + +-- Error loading license text, please consider following the links to read the GPL. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3054618024"] = "Error loading license text, please consider following the links to read the GPL." + +-- Accept the GPL and download the installer +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3104260405"] = "Accept the GPL and download the installer" + +-- Add the copied path to your system's or user's PATH environment variable, restart your terminal, and check the installation: +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T313476957"] = "Add the copied path to your system's or user's PATH environment variable, restart your terminal, and check the installation:" + +-- Accept the terms of the GPL license and download the latest archive with the download button below. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3263447722"] = "Accept the terms of the GPL license and download the latest archive with the download button below." + +-- Pandoc doesn't seem to be installed on this system. AI Studio can help you install the correct version. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3355132094"] = "Pandoc doesn't seem to be installed on this system. AI Studio can help you install the correct version." + +-- Close +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3448155331"] = "Close" + +-- Pandoc is installed and the version meets the requirements of MindWork AI Studio. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3653795841"] = "Pandoc is installed and the version meets the requirements of MindWork AI Studio." + +-- Pandoc is installed, but the version is too old and does not meet the requirements of MindWork AI Studio. AI Studio can help you install a newer version. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3692691761"] = "Pandoc is installed, but the version is too old and does not meet the requirements of MindWork AI Studio. AI Studio can help you install a newer version." + +-- Execute the installer and follow the instructions. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3730261061"] = "Execute the installer and follow the instructions." + +-- If you want to install Pandoc yourself, follow one of these two guides. The first guide uses an installer and is available for Windows and macOS. Alternatively, you might use a package manager of your operating system to install Pandoc. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3780227601"] = "If you want to install Pandoc yourself, follow one of these two guides. The first guide uses an installer and is available for Windows and macOS. Alternatively, you might use a package manager of your operating system to install Pandoc." + +-- Download installer +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3791603277"] = "Download installer" + +-- Accept the GPL and download the archive +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3987456907"] = "Accept the GPL and download the archive" + +-- Reject Pandoc's Licence +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T4092049320"] = "Reject Pandoc's Licence" + +-- Proceed to the installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T4134878031"] = "Proceed to the installation" + +-- Re-install Pandoc +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T4152693089"] = "Re-install Pandoc" + +-- Accept the terms of the GPL license and download the latest installer with the download button below. Eventually, you need to allow the download of the installer in the download window. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T504404155"] = "Accept the terms of the GPL license and download the latest installer with the download button below. Eventually, you need to allow the download of the installer in the download window." + +-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and archive," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T523908375"] = "Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking \"Accept GPL and archive,\" you agree to the terms of the GPL license. Software under GPL is free of charge and free to use." + -- Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T1458195391"] = "Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally." @@ -4033,6 +4171,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1772678682"] = "This library is used t -- By clicking on the respective path, the path is copied to the clipboard. You might open these files with a text editor to view their contents. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1806897624"] = "By clicking on the respective path, the path is copied to the clipboard. You might open these files with a text editor to view their contents." +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T185447014"] = "Pandoc Installation" + -- Check for updates UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1890416390"] = "Check for updates" @@ -4051,6 +4192,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2173617769"] = "This library is used t -- For the secure communication between the user interface and the runtime, we need to create certificates. This Rust library is great for this purpose. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2174764529"] = "For the secure communication between the user interface and the runtime, we need to create certificates. This Rust library is great for this purpose." +-- OK +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2246359087"] = "OK" + -- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2273492381"] = "We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose." @@ -4063,6 +4207,12 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2329884315"] = "The C# language is use -- Used PDFium version UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2368247719"] = "Used PDFium version" +-- installation provided by the system +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2371107659"] = "installation provided by the system" + +-- Installed Pandoc version: Pandoc is not installed or not available. +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2374031539"] = "Installed Pandoc version: Pandoc is not installed or not available." + -- This library is used to determine the language of the operating system. This is necessary to set the language of the user interface. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2557014401"] = "This library is used to determine the language of the operating system. This is necessary to set the language of the user interface." @@ -4084,6 +4234,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2706940196"] = "Logbook" -- This component is used to render Markdown text. This is important because the LLM often responds with Markdown-formatted text, allowing us to present it in a way that is easier to read. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2726131107"] = "This component is used to render Markdown text. This is important because the LLM often responds with Markdown-formatted text, allowing us to present it in a way that is easier to read." +-- Determine Pandoc version, please wait... +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2765814390"] = "Determine Pandoc version, please wait..." + -- Code in the Rust language can be specified as synchronous or asynchronous. Unlike .NET and the C# language, Rust cannot execute asynchronous code by itself. Rust requires support in the form of an executor for this. Tokio is one such executor. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2777988282"] = "Code in the Rust language can be specified as synchronous or asynchronous. Unlike .NET and the C# language, Rust cannot execute asynchronous code by itself. Rust requires support in the form of an executor for this. Tokio is one such executor." @@ -4108,6 +4261,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T313276297"] = "Connect AI Studio to yo -- Have feature ideas? Submit suggestions for future AI Studio enhancements. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3178730036"] = "Have feature ideas? Submit suggestions for future AI Studio enhancements." +-- Update Pandoc +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3249965383"] = "Update Pandoc" + -- Discover MindWork AI's mission and vision on our official homepage. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3294830584"] = "Discover MindWork AI's mission and vision on our official homepage." @@ -4129,9 +4285,18 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3563271893"] = "Motivation" -- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3722989559"] = "This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat." +-- this version does not met the requirements +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3813932670"] = "this version does not met the requirements" + -- Now we have multiple systems, some developed in .NET and others in Rust. The data format JSON is responsible for translating data between both worlds (called data serialization and deserialization). Serde takes on this task in the Rust world. The counterpart in the .NET world is an integral part of .NET and is located in System.Text.Json. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3908558992"] = "Now we have multiple systems, some developed in .NET and others in Rust. The data format JSON is responsible for translating data between both worlds (called data serialization and deserialization). Serde takes on this task in the Rust world. The counterpart in the .NET world is an integral part of .NET and is located in System.Text.Json." +-- Installed Pandoc version +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3983971016"] = "Installed Pandoc version" + +-- Check Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3986423270"] = "Check Pandoc Installation" + -- Versions UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T4010195468"] = "Versions" @@ -4159,9 +4324,15 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T639371534"] = "Did you find a bug or a -- This Rust library is used to output the app's messages to the terminal. This is helpful during development and troubleshooting. This feature is initially invisible; when the app is started via the terminal, the messages become visible. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T64689067"] = "This Rust library is used to output the app's messages to the terminal. This is helpful during development and troubleshooting. This feature is initially invisible; when the app is started via the terminal, the messages become visible." +-- installed by AI Studio +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T833849470"] = "installed by AI Studio" + -- For some data transfers, we need to encode the data in base64. This Rust library is great for this purpose. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T870640199"] = "For some data transfers, we need to encode the data in base64. This Rust library is great for this purpose." +-- Install Pandoc +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T986578435"] = "Install Pandoc" + -- Get coding and debugging support from an LLM. UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1243850917"] = "Get coding and debugging support from an LLM." @@ -4996,6 +5167,42 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::ERICLIENTV1::T816853779"] = "Failed -- Failed to retrieve the authentication methods: the ERI server did not return a valid response. UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::ERICLIENTV1::T984407320"] = "Failed to retrieve the authentication methods: the ERI server did not return a valid response." +-- Was not able to validate the Pandoc installation. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T1364844008"] = "Was not able to validate the Pandoc installation." + +-- Installers are not available on {0} systems. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T1640771881"] = "Installers are not available on {0} systems." + +-- Pandoc v{0} was installed successfully. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T1885555132"] = "Pandoc v{0} was installed successfully." + +-- Was not able to check the Pandoc installation. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2171727146"] = "Was not able to check the Pandoc installation." + +-- Pandoc v{0} is installed, but it doesn't match the required version (v{1}). +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2299898115"] = "Pandoc v{0} is installed, but it doesn't match the required version (v{1})." + +-- Pandoc v{0} is installed. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2550598062"] = "Pandoc v{0} is installed." + +-- Pandoc v{0} is installed, but it does not match the required version (v{1}). +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2555465873"] = "Pandoc v{0} is installed, but it does not match the required version (v{1})." + +-- Pandoc was not installed successfully, because the archive was not found. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T34210248"] = "Pandoc was not installed successfully, because the archive was not found." + +-- Pandoc is not available on the system or the process had issues. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T3746116957"] = "Pandoc is not available on the system or the process had issues." + +-- Pandoc was not installed successfully, because the archive type is unknown. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T3962211670"] = "Pandoc was not installed successfully, because the archive type is unknown." + +-- It seems that Pandoc is not installed. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T567205144"] = "It seems that Pandoc is not installed." + +-- The latest Pandoc version was not found, installing version {0} instead. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T726914939"] = "The latest Pandoc version was not found, installing version {0} instead." + -- The table AUTHORS does not exist or is using an invalid syntax. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T1068328139"] = "The table AUTHORS does not exist or is using an invalid syntax." diff --git a/app/MindWork AI Studio/Components/CodeBlock.razor b/app/MindWork AI Studio/Components/CodeBlock.razor index f0a4167a..d2b73745 100644 --- a/app/MindWork AI Studio/Components/CodeBlock.razor +++ b/app/MindWork AI Studio/Components/CodeBlock.razor @@ -1,15 +1,22 @@ - -@if (!this.IsInline) +@if (!this.IsInline) { @if (this.ParentTabs is null) { - -
@this.ChildContent
+ +
+                
+                    @this.ChildContent
+                
+            
} } else { - @this.ChildContent + + + @this.ChildContent + + } diff --git a/app/MindWork AI Studio/Components/CodeBlock.razor.cs b/app/MindWork AI Studio/Components/CodeBlock.razor.cs index 705e6310..cddad095 100644 --- a/app/MindWork AI Studio/Components/CodeBlock.razor.cs +++ b/app/MindWork AI Studio/Components/CodeBlock.razor.cs @@ -33,8 +33,5 @@ public partial class CodeBlock : ComponentBase } } - private string BlockPadding() - { - return this.ParentTabs is null ? "padding: 16px !important;" : "padding: 8px !important"; - } + private string BlockPadding => this.ParentTabs is null ? "padding: 16px !important;" : "padding: 8px !important"; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/CodeTabs.razor b/app/MindWork AI Studio/Components/CodeTabs.razor index 7223cecb..ea5fde2d 100644 --- a/app/MindWork AI Studio/Components/CodeTabs.razor +++ b/app/MindWork AI Studio/Components/CodeTabs.razor @@ -1,5 +1,5 @@ - - @foreach (var block in blocks) + + @foreach (var block in this.blocks) { @block.Fragment diff --git a/app/MindWork AI Studio/Components/CodeTabs.razor.cs b/app/MindWork AI Studio/Components/CodeTabs.razor.cs index 28f5a12a..668ee84a 100644 --- a/app/MindWork AI Studio/Components/CodeTabs.razor.cs +++ b/app/MindWork AI Studio/Components/CodeTabs.razor.cs @@ -7,8 +7,13 @@ public partial class CodeTabs : ComponentBase [Parameter] public RenderFragment? ChildContent { get; set; } + [Parameter] + public int SelectedIndex { get; set; } + + [Parameter] + public EventCallback SelectedIndexChanged { get; set; } + private readonly List blocks = new(); - private int selectedIndex; internal void RegisterBlock(string title, RenderFragment fragment) { @@ -27,4 +32,11 @@ public partial class CodeTabs : ComponentBase public RenderFragment Fragment { get; init; } = null!; } + + private async Task TabChanged(int index) + { + this.SelectedIndex = index; + await this.SelectedIndexChanged.InvokeAsync(index); + await this.InvokeAsync(this.StateHasChanged); + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ExpansionPanel.razor b/app/MindWork AI Studio/Components/ExpansionPanel.razor index 713444ea..329bfd08 100644 --- a/app/MindWork AI Studio/Components/ExpansionPanel.razor +++ b/app/MindWork AI Studio/Components/ExpansionPanel.razor @@ -1,4 +1,4 @@ - +
diff --git a/app/MindWork AI Studio/Components/ExpansionPanel.razor.cs b/app/MindWork AI Studio/Components/ExpansionPanel.razor.cs index 6a8e1d4f..a8ba6a2f 100644 --- a/app/MindWork AI Studio/Components/ExpansionPanel.razor.cs +++ b/app/MindWork AI Studio/Components/ExpansionPanel.razor.cs @@ -16,6 +16,12 @@ public partial class ExpansionPanel : ComponentBase [Parameter] public string HeaderText { get; set; } = "n/a"; + [Parameter] + public int? MaxHeight { get; set; } + + [Parameter] + public Func ExpandedChanged { get; set; } = _ => Task.CompletedTask; + [Parameter] public RenderFragment? ChildContent { get; set; } diff --git a/app/MindWork AI Studio/Components/ManagePandocDependency.razor b/app/MindWork AI Studio/Components/ManagePandocDependency.razor new file mode 100644 index 00000000..7208b1c4 --- /dev/null +++ b/app/MindWork AI Studio/Components/ManagePandocDependency.razor @@ -0,0 +1,10 @@ +@inherits MSGComponentBase + + + + @this.DetermineIntroText() + + + @this.DetermineButtonText() + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ManagePandocDependency.razor.cs b/app/MindWork AI Studio/Components/ManagePandocDependency.razor.cs new file mode 100644 index 00000000..886b1ff4 --- /dev/null +++ b/app/MindWork AI Studio/Components/ManagePandocDependency.razor.cs @@ -0,0 +1,97 @@ +using AIStudio.Dialogs; +using AIStudio.Tools.Services; + +using Microsoft.AspNetCore.Components; + +using DialogOptions = AIStudio.Dialogs.DialogOptions; + +namespace AIStudio.Components; + +public partial class ManagePandocDependency : MSGComponentBase +{ + [Parameter] + public string IntroText { get; set; } = string.Empty; + + [Inject] + private IDialogService DialogService { get; init; } = null!; + + [Inject] + private RustService RustService { get; init; } = null!; + + private PandocInstallation pandocInstallation; + + #region Overrides of MSGComponentBase + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + this.pandocInstallation = await Pandoc.CheckAvailabilityAsync(this.RustService, false); + } + + #endregion + + private Color DetermineButtonColor() + { + if (this.pandocInstallation == default) + return Color.Default; + + switch (this.pandocInstallation) + { + case { CheckWasSuccessful: true, IsAvailable: true }: + return Color.Default; + + case { CheckWasSuccessful: true, IsAvailable: false }: + return Color.Warning; + + case { CheckWasSuccessful: false }: + return Color.Error; + } + } + + private string DetermineButtonText() + { + if(this.pandocInstallation == default) + return T("Please wait while we check the availability of Pandoc."); + + switch (this.pandocInstallation) + { + case { CheckWasSuccessful: true, IsAvailable: true }: + return T("Check your Pandoc installation"); + + case { CheckWasSuccessful: true, IsAvailable: false }: + return T("Update Pandoc"); + + case { CheckWasSuccessful: false }: + return T("Install Pandoc"); + } + } + + private string DetermineIntroText() + { + if (this.pandocInstallation == default) + return $"{this.IntroText} {T("Please wait while we check the availability of Pandoc.")}"; + + switch (this.pandocInstallation) + { + case { CheckWasSuccessful: true, IsAvailable: true }: + return $"{this.IntroText} {T("Your Pandoc installation meets the requirements.")}"; + + case { CheckWasSuccessful: true, IsAvailable: false }: + return $"{this.IntroText} {T("Your Pandoc installation is outdated. Please update it to the latest version to ensure compatibility with all features.")}"; + + case { CheckWasSuccessful: false }: + return $"{this.IntroText} {T("Pandoc is not installed or not available. Please install it to use the features that require Pandoc.")}"; + } + } + + private async Task ShowPandocDialogAsync() + { + var dialogReference = await this.DialogService.ShowAsync(T("Pandoc Installation"), DialogOptions.FULLSCREEN); + await dialogReference.Result; + + // Refresh the availability of Pandoc after the dialog is closed: + this.pandocInstallation = await Pandoc.CheckAvailabilityAsync(this.RustService, false); + + await this.InvokeAsync(this.StateHasChanged); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor index badb9b80..d21244de 100644 --- a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor +++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor @@ -60,6 +60,8 @@ } } + + @foreach (var policy in Enum.GetValues()) diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor index 1325a336..ccff69e9 100644 --- a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor +++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor @@ -60,6 +60,8 @@ } } + + @foreach (var policy in Enum.GetValues()) diff --git a/app/MindWork AI Studio/Dialogs/PandocDialog.razor b/app/MindWork AI Studio/Dialogs/PandocDialog.razor index a9b64504..a27a0913 100644 --- a/app/MindWork AI Studio/Dialogs/PandocDialog.razor +++ b/app/MindWork AI Studio/Dialogs/PandocDialog.razor @@ -1,154 +1,229 @@ - - - Install Pandoc - +@inherits MSGComponentBase + + - @if (this.showInstallPage) + @if (this.isInstallationInProgress) + { + + @T("Please wait for the installation to complete...") + + + } + else if (this.ShowInstallationPage) {
- - AI Studio relies on the free and open-sourced third-party app Pandoc to process and retrieve data from local - Office files (ex. Word) and later other text formats like LaTeX. - - - Unfortunately Pandoc's GPL license is not compatible with AI Studios licences, nonetheless software under GPL is generally free to use and - free of charge as well. - Therefore you have to accept Pandoc's GPL license before we can download and install Pandoc for free - automatically for you (recommended). - However you can download it yourself manually with the instructions below. - - - - @if (this.isLoading) - { - - - - } - else if (!string.IsNullOrEmpty(this.licenseText)) - { - @this.licenseText - } - - + + @T("AI Studio uses the free and open-source third-party app Pandoc to process and retrieve data from local Office files (such as Word files) or to generate Office documents.") + + + @T("Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system.") +
+ - - - Pandoc is distributed under the - GNU General Public License v2 (GPL). - By clicking "Accept GPL and Install", you agree to the terms of the GPL license
and Pandoc - will be installed automatically for you. Software under GPL is free of charge and free to use.
-
- - Accept GPL and install for free + + @if (this.isLoadingLicence) + { + + + + } + else if (!string.IsNullOrWhiteSpace(this.licenseText)) + { + + } + + + + + @T("""Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and Install," you agree to the terms of the GPL license, and Pandoc will be installed automatically for you. Software under GPL is free of charge and free to use.""") + + + @T("Accept the GPL and start the installation") - - - If you prefer to install Pandoc yourself, please follow one of these two guides. Installers are only available for Windows and Mac. - + + + + @T("If you want to install Pandoc yourself, follow one of these two guides. The first guide uses an installer and is available for Windows and macOS. Alternatively, you might use a package manager of your operating system to install Pandoc.") + + - + - Accept the terms of the GPL license and download the latest installer with the download button below. - Eventually you need to allow the download of the installer in the download window. - - pandoc-@(PANDOC_VERSION)-windows-x86_64.msi - pandoc-@(PANDOC_VERSION)-x86_64-macOS.pkg - pandoc-@(PANDOC_VERSION)-arm64-macOS.pkg + + @T("Accept the terms of the GPL license and download the latest installer with the download button below. Eventually, you need to allow the download of the installer in the download window.") + + + pandoc-@(LATEST_PANDOC_VERSION)-windows-x86_64.msi + pandoc-@(LATEST_PANDOC_VERSION)-arm64-macOS.pkg + pandoc-@(LATEST_PANDOC_VERSION)-x86_64-macOS.pkg - Execute the installer and follow the instructions. + + @T("Execute the installer and follow the instructions.") + - - Pandoc is distributed under the GNU General Public License v2 (GPL). - By clicking "Accept GPL and download installer", you agree to the terms of the GPL license. Software under GPL is free of charge and free to use.
-
- - Accept GPL and download installer + + + @T("""Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and download installer," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use.""") + + + + @T("Accept the GPL and download the installer")
- + + - Accept the terms of the GPL license and download the latest archive with the download button below. + + @T("Accept the terms of the GPL license and download the latest archive with the download button below.") + + - Extract the archive to a folder of your choice. - + + @T("Extract the archive to a folder of your choice, e.g.:") + + C:\Users\%USERNAME%\pandoc - /usr/local/bin/pandoc + ~/pandoc /usr/local/bin/pandoc + - Open the folder and copy the full path to the pandoc.exe file into your - clipboard. - - C:\Users\%USERNAME%\pandoc\pandoc-@(PANDOC_VERSION) - /usr/local/bin/pandoc/pandoc-@(PANDOC_VERSION) - /usr/local/bin/pandoc/pandoc-@(PANDOC_VERSION) + + @T("Open the folder and copy the full path to the folder where your Pandoc executable file is into your clipboard:") + + + C:\Users\%USERNAME%\pandoc\pandoc-@(LATEST_PANDOC_VERSION) + ~/pandoc/pandoc-@(LATEST_PANDOC_VERSION) + /usr/local/bin/pandoc/pandoc-@(LATEST_PANDOC_VERSION) + - Add the copied path to your systems environment variables and check the installation - by typing
pandoc --version - into your command line interface. - - > pandoc.exe --version
> pandoc.exe @(PANDOC_VERSION)
- > pandoc --version
> pandoc.exe @(PANDOC_VERSION)
- > pandoc --version
> pandoc.exe @(PANDOC_VERSION)
+ + @T("Add the copied path to your system's or user's PATH environment variable, restart your terminal, and check the installation:") + + + > pandoc.exe --version
> pandoc @(LATEST_PANDOC_VERSION)
+ > pandoc --version
> pandoc @(LATEST_PANDOC_VERSION)
+ > pandoc --version
> pandoc @(LATEST_PANDOC_VERSION)
+ - Pandoc is distributed under the GNU General Public License v2 (GPL). - By clicking "Accept GPL and archive", you agree to the terms of the GPL license. Software under GPL is free of charge and free to use.
+ + @T("""Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and archive," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use.""") +
- - Accept GPL and download archive + + + @T("Accept the GPL and download the archive")
-
- Reject GPL licence -
} else { - - @if (showSkeleton) + + @if (this.pandocInstallation == default) { - - - } - else if (isPandocAvailable) - { - - - Pandoc ist auf Ihrem System verfügbar - + + + + + + + + + } else { - - - Pandoc ist auf Ihrem System nicht verfügbar - - - Proceed to installation - + switch (this.pandocInstallation) + { + case { CheckWasSuccessful: true, IsAvailable: true }: + + + + @T("Pandoc is installed and the version meets the requirements of MindWork AI Studio.") + + + break; + + case { CheckWasSuccessful: true, IsAvailable: false }: + + + + @T("Pandoc is installed, but the version is too old and does not meet the requirements of MindWork AI Studio. AI Studio can help you install a newer version.") + + + break; + + case { CheckWasSuccessful: false }: + + + + @T("Pandoc doesn't seem to be installed on this system. AI Studio can help you install the correct version.") + + + break; + } } }
+ + @if (this.isInstallationInProgress) + { + + @T("Close") + + } + else if (this.ShowInstallationPage) + { + + @T("Close") + + + + @T("Reject the GPL licence") + + } + else + { + + @T("Close") + + + @if (this.pandocInstallation != default) + { + switch (this.pandocInstallation) + { + case { CheckWasSuccessful: true, IsAvailable: false }: + case { CheckWasSuccessful: false, IsAvailable: false }: + + @T("Proceed to the installation") + + break; + + case { CheckWasSuccessful: true, IsAvailable: true }: + + @T("Re-install Pandoc") + + break; + } + } + } +
\ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/PandocDialog.razor.cs b/app/MindWork AI Studio/Dialogs/PandocDialog.razor.cs index 9226074c..ae048016 100644 --- a/app/MindWork AI Studio/Dialogs/PandocDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/PandocDialog.razor.cs @@ -1,19 +1,32 @@ -using AIStudio.Tools.Services; +using System.Reflection; + +using AIStudio.Components; +using AIStudio.Tools.Metadata; +using AIStudio.Tools.Services; using Microsoft.AspNetCore.Components; +using SharedTools; + namespace AIStudio.Dialogs; -public partial class PandocDialog : ComponentBase +public partial class PandocDialog : MSGComponentBase { + private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly(); + private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute()!; + private static readonly RID CPU_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID(); + + [Parameter] + public bool ShowInstallationPage { get; set; } + + [Parameter] + public bool ShowInitialResultInSnackbar { get; set; } = true; + [Inject] private HttpClient HttpClient { get; set; } = null!; [Inject] private RustService RustService { get; init; } = null!; - [Inject] - protected IJSRuntime JsRuntime { get; init; } = null!; - [Inject] private IDialogService DialogService { get; init; } = null!; @@ -21,107 +34,98 @@ public partial class PandocDialog : ComponentBase private IMudDialogInstance MudDialog { get; set; } = null!; private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger("PandocDialog"); - private static readonly string LICENCE_URI = "https://raw.githubusercontent.com/jgm/pandoc/master/COPYRIGHT"; - private static string PANDOC_VERSION = "1.0.0"; + private static readonly string LICENCE_URI = "https://raw.githubusercontent.com/jgm/pandoc/refs/heads/main/COPYING.md"; + private static string LATEST_PANDOC_VERSION = string.Empty; - private bool isPandocAvailable; - private bool showSkeleton; - private bool showInstallPage; + private PandocInstallation pandocInstallation; private string? licenseText; - private bool isLoading; + private bool isLoadingLicence; + private bool isInstallationInProgress; + private int selectedInstallerIndex = SelectInstallerIndex(); + private int selectedArchiveIndex = SelectArchiveIndex(); + private string downloadUrlArchive = string.Empty; + private string downloadUrlInstaller = string.Empty; #region Overrides of ComponentBase protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - this.showSkeleton = true; - await this.CheckPandocAvailabilityAsync(); - PANDOC_VERSION = await Pandoc.FetchLatestVersionAsync(); + + LATEST_PANDOC_VERSION = await Pandoc.FetchLatestVersionAsync(); + await this.CheckPandocAvailabilityAsync(this.ShowInitialResultInSnackbar); } #endregion private void Cancel() => this.MudDialog.Cancel(); - private async Task CheckPandocAvailabilityAsync() + private async Task CheckPandocAvailabilityAsync(bool useSnackbar) { - this.isPandocAvailable = await Pandoc.CheckAvailabilityAsync(this.RustService); - this.showSkeleton = false; + this.pandocInstallation = await Pandoc.CheckAvailabilityAsync(this.RustService, useSnackbar); await this.InvokeAsync(this.StateHasChanged); } private async Task InstallPandocAsync() { + this.isInstallationInProgress = true; + this.StateHasChanged(); + await Pandoc.InstallAsync(this.RustService); + + this.isInstallationInProgress = false; this.MudDialog.Close(DialogResult.Ok(true)); - await this.DialogService.ShowAsync("pandoc dialog"); + await this.DialogService.ShowAsync("Pandoc Installation", DialogOptions.FULLSCREEN); } - private void ProceedToInstallation() => this.showInstallPage = true; - - private async Task GetInstaller() - { - var uri = await Pandoc.GenerateInstallerUriAsync(); - var filename = this.FilenameFromUri(uri); - await this.JsRuntime.InvokeVoidAsync("triggerDownload", uri, filename); - } - - private async Task GetArchive() - { - var uri = await Pandoc.GenerateUriAsync(); - var filename = this.FilenameFromUri(uri); - await this.JsRuntime.InvokeVoidAsync("triggerDownload", uri, filename); - } + private void ProceedToInstallation() => this.ShowInstallationPage = true; private async Task RejectLicense() { - var message = "Pandoc is open-source and free of charge, but if you reject Pandoc's license, it can not be installed and some of AIStudios data retrieval features will be disabled (e.g. using Office files like Word)." + - "This decision can be revoked at any time. Are you sure you want to reject the license?"; - + var message = T("Pandoc is open-source and free, but if you reject its license, you can't install it and some MindWork AI Studio features will be limited (like the integration of Office files) or unavailable (like the generation of Office files). You can change your decision anytime. Are you sure you want to reject the license?"); var dialogParameters = new DialogParameters { { "Message", message }, }; - var dialogReference = await this.DialogService.ShowAsync("Reject Pandoc's licence", dialogParameters, DialogOptions.FULLSCREEN); + var dialogReference = await this.DialogService.ShowAsync(T("Reject Pandoc's Licence"), dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; if (dialogResult is null || dialogResult.Canceled) dialogReference.Close(); else this.Cancel(); } - - private string FilenameFromUri(string uri) + + private async Task WhenExpandingManualInstallation(bool isExpanded) { - var index = uri.LastIndexOf('/'); - return uri[(index + 1)..]; + if(string.IsNullOrWhiteSpace(this.downloadUrlArchive)) + this.downloadUrlArchive = await Pandoc.GenerateArchiveUriAsync(); + + if(string.IsNullOrWhiteSpace(this.downloadUrlInstaller)) + this.downloadUrlInstaller = await Pandoc.GenerateInstallerUriAsync(); } - private async Task OnExpandedChanged(bool isExpanded) + private async Task WhenExpandingLicence(bool isExpanded) { if (isExpanded) { - this.isLoading = true; + this.isLoadingLicence = true; try { - await Task.Delay(600); - this.licenseText = await this.LoadLicenseTextAsync(); } catch (Exception ex) { - this.licenseText = "Error loading license text, please consider following the links to read the GPL."; - LOG.LogError("Error loading GPL license text:\n{ErrorMessage}", ex.Message); + this.licenseText = T("Error loading license text, please consider following the links to read the GPL."); + LOG.LogError("Error loading GPL license text: {ErrorMessage}", ex.Message); } finally { - this.isLoading = false; + this.isLoadingLicence = false; } } else { - await Task.Delay(350); this.licenseText = string.Empty; } } @@ -130,7 +134,34 @@ public partial class PandocDialog : ComponentBase { var response = await this.HttpClient.GetAsync(LICENCE_URI); response.EnsureSuccessStatusCode(); - var content = await response.Content.ReadAsStringAsync(); - return content; + + return await response.Content.ReadAsStringAsync(); } + + // ReSharper disable RedundantSwitchExpressionArms + private static int SelectInstallerIndex() => CPU_ARCHITECTURE switch + { + RID.OSX_ARM64 => 1, + RID.OSX_X64 => 2, + + RID.WIN_ARM64 => 0, + RID.WIN_X64 => 0, + + _ => 0, + }; + + private static int SelectArchiveIndex() => CPU_ARCHITECTURE switch + { + RID.OSX_ARM64 => 1, + RID.OSX_X64 => 1, + + RID.WIN_ARM64 => 0, + RID.WIN_X64 => 0, + + RID.LINUX_ARM64 => 2, + RID.LINUX_X64 => 2, + + _ => 0, + }; + // ReSharper restore RedundantSwitchExpressionArms } \ No newline at end of file diff --git a/app/MindWork AI Studio/Pages/About.razor b/app/MindWork AI Studio/Pages/About.razor index 0f5329d0..ff764e0c 100644 --- a/app/MindWork AI Studio/Pages/About.razor +++ b/app/MindWork AI Studio/Pages/About.razor @@ -19,13 +19,19 @@ + - - @T("Check for updates") - + + + @T("Check for updates") + + + @this.PandocButtonText + + diff --git a/app/MindWork AI Studio/Pages/About.razor.cs b/app/MindWork AI Studio/Pages/About.razor.cs index 66657077..7a65d05f 100644 --- a/app/MindWork AI Studio/Pages/About.razor.cs +++ b/app/MindWork AI Studio/Pages/About.razor.cs @@ -1,6 +1,7 @@ using System.Reflection; using AIStudio.Components; +using AIStudio.Dialogs; using AIStudio.Tools.Metadata; using AIStudio.Tools.Rust; using AIStudio.Tools.Services; @@ -9,6 +10,8 @@ using Microsoft.AspNetCore.Components; using SharedTools; +using DialogOptions = AIStudio.Dialogs.DialogOptions; + namespace AIStudio.Pages; public partial class About : MSGComponentBase @@ -16,6 +19,9 @@ public partial class About : MSGComponentBase [Inject] private RustService RustService { get; init; } = null!; + [Inject] + private IDialogService DialogService { get; init; } = null!; + [Inject] private ISnackbar Snackbar { get; init; } = null!; @@ -23,6 +29,8 @@ public partial class About : MSGComponentBase private static readonly MetaDataAttribute META_DATA = ASSEMBLY.GetCustomAttribute()!; private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute()!; private static readonly MetaDataLibrariesAttribute META_DATA_LIBRARIES = ASSEMBLY.GetCustomAttribute()!; + + private static string TB(string fallbackEN) => Tools.PluginSystem.I18N.I.T(fallbackEN, typeof(About).Namespace, nameof(About)); private string osLanguage = string.Empty; @@ -43,6 +51,9 @@ public partial class About : MSGComponentBase private string BuildTime => $"{T("Build time")}: {META_DATA.BuildTime}"; private string VersionPdfium => $"{T("Used PDFium version")}: v{META_DATA_LIBRARIES.PdfiumVersion}"; + + private string versionPandoc = TB("Determine Pandoc version, please wait..."); + private PandocInstallation pandocInstallation; private GetLogPathsResponse logPaths; @@ -52,11 +63,59 @@ public partial class About : MSGComponentBase { this.osLanguage = await this.RustService.ReadUserLanguage(); this.logPaths = await this.RustService.GetLogPaths(); + await base.OnInitializedAsync(); + await this.DeterminePandocVersion(); } #endregion + private async Task DeterminePandocVersion() + { + this.pandocInstallation = await Pandoc.CheckAvailabilityAsync(this.RustService, false); + var pandocInstallationType = this.pandocInstallation.IsLocalInstallation + ? T("installed by AI Studio") + : T("installation provided by the system"); + + switch (this.pandocInstallation) + { + case { CheckWasSuccessful: true, IsAvailable: true }: + this.versionPandoc = $"{this.T("Installed Pandoc version")}: v{this.pandocInstallation.Version} ({pandocInstallationType}) - {T("OK")}"; + break; + + case { CheckWasSuccessful: true, IsAvailable: false }: + this.versionPandoc = $"{this.T("Installed Pandoc version")}: v{this.pandocInstallation.Version} ({pandocInstallationType}) - {T("this version does not met the requirements")}"; + break; + + default: + this.versionPandoc = TB("Installed Pandoc version: Pandoc is not installed or not available."); + break; + } + + await this.InvokeAsync(this.StateHasChanged); + } + + private string PandocButtonText + { + get + { + return this.pandocInstallation switch + { + { IsAvailable: true, CheckWasSuccessful: true } => this.T("Check Pandoc Installation"), + { IsAvailable: false, CheckWasSuccessful: true } => this.T("Update Pandoc"), + + _ => this.T("Install Pandoc") + }; + } + } + + private async Task ShowPandocDialog() + { + var dialogReference = await this.DialogService.ShowAsync(T("Pandoc Installation"), DialogOptions.FULLSCREEN); + await dialogReference.Result; + await this.DeterminePandocVersion(); + } + private async Task CopyStartupLogPath() { await this.RustService.CopyText2Clipboard(this.Snackbar, this.logPaths.LogStartupPath); diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index 27a02a78..02f9c9e1 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -486,6 +486,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ALLOWEDLLMPROVIDERSEXTENSIONS::T4096 -- Please describe at least one retrieval process. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1035068989"] = "Bitte beschreiben Sie mindestens einen Abrufprozess." +-- Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1047217452"] = "Lokale oder selbst gehostete Modelle funktionieren möglicherweise ohne diese Einschränkungen und können schneller Antworten generieren. AI Studio passt sein Verhalten dynamisch an und versucht stets, die schnellstmögliche Datenverarbeitung zu erreichen." + -- Please select which types of LLMs users are allowed to use with the data from this ERI server. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1047631678"] = "Bitte wählen Sie aus, welche Typen von LLMs mit den Daten dieses ERI-Servers verwendet werden dürfen." @@ -513,9 +516,6 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1261836894"] = "Bitte -- You have not yet added any ERI server presets. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1267931972"] = "Sie haben bislang keine ERI-Server-Voreinstellung hinzugefügt." --- Warning: Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user). -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1287629674"] = "Warnung: Ports unter 1024 sind für Systemdienste reserviert. Ihr ERI-Server muss mit erhöhten Rechten (als Root-Benutzer) ausgeführt werden." - -- The task of writing the ERI server for you is very complex. Therefore, a very powerful LLM is needed to successfully accomplish this task. Small local models will probably not be sufficient. Instead, try using a large cloud-based or a large self-hosted model. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1302705248"] = "Die Aufgabe, den ERI-Server für Sie zu schreiben, ist sehr komplex. Daher wird ein sehr leistungsfähiges LLM benötigt, um diese Aufgabe erfolgreich zu bewältigen. Kleine lokale Modelle werden dafür wahrscheinlich nicht ausreichen. Versuchen Sie stattdessen, ein großes Cloud-basiertes oder ein großes selbst gehostetes Modell zu verwenden." @@ -537,12 +537,18 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1456749976"] = "Bitte -- Delete UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1469573738"] = "Löschen" +-- When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1531680404"] = "Wenn Sie den ERI-Server-Code neu erstellen oder generieren, geht AI Studio wie folgt vor: Alle beim letzten Mal generierten Dateien werden gelöscht. Alle anderen von ihnen erstellten Dateien bleiben erhalten. Anschließend generiert die KI die neuen Dateien." + -- Related links: UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1565111217"] = "Relevante Links:" -- Please select an ERI specification version for the ERI server. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1612890554"] = "Bitte wählen Sie eine Version der ERI-Spezifikation für den ERI-Server aus." +-- Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user). +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T168780641"] = "Ports unterhalb von 1024 sind für Systemdienste reserviert. Ihr ERI-Server muss mit erhöhten Rechten (als Root-Benutzer) ausgeführt werden." + -- Write code to file system UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1717303021"] = "Code in das Dateisystem schreiben" @@ -564,6 +570,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T180938091"] = "Abrufp -- Provider selection for generation UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1840198821"] = "Anbieterauswahl für die Generierung" +-- However, generating all the files takes a certain amount of time. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1862007299"] = "Das Erzeugen aller Dateien benötigt jedoch eine gewisse Zeit." + -- Should we automatically save any input made? UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1980659256"] = "Sollen wir sämtliche Eingaben automatisch speichern?" @@ -579,8 +588,8 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2034620186"] = "Daten -- Interactive documentation aka Swagger UI UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2064957876"] = "Interaktive Dokumentation (auch bekannt als Swagger UI)" --- When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files. But beware: It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2155983785"] = "Wenn Sie den ERI-Server-Code neu erstellen oder generieren, geht AI Studio wie folgt vor: Alle beim letzten Mal generierten Dateien werden gelöscht. Alle anderen von ihnen erstellten Dateien bleiben erhalten. Anschließend generiert die KI die neuen Dateien. Aber Vorsicht: Es kann passieren, dass die KI diesmal eine Datei generiert, die Sie beim letzten Mal manuell erstellt haben. In diesem Fall wird ihre manuell erstellte Datei überschrieben. Sie sollten daher immer ein Git-Repository anlegen und alle Änderungen vor der Nutzung dieses Assistenten committen oder gegebenenfalls zurücksetzen. Mit einer Diff-Ansicht können Sie sofort erkennen, wo die KI Änderungen vorgenommen hat. Am besten nutzen Sie dafür eine IDE, die für die von ihnen gewählte Programmiersprache geeignet ist." +-- Warning: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2149175535"] = "Warnung:" -- Add Embedding Method UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2176833082"] = "Einbettungsmethode hinzufügen" @@ -609,6 +618,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2417944396"] = "Sind -- Data source settings UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2440619931"] = "Datenquellen-Einstellungen" +-- The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T248288139"] = "Das LLM muss möglicherweise viele Dateien generieren. Dadurch wird das Anfrage-Limit der meisten LLM-Anbieter erreicht. In der Regel kann nur eine bestimmte Anzahl von Anfragen pro Minute gestellt werden, und es dürfen nur eine maximale Anzahl von Tokens pro Minute erzeugt werden. AI Studio berücksichtigt dies automatisch." + -- Yes, please write or update all generated code to the file system UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T252707279"] = "Ja, bitte schreibe oder aktualisiere allen erzeugten Code im Dateisystem." @@ -684,18 +696,21 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3316699247"] = "Nein, -- Other language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3374524465"] = "Andere Sprache" +-- Important: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3379345517"] = "Wichtig:" + -- ERI Server {0} UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3443687246"] = "ERI-Server {0}" -- You will likely use one or more embedding methods to encode the meaning of your data into a typically high-dimensional vector space. In this case, you will use a vector database to store and search these vectors (called embeddings). However, you don't have to use embedding methods. When your retrieval method works without any embedding, you can ignore this section. An example: You store files on a file server, and your retrieval method works exclusively with file names in the file system, so you don't need embeddings. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3446047228"] = "Sie werden wahrscheinlich eine oder mehrere Einbettungs-Methoden verwenden, um die Bedeutung Ihrer Daten in einen typischerweise hochdimensionalen Vektorraum zu kodieren. In diesem Fall nutzen Sie eine Vektordatenbank, um diese Vektoren (sogenannte Einbettungen) zu speichern und zu durchsuchen. Es ist jedoch nicht zwingend erforderlich, Einbettungs-Methoden zu verwenden. Wenn ihre Suchmethode ohne Einbettungen funktioniert, können Sie diesen Abschnitt ignorieren. Ein Beispiel: Sie speichern Dateien auf einem Dateiserver, und ihre Suchmethode arbeitet ausschließlich mit Dateinamen im Dateisystem – dann benötigen Sie keine Einbettungen." --- Important: The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this. However, generating all the files takes a certain amount of time. Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3485079498"] = "Wichtig: Das LLM muss möglicherweise viele Dateien generieren. Dadurch wird das Anfrage-Limit der meisten LLM-Anbieter erreicht. In der Regel kann nur eine bestimmte Anzahl von Anfragen pro Minute gestellt werden, und es dürfen nur eine maximale Anzahl von Tokens pro Minute erzeugt werden. AI Studio berücksichtigt dies automatisch. Das Erzeugen aller Dateien benötigt jedoch eine gewisse Zeit. Lokale oder selbst gehostete Modelle funktionieren möglicherweise ohne diese Einschränkungen und können schneller antworten. AI Studio passt sein Verhalten dynamisch an und versucht immer, die Daten so schnell wie möglich zu verarbeiten." - -- Type UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3512062061"] = "Typ" +-- It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3541842180"] = "Es kann passieren, dass die KI diesmal eine Datei generiert, die Sie beim letzten Mal manuell erstellt haben. In diesem Fall wird ihre manuell erstellte Datei überschrieben. Sie sollten daher immer ein Git-Repository anlegen und alle Änderungen vor der Nutzung dieses Assistenten committen oder gegebenenfalls zurücksetzen. Mit einer Diff-Ansicht können Sie sofort erkennen, wo die KI Änderungen vorgenommen hat. Am besten nutzen Sie dafür eine IDE, die für die von ihnen gewählte Programmiersprache geeignet ist." + -- Please describe how the selected authentication methods should be used. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T356079033"] = "Bitte beschreiben Sie, wie die ausgewählten Authentifizierungsmethoden verwendet werden sollen." @@ -735,6 +750,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3865031940"] = "Aktio -- ERI specification version UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3897494556"] = "ERI-Spezifikations-Version" +-- But beware: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3956615326"] = "Aber Vorsicht:" + -- Please provide a description for your ERI server. What data will the server retrieve? This description will be used to inform users about the purpose of your ERI server. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3973182416"] = "Bitte geben Sie eine Beschreibung für Ihren ERI-Server an. Welche Daten wird der Server abrufen? Diese Beschreibung wird dazu verwendet, die Nutzer über den Zweck ihres ERI-Servers zu informieren." @@ -1521,6 +1539,30 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCESELECTION::T86053874"] = "Verf -- Issues UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ISSUES::T3229841001"] = "Probleme" +-- Your Pandoc installation meets the requirements. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T1167365374"] = "Ihre Pandoc-Installation erfüllt die Anforderungen." + +-- Please wait while we check the availability of Pandoc. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T1336364299"] = "Bitte warten Sie, während wir die Verfügbarkeit von Pandoc überprüfen." + +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T185447014"] = "Pandoc-Installation" + +-- Your Pandoc installation is outdated. Please update it to the latest version to ensure compatibility with all features. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T251757907"] = "Ihre Pandoc-Installation ist veraltet. Bitte aktualisieren Sie Pandoc auf die neueste Version, um die volle Kompatibilität mit allen Funktionen sicherzustellen." + +-- Pandoc is not installed or not available. Please install it to use the features that require Pandoc. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T3147551473"] = "Pandoc ist nicht installiert oder nicht verfügbar. Bitte installieren Sie Pandoc, um die Funktionen zu nutzen, die Pandoc erfordern." + +-- Update Pandoc +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T3249965383"] = "Pandoc aktualisieren" + +-- Check your Pandoc installation +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T527187983"] = "Überprüfen Sie Ihre Pandoc-Installation" + +-- Install Pandoc +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T986578435"] = "Pandoc installieren" + -- Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1057189794"] = "Da mein Arbeitgeber sowohl Windows als auch Linux am Arbeitsplatz nutzt, wollte ich eine plattformübergreifende Lösung, die nahtlos auf allen wichtigen Betriebssystemen, einschließlich macOS, funktioniert. Außerdem wollte ich zeigen, dass es möglich ist, moderne, effiziente und plattformübergreifende Anwendungen zu erstellen, ohne auf Software-Balast, wie z.B. das Electron-Framework, zurückzugreifen. Die Kombination aus .NET und Rust mit Tauri hat sich dabei als hervorragender Technologiestapel für den Bau solch robuster Anwendungen erwiesen." @@ -2439,6 +2481,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2814869210" -- Embedding UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2838542994"] = "Einbettung" +-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3359366900"] = "Für einige Dateitypen, wie zum Beispiel Office-Dateien, benötigt MindWork AI Studio die Open-Source-Anwendung Pandoc." + -- Yes, please send my data to the cloud UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3572613009"] = "Ja, bitte senden Sie meine Daten in die Cloud" @@ -2553,6 +2598,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2814869210"] = " -- Embedding UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2838542994"] = "Einbettung" +-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3359366900"] = "Für einige Dateitypen, wie zum Beispiel Office-Dateien, benötigt MindWork AI Studio die Open-Source-Anwendung Pandoc." + -- Yes, please send my data to the cloud UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3572613009"] = "Ja, bitte senden Sie meine Daten in die Cloud." @@ -2748,6 +2796,96 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900237532"] = "Anb -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900713019"] = "Abbrechen" +-- Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1001483402"] = "Leider ist die GPL-Lizenz von Pandoc nicht mit der Lizenz von AI Studio kompatibel. Software unter der GPL-Lizenz ist jedoch kostenlos und frei nutzbar. Sie müssen die GPL-Lizenz akzeptieren, bevor wir Pandoc automatisch für Sie herunterladen und installieren können (empfohlen). Alternativ können Sie Pandoc auch selbst herunterladen – entweder mit den untenstehenden Anweisungen oder auf anderem Weg, zum Beispiel über den Paketmanager Ihres Betriebssystems." + +-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and Install," you agree to the terms of the GPL license, and Pandoc will be installed automatically for you. Software under GPL is free of charge and free to use. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1357200670"] = "Pandoc wird unter der GNU General Public License v2 (GPL) vertrieben. Wenn Sie auf „GPL akzeptieren und installieren“ klicken, stimmen Sie den Bedingungen der GPL-Lizenz zu und Pandoc wird automatisch für Sie installiert. Software unter der GPL ist kostenlos und frei nutzbar." + +-- View the GNU General Public License v2 (GPL) +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1587398673"] = "GNU General Public License v2 (GPL) anzeigen" + +-- Reject the GPL licence +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1655899051"] = "GPL-Lizenz ablehnen" + +-- Automatic installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1780479836"] = "Automatische Installation" + +-- Manual installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1814127049"] = "Manuelle Installation" + +-- AI Studio uses the free and open-source third-party app Pandoc to process and retrieve data from local Office files (such as Word files) or to generate Office documents. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T205422394"] = "AI Studio verwendet die kostenlose und quelloffene Drittanbieter-Software Pandoc, um Daten aus lokalen Office-Dateien (wie Word-Dateien) zu verarbeiten und abzurufen oder um Office-Dokumente zu erstellen." + +-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and download installer," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2084501359"] = "Pandoc wird unter der GNU General Public License v2 (GPL) verbreitet. Wenn Sie auf „GPL akzeptieren und Installer herunterladen“ klicken, stimmen Sie den Bedingungen der GPL-Lizenz zu. Software unter der GPL ist kostenlos und frei nutzbar." + +-- Extract the archive to a folder of your choice, e.g.: +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2094245964"] = "Entpacken Sie das Archiv in einen Ordner Ihrer Wahl, z. B.:" + +-- Pandoc is open-source and free, but if you reject its license, you can't install it and some MindWork AI Studio features will be limited (like the integration of Office files) or unavailable (like the generation of Office files). You can change your decision anytime. Are you sure you want to reject the license? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2559178004"] = "Pandoc ist Open Source und kostenlos. Wenn Sie die Lizenz jedoch ablehnen, können Sie Pandoc nicht installieren. Dadurch werden einige Funktionen von MindWork AI Studio eingeschränkt (wie die Integration von Office-Dateien) oder stehen nicht zur Verfügung (wie das Erstellen von Office-Dateien). Sie können Ihre Entscheidung jederzeit ändern. Möchten Sie die Lizenz wirklich ablehnen?" + +-- Please wait for the installation to complete... +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2606205182"] = "Bitte warten Sie, bis die Installation abgeschlossen ist..." + +-- Open the folder and copy the full path to the folder where your Pandoc executable file is into your clipboard: +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2946844485"] = "Öffnen Sie den Ordner und kopieren Sie den vollständigen Pfad zu dem Ordner, in dem sich die Pandoc-Programmdatei befindet, in die Zwischenablage:" + +-- Accept the GPL and start the installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2966192331"] = "Akzeptieren Sie die GPL und starten Sie die Installation" + +-- Error loading license text, please consider following the links to read the GPL. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3054618024"] = "Fehler beim Laden des Lizenztexts. Bitte nutzen Sie die Links, um die GPL zu lesen." + +-- Accept the GPL and download the installer +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3104260405"] = "Akzeptieren Sie die GPL und laden Sie das Installationsprogramm herunter" + +-- Add the copied path to your system's or user's PATH environment variable, restart your terminal, and check the installation: +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T313476957"] = "Fügen Sie den kopierten Pfad zur PATH-Umgebungsvariable Ihres Systems oder Benutzers hinzu, starten Sie Ihr Terminal neu und überprüfen Sie die Installation:" + +-- Accept the terms of the GPL license and download the latest archive with the download button below. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3263447722"] = "Akzeptieren Sie die Bedingungen der GPL-Lizenz und laden Sie das neueste Archiv mit dem untenstehenden Download-Button herunter." + +-- Pandoc doesn't seem to be installed on this system. AI Studio can help you install the correct version. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3355132094"] = "Pandoc scheint auf diesem System nicht installiert zu sein. AI Studio kann ihnen helfen, die richtige Version zu installieren." + +-- Close +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3448155331"] = "Schließen" + +-- Pandoc is installed and the version meets the requirements of MindWork AI Studio. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3653795841"] = "Pandoc ist installiert und die Version entspricht den Anforderungen von MindWork AI Studio." + +-- Pandoc is installed, but the version is too old and does not meet the requirements of MindWork AI Studio. AI Studio can help you install a newer version. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3692691761"] = "Pandoc ist installiert, aber die Version ist zu alt und erfüllt nicht die Anforderungen von MindWork AI Studio. AI Studio kann ihnen helfen, eine neuere Version zu installieren." + +-- Execute the installer and follow the instructions. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3730261061"] = "Führen Sie das Installationsprogramm aus und folgen Sie den Anweisungen." + +-- If you want to install Pandoc yourself, follow one of these two guides. The first guide uses an installer and is available for Windows and macOS. Alternatively, you might use a package manager of your operating system to install Pandoc. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3780227601"] = "Wenn Sie Pandoc selbst installieren möchten, folgen Sie einer der beiden Anleitungen. Die erste Anleitung verwendet ein Installationsprogramm und ist für Windows und macOS verfügbar. Alternativ können Sie auch den Paketmanager Ihres Betriebssystems verwenden, um Pandoc zu installieren." + +-- Download installer +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3791603277"] = "Installer herunterladen" + +-- Accept the GPL and download the archive +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3987456907"] = "Akzeptieren Sie die GPL und laden Sie das Archiv herunter" + +-- Reject Pandoc's Licence +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T4092049320"] = "Pandoc-Lizenz ablehnen" + +-- Proceed to the installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T4134878031"] = "Mit der Installation fortfahren" + +-- Re-install Pandoc +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T4152693089"] = "Pandoc neu installieren" + +-- Accept the terms of the GPL license and download the latest installer with the download button below. Eventually, you need to allow the download of the installer in the download window. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T504404155"] = "Akzeptieren Sie die Bedingungen der GPL-Lizenz und laden Sie mit dem untenstehenden Download-Button das neueste Installationsprogramm herunter. Gegebenenfalls müssen Sie den Download des Installationsprogramms im Downloadfenster erlauben." + +-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept the GPL and download the archive," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T523908375"] = "Pandoc wird unter der GNU General Public License v2 (GPL) vertrieben. Wenn Sie auf „GPL akzeptieren und Archiv herunterladen“ klicken, stimmen Sie den Bedingungen der GPL-Lizenz zu. Software unter der GPL ist kostenlos und frei nutzbar." + -- Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T1458195391"] = "Teilen Sie der KI mit, was sie machen soll. Was sind ihre Ziele oder was möchten Sie erreichen? Zum Beispiel, dass die KI Sie duzt." @@ -3301,7 +3439,7 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T108494 UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T1096979935"] = "Möchten Sie die Datenquelle „{0}“ vom Typ {1} wirklich löschen?" -- Edit Local Directory Data Source -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T1215599168"] = "Lokale Ordner-Datenquelle bearbeiten" +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T1215599168"] = "Datenquelle bearbeiten: Lokaler Ordner" -- Add Local Directory as Data Source UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T1454193397"] = "Lokalen Ordner als Datenquelle hinzufügen" @@ -3325,7 +3463,7 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T214675 UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T221059217"] = "ERI v1 Datenquelle bearbeiten" -- Edit Local File Data Source -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T2453292893"] = "Lokale Datei-Datenquelle bearbeiten" +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T2453292893"] = "Datenquelle bearbeiten: Lokale Datei" -- ERI v1 Data Source Information UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T26243729"] = "ERI v1 Datenquellen-Informationen" @@ -4035,6 +4173,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1772678682"] = "Diese Bibliothek wird -- By clicking on the respective path, the path is copied to the clipboard. You might open these files with a text editor to view their contents. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1806897624"] = "Wenn Sie auf den jeweiligen Pfad klicken, wird dieser in die Zwischenablage kopiert. Sie können diese Dateien mit einem Texteditor öffnen, um ihren Inhalt anzusehen." +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T185447014"] = "Pandoc-Installation" + -- Check for updates UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1890416390"] = "Nach Updates suchen" @@ -4053,6 +4194,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2173617769"] = "Diese Bibliothek wird -- For the secure communication between the user interface and the runtime, we need to create certificates. This Rust library is great for this purpose. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2174764529"] = "Für die sichere Kommunikation zwischen der Benutzeroberfläche und der Laufzeit müssen wir Zertifikate erstellen. Diese Rust-Bibliothek eignet sich hervorragend dafür." +-- OK +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2246359087"] = "OK" + -- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2273492381"] = "Wir müssen Zufallszahlen erzeugen, z. B. um die Kommunikation zwischen der Benutzeroberfläche und der Laufzeitumgebung abzusichern. Die rand-Bibliothek eignet sich dafür hervorragend." @@ -4065,6 +4209,12 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2329884315"] = "Die Programmiersprache -- Used PDFium version UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2368247719"] = "Verwendete PDFium-Version" +-- installation provided by the system +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2371107659"] = "Installation vom System bereitgestellt" + +-- Installed Pandoc version: Pandoc is not installed or not available. +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2374031539"] = "Installierte Pandoc-Version: Pandoc ist nicht installiert oder nicht verfügbar." + -- This library is used to determine the language of the operating system. This is necessary to set the language of the user interface. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2557014401"] = "Diese Bibliothek wird verwendet, um die Sprache des Betriebssystems zu erkennen. Dies ist notwendig, um die Sprache der Benutzeroberfläche einzustellen." @@ -4086,6 +4236,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2706940196"] = "Protokolldateien" -- This component is used to render Markdown text. This is important because the LLM often responds with Markdown-formatted text, allowing us to present it in a way that is easier to read. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2726131107"] = "Diese Komponente wird verwendet, um Markdown-Text darzustellen. Das ist wichtig, weil das LLM häufig mit im Markdown-Format formatiertem Text antwortet. Dadurch können wir die Antworten besser lesbar anzeigen." +-- Determine Pandoc version, please wait... +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2765814390"] = "Pandoc-Version wird ermittelt, bitte warten …" + -- Code in the Rust language can be specified as synchronous or asynchronous. Unlike .NET and the C# language, Rust cannot execute asynchronous code by itself. Rust requires support in the form of an executor for this. Tokio is one such executor. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2777988282"] = "Code in der Programmiersprache Rust kann als synchron oder asynchron spezifiziert werden. Im Gegensatz zu .NET und der Sprache C# kann Rust asynchronen Code jedoch nicht von selbst ausführen. Dafür benötigt Rust Unterstützung in Form eines Executors. Tokio ist ein solcher Executor." @@ -4110,6 +4263,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T313276297"] = "Verbinden Sie AI Studio -- Have feature ideas? Submit suggestions for future AI Studio enhancements. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3178730036"] = "Haben Sie Ideen für neue Funktionen? Senden Sie uns Vorschläge für zukünftige Verbesserungen von AI Studio." +-- Update Pandoc +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3249965383"] = "Pandoc aktualisieren" + -- Discover MindWork AI's mission and vision on our official homepage. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3294830584"] = "Entdecken Sie die Mission und Vision von MindWork AI auf unserer offiziellen Homepage." @@ -4131,9 +4287,18 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3563271893"] = "Motivation" -- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3722989559"] = "Diese Bibliothek wird verwendet, um Excel- und OpenDocument-Tabellendateien zu lesen. Dies ist zum Beispiel notwendig, wenn Tabellen als Datenquelle für einen Chat verwendet werden sollen." +-- this version does not met the requirements +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3813932670"] = "diese Version erfüllt die Anforderungen nicht" + -- Now we have multiple systems, some developed in .NET and others in Rust. The data format JSON is responsible for translating data between both worlds (called data serialization and deserialization). Serde takes on this task in the Rust world. The counterpart in the .NET world is an integral part of .NET and is located in System.Text.Json. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3908558992"] = "Jetzt haben wir mehrere Systeme, einige entwickelt in .NET und andere in Rust. Das Datenformat JSON ist dafür zuständig, Daten zwischen beiden Welten zu übersetzen (dies nennt man Serialisierung und Deserialisierung von Daten). In der Rust-Welt übernimmt Serde diese Aufgabe. Das Pendant in der .NET-Welt ist ein fester Bestandteil von .NET und findet sich in System.Text.Json." +-- Installed Pandoc version +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3983971016"] = "Installierte Pandoc-Version" + +-- Check Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3986423270"] = "Pandoc-Installation prüfen" + -- Versions UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T4010195468"] = "Versionen" @@ -4161,9 +4326,15 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T639371534"] = "Haben Sie einen Fehler -- This Rust library is used to output the app's messages to the terminal. This is helpful during development and troubleshooting. This feature is initially invisible; when the app is started via the terminal, the messages become visible. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T64689067"] = "Diese Rust-Bibliothek wird verwendet, um die Nachrichten der App im Terminal auszugeben. Das ist während der Entwicklung und Fehlersuche hilfreich. Diese Funktion ist zunächst unsichtbar; werden App über das Terminal gestartet, werden die Nachrichten sichtbar." +-- installed by AI Studio +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T833849470"] = "installiert von AI Studio" + -- For some data transfers, we need to encode the data in base64. This Rust library is great for this purpose. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T870640199"] = "Für einige Datenübertragungen müssen wir die Daten in Base64 kodieren. Diese Rust-Bibliothek eignet sich dafür hervorragend." +-- Install Pandoc +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T986578435"] = "Pandoc installieren" + -- Get coding and debugging support from an LLM. UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1243850917"] = "Erhalten Sie Unterstützung beim Programmieren und Debuggen durch ein KI-Modell." @@ -4998,6 +5169,42 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::ERICLIENTV1::T816853779"] = "Fehler -- Failed to retrieve the authentication methods: the ERI server did not return a valid response. UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::ERICLIENTV1::T984407320"] = "Fehler beim Abrufen der Authentifizierungsmethoden: Der ERI-Server hat keine gültige Antwort zurückgegeben." +-- Was not able to validate the Pandoc installation. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T1364844008"] = "Die Pandoc-Installation konnte nicht überprüft werden." + +-- Installers are not available on {0} systems. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T1640771881"] = "Installationsprogramme sind für {0}-Systemen nicht verfügbar." + +-- Pandoc v{0} was installed successfully. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T1885555132"] = "Pandoc v{0} wurde erfolgreich installiert." + +-- Was not able to check the Pandoc installation. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2171727146"] = "Die Pandoc-Installation konnte nicht überprüft werden." + +-- Pandoc v{0} is installed, but it doesn't match the required version (v{1}). +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2299898115"] = "Pandoc v{0} ist installiert, entspricht jedoch nicht der erforderlichen Version (v{1})." + +-- Pandoc v{0} is installed. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2550598062"] = "Pandoc v{0} ist installiert." + +-- Pandoc v{0} is installed, but it does not match the required version (v{1}). +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2555465873"] = "Pandoc v{0} ist installiert, entspricht aber nicht der benötigten Version (v{1})." + +-- Pandoc was not installed successfully, because the archive was not found. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T34210248"] = "Pandoc wurde nicht erfolgreich installiert, da das Archiv nicht gefunden wurde." + +-- Pandoc is not available on the system or the process had issues. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T3746116957"] = "Pandoc ist auf dem System nicht verfügbar oder der Vorgang ist auf Probleme gestoßen." + +-- Pandoc was not installed successfully, because the archive type is unknown. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T3962211670"] = "Pandoc wurde nicht erfolgreich installiert, da der Archivtyp unbekannt ist." + +-- It seems that Pandoc is not installed. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T567205144"] = "Es scheint, dass Pandoc nicht installiert ist." + +-- The latest Pandoc version was not found, installing version {0} instead. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T726914939"] = "Die neueste Pandoc-Version wurde nicht gefunden, stattdessen wird Version {0} installiert." + -- The table AUTHORS does not exist or is using an invalid syntax. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T1068328139"] = "Die Tabelle AUTHORS existiert nicht oder verwendet eine ungültige Syntax." diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index 7569c8bc..5ba47cf6 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -486,6 +486,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ALLOWEDLLMPROVIDERSEXTENSIONS::T4096 -- Please describe at least one retrieval process. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1035068989"] = "Please describe at least one retrieval process." +-- Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1047217452"] = "Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing." + -- Please select which types of LLMs users are allowed to use with the data from this ERI server. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1047631678"] = "Please select which types of LLMs users are allowed to use with the data from this ERI server." @@ -513,9 +516,6 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1261836894"] = "Pleas -- You have not yet added any ERI server presets. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1267931972"] = "You have not yet added any ERI server presets." --- Warning: Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user). -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1287629674"] = "Warning: Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user)." - -- The task of writing the ERI server for you is very complex. Therefore, a very powerful LLM is needed to successfully accomplish this task. Small local models will probably not be sufficient. Instead, try using a large cloud-based or a large self-hosted model. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1302705248"] = "The task of writing the ERI server for you is very complex. Therefore, a very powerful LLM is needed to successfully accomplish this task. Small local models will probably not be sufficient. Instead, try using a large cloud-based or a large self-hosted model." @@ -537,12 +537,18 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1456749976"] = "Pleas -- Delete UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1469573738"] = "Delete" +-- When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1531680404"] = "When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files." + -- Related links: UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1565111217"] = "Related links:" -- Please select an ERI specification version for the ERI server. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1612890554"] = "Please select an ERI specification version for the ERI server." +-- Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user). +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T168780641"] = "Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user)." + -- Write code to file system UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1717303021"] = "Write code to file system" @@ -564,6 +570,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T180938091"] = "Delete -- Provider selection for generation UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1840198821"] = "Provider selection for generation" +-- However, generating all the files takes a certain amount of time. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1862007299"] = "However, generating all the files takes a certain amount of time." + -- Should we automatically save any input made? UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1980659256"] = "Should we automatically save any input made?" @@ -579,8 +588,8 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2034620186"] = "Data -- Interactive documentation aka Swagger UI UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2064957876"] = "Interactive documentation aka Swagger UI" --- When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files. But beware: It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2155983785"] = "When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files. But beware: It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose." +-- Warning: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2149175535"] = "Warning:" -- Add Embedding Method UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2176833082"] = "Add Embedding Method" @@ -609,6 +618,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2417944396"] = "Are y -- Data source settings UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T2440619931"] = "Data source settings" +-- The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T248288139"] = "The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this." + -- Yes, please write or update all generated code to the file system UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T252707279"] = "Yes, please write or update all generated code to the file system" @@ -684,18 +696,21 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3316699247"] = "No, j -- Other language UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3374524465"] = "Other language" +-- Important: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3379345517"] = "Important:" + -- ERI Server {0} UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3443687246"] = "ERI Server {0}" -- You will likely use one or more embedding methods to encode the meaning of your data into a typically high-dimensional vector space. In this case, you will use a vector database to store and search these vectors (called embeddings). However, you don't have to use embedding methods. When your retrieval method works without any embedding, you can ignore this section. An example: You store files on a file server, and your retrieval method works exclusively with file names in the file system, so you don't need embeddings. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3446047228"] = "You will likely use one or more embedding methods to encode the meaning of your data into a typically high-dimensional vector space. In this case, you will use a vector database to store and search these vectors (called embeddings). However, you don't have to use embedding methods. When your retrieval method works without any embedding, you can ignore this section. An example: You store files on a file server, and your retrieval method works exclusively with file names in the file system, so you don't need embeddings." --- Important: The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this. However, generating all the files takes a certain amount of time. Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing. -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3485079498"] = "Important: The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this. However, generating all the files takes a certain amount of time. Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing." - -- Type UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3512062061"] = "Type" +-- It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3541842180"] = "It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose." + -- Please describe how the selected authentication methods should be used. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T356079033"] = "Please describe how the selected authentication methods should be used." @@ -735,6 +750,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3865031940"] = "Actio -- ERI specification version UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3897494556"] = "ERI specification version" +-- But beware: +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3956615326"] = "But beware:" + -- Please provide a description for your ERI server. What data will the server retrieve? This description will be used to inform users about the purpose of your ERI server. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T3973182416"] = "Please provide a description for your ERI server. What data will the server retrieve? This description will be used to inform users about the purpose of your ERI server." @@ -1521,6 +1539,30 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::DATASOURCESELECTION::T86053874"] = "Avail -- Issues UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ISSUES::T3229841001"] = "Issues" +-- Your Pandoc installation meets the requirements. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T1167365374"] = "Your Pandoc installation meets the requirements." + +-- Please wait while we check the availability of Pandoc. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T1336364299"] = "Please wait while we check the availability of Pandoc." + +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T185447014"] = "Pandoc Installation" + +-- Your Pandoc installation is outdated. Please update it to the latest version to ensure compatibility with all features. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T251757907"] = "Your Pandoc installation is outdated. Please update it to the latest version to ensure compatibility with all features." + +-- Pandoc is not installed or not available. Please install it to use the features that require Pandoc. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T3147551473"] = "Pandoc is not installed or not available. Please install it to use the features that require Pandoc." + +-- Update Pandoc +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T3249965383"] = "Update Pandoc" + +-- Check your Pandoc installation +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T527187983"] = "Check your Pandoc installation" + +-- Install Pandoc +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T986578435"] = "Install Pandoc" + -- Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1057189794"] = "Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications." @@ -2439,6 +2481,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2814869210" -- Embedding UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T2838542994"] = "Embedding" +-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3359366900"] = "For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc." + -- Yes, please send my data to the cloud UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALDIRECTORYDIALOG::T3572613009"] = "Yes, please send my data to the cloud" @@ -2553,6 +2598,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2814869210"] = " -- Embedding UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T2838542994"] = "Embedding" +-- For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3359366900"] = "For some data types, such as Office files, MindWork AI Studio requires the open-source application Pandoc." + -- Yes, please send my data to the cloud UI_TEXT_CONTENT["AISTUDIO::DIALOGS::DATASOURCELOCALFILEDIALOG::T3572613009"] = "Yes, please send my data to the cloud" @@ -2748,6 +2796,96 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900237532"] = "Pro -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::EMBEDDINGPROVIDERDIALOG::T900713019"] = "Cancel" +-- Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1001483402"] = "Unfortunately, Pandoc's GPL license isn't compatible with the AI Studios licenses. However, software under the GPL is free to use and free of charge. You'll need to accept the GPL license before we can download and install Pandoc for you automatically (recommended). Alternatively, you might download it yourself using the instructions below or install it otherwise, e.g., by using a package manager of your operating system." + +-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and Install," you agree to the terms of the GPL license, and Pandoc will be installed automatically for you. Software under GPL is free of charge and free to use. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1357200670"] = "Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking \"Accept GPL and Install,\" you agree to the terms of the GPL license, and Pandoc will be installed automatically for you. Software under GPL is free of charge and free to use." + +-- View the GNU General Public License v2 (GPL) +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1587398673"] = "View the GNU General Public License v2 (GPL)" + +-- Reject the GPL licence +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1655899051"] = "Reject the GPL licence" + +-- Automatic installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1780479836"] = "Automatic installation" + +-- Manual installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T1814127049"] = "Manual installation" + +-- AI Studio uses the free and open-source third-party app Pandoc to process and retrieve data from local Office files (such as Word files) or to generate Office documents. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T205422394"] = "AI Studio uses the free and open-source third-party app Pandoc to process and retrieve data from local Office files (such as Word files) or to generate Office documents." + +-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept GPL and download installer," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2084501359"] = "Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking \"Accept GPL and download installer,\" you agree to the terms of the GPL license. Software under GPL is free of charge and free to use." + +-- Extract the archive to a folder of your choice, e.g.: +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2094245964"] = "Extract the archive to a folder of your choice, e.g.:" + +-- Pandoc is open-source and free, but if you reject its license, you can't install it and some MindWork AI Studio features will be limited (like the integration of Office files) or unavailable (like the generation of Office files). You can change your decision anytime. Are you sure you want to reject the license? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2559178004"] = "Pandoc is open-source and free, but if you reject its license, you can't install it and some MindWork AI Studio features will be limited (like the integration of Office files) or unavailable (like the generation of Office files). You can change your decision anytime. Are you sure you want to reject the license?" + +-- Please wait for the installation to complete... +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2606205182"] = "Please wait for the installation to complete..." + +-- Open the folder and copy the full path to the folder where your Pandoc executable file is into your clipboard: +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2946844485"] = "Open the folder and copy the full path to the folder where your Pandoc executable file is into your clipboard:" + +-- Accept the GPL and start the installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T2966192331"] = "Accept the GPL and start the installation" + +-- Error loading license text, please consider following the links to read the GPL. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3054618024"] = "Error loading license text, please consider following the links to read the GPL." + +-- Accept the GPL and download the installer +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3104260405"] = "Accept the GPL and download the installer" + +-- Add the copied path to your system's or user's PATH environment variable, restart your terminal, and check the installation: +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T313476957"] = "Add the copied path to your system's or user's PATH environment variable, restart your terminal, and check the installation:" + +-- Accept the terms of the GPL license and download the latest archive with the download button below. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3263447722"] = "Accept the terms of the GPL license and download the latest archive with the download button below." + +-- Pandoc doesn't seem to be installed on this system. AI Studio can help you install the correct version. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3355132094"] = "Pandoc doesn't seem to be installed on this system. AI Studio can help you install the correct version." + +-- Close +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3448155331"] = "Close" + +-- Pandoc is installed and the version meets the requirements of MindWork AI Studio. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3653795841"] = "Pandoc is installed and the version meets the requirements of MindWork AI Studio." + +-- Pandoc is installed, but the version is too old and does not meet the requirements of MindWork AI Studio. AI Studio can help you install a newer version. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3692691761"] = "Pandoc is installed, but the version is too old and does not meet the requirements of MindWork AI Studio. AI Studio can help you install a newer version." + +-- Execute the installer and follow the instructions. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3730261061"] = "Execute the installer and follow the instructions." + +-- If you want to install Pandoc yourself, follow one of these two guides. The first guide uses an installer and is available for Windows and macOS. Alternatively, you might use a package manager of your operating system to install Pandoc. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3780227601"] = "If you want to install Pandoc yourself, follow one of these two guides. The first guide uses an installer and is available for Windows and macOS. Alternatively, you might use a package manager of your operating system to install Pandoc." + +-- Download installer +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3791603277"] = "Download installer" + +-- Accept the GPL and download the archive +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T3987456907"] = "Accept the GPL and download the archive" + +-- Reject Pandoc's Licence +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T4092049320"] = "Reject Pandoc's Licence" + +-- Proceed to the installation +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T4134878031"] = "Proceed to the installation" + +-- Re-install Pandoc +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T4152693089"] = "Re-install Pandoc" + +-- Accept the terms of the GPL license and download the latest installer with the download button below. Eventually, you need to allow the download of the installer in the download window. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T504404155"] = "Accept the terms of the GPL license and download the latest installer with the download button below. Eventually, you need to allow the download of the installer in the download window." + +-- Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking "Accept the GPL and download the archive," you agree to the terms of the GPL license. Software under GPL is free of charge and free to use. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T523908375"] = "Pandoc is distributed under the GNU General Public License v2 (GPL). By clicking \"Accept the GPL and download the archive,\" you agree to the terms of the GPL license. Software under GPL is free of charge and free to use." + -- Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T1458195391"] = "Tell the AI what you want it to do for you. What are your goals or are you trying to achieve? Like having the AI address you informally." @@ -4035,6 +4173,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1772678682"] = "This library is used t -- By clicking on the respective path, the path is copied to the clipboard. You might open these files with a text editor to view their contents. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1806897624"] = "By clicking on the respective path, the path is copied to the clipboard. You might open these files with a text editor to view their contents." +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T185447014"] = "Pandoc Installation" + -- Check for updates UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1890416390"] = "Check for updates" @@ -4053,6 +4194,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2173617769"] = "This library is used t -- For the secure communication between the user interface and the runtime, we need to create certificates. This Rust library is great for this purpose. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2174764529"] = "For the secure communication between the user interface and the runtime, we need to create certificates. This Rust library is great for this purpose." +-- OK +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2246359087"] = "OK" + -- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2273492381"] = "We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose." @@ -4065,6 +4209,12 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2329884315"] = "The C# language is use -- Used PDFium version UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2368247719"] = "Used PDFium version" +-- installation provided by the system +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2371107659"] = "installation provided by the system" + +-- Installed Pandoc version: Pandoc is not installed or not available. +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2374031539"] = "Installed Pandoc version: Pandoc is not installed or not available." + -- This library is used to determine the language of the operating system. This is necessary to set the language of the user interface. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2557014401"] = "This library is used to determine the language of the operating system. This is necessary to set the language of the user interface." @@ -4086,6 +4236,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2706940196"] = "Logbook" -- This component is used to render Markdown text. This is important because the LLM often responds with Markdown-formatted text, allowing us to present it in a way that is easier to read. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2726131107"] = "This component is used to render Markdown text. This is important because the LLM often responds with Markdown-formatted text, allowing us to present it in a way that is easier to read." +-- Determine Pandoc version, please wait... +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2765814390"] = "Determine Pandoc version, please wait..." + -- Code in the Rust language can be specified as synchronous or asynchronous. Unlike .NET and the C# language, Rust cannot execute asynchronous code by itself. Rust requires support in the form of an executor for this. Tokio is one such executor. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2777988282"] = "Code in the Rust language can be specified as synchronous or asynchronous. Unlike .NET and the C# language, Rust cannot execute asynchronous code by itself. Rust requires support in the form of an executor for this. Tokio is one such executor." @@ -4110,6 +4263,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T313276297"] = "Connect AI Studio to yo -- Have feature ideas? Submit suggestions for future AI Studio enhancements. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3178730036"] = "Have feature ideas? Submit suggestions for future AI Studio enhancements." +-- Update Pandoc +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3249965383"] = "Update Pandoc" + -- Discover MindWork AI's mission and vision on our official homepage. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3294830584"] = "Discover MindWork AI's mission and vision on our official homepage." @@ -4131,9 +4287,18 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3563271893"] = "Motivation" -- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3722989559"] = "This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat." +-- this version does not met the requirements +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3813932670"] = "this version does not met the requirements" + -- Now we have multiple systems, some developed in .NET and others in Rust. The data format JSON is responsible for translating data between both worlds (called data serialization and deserialization). Serde takes on this task in the Rust world. The counterpart in the .NET world is an integral part of .NET and is located in System.Text.Json. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3908558992"] = "Now we have multiple systems, some developed in .NET and others in Rust. The data format JSON is responsible for translating data between both worlds (called data serialization and deserialization). Serde takes on this task in the Rust world. The counterpart in the .NET world is an integral part of .NET and is located in System.Text.Json." +-- Installed Pandoc version +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3983971016"] = "Installed Pandoc version" + +-- Check Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3986423270"] = "Check Pandoc Installation" + -- Versions UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T4010195468"] = "Versions" @@ -4161,9 +4326,15 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T639371534"] = "Did you find a bug or a -- This Rust library is used to output the app's messages to the terminal. This is helpful during development and troubleshooting. This feature is initially invisible; when the app is started via the terminal, the messages become visible. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T64689067"] = "This Rust library is used to output the app's messages to the terminal. This is helpful during development and troubleshooting. This feature is initially invisible; when the app is started via the terminal, the messages become visible." +-- installed by AI Studio +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T833849470"] = "installed by AI Studio" + -- For some data transfers, we need to encode the data in base64. This Rust library is great for this purpose. UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T870640199"] = "For some data transfers, we need to encode the data in base64. This Rust library is great for this purpose." +-- Install Pandoc +UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T986578435"] = "Install Pandoc" + -- Get coding and debugging support from an LLM. UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1243850917"] = "Get coding and debugging support from an LLM." @@ -4998,6 +5169,42 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::ERICLIENTV1::T816853779"] = "Failed -- Failed to retrieve the authentication methods: the ERI server did not return a valid response. UI_TEXT_CONTENT["AISTUDIO::TOOLS::ERICLIENT::ERICLIENTV1::T984407320"] = "Failed to retrieve the authentication methods: the ERI server did not return a valid response." +-- Was not able to validate the Pandoc installation. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T1364844008"] = "Was not able to validate the Pandoc installation." + +-- Installers are not available on {0} systems. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T1640771881"] = "Installers are not available on {0} systems." + +-- Pandoc v{0} was installed successfully. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T1885555132"] = "Pandoc v{0} was installed successfully." + +-- Was not able to check the Pandoc installation. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2171727146"] = "Was not able to check the Pandoc installation." + +-- Pandoc v{0} is installed, but it doesn't match the required version (v{1}). +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2299898115"] = "Pandoc v{0} is installed, but it doesn't match the required version (v{1})." + +-- Pandoc v{0} is installed. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2550598062"] = "Pandoc v{0} is installed." + +-- Pandoc v{0} is installed, but it does not match the required version (v{1}). +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T2555465873"] = "Pandoc v{0} is installed, but it does not match the required version (v{1})." + +-- Pandoc was not installed successfully, because the archive was not found. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T34210248"] = "Pandoc was not installed successfully, because the archive was not found." + +-- Pandoc is not available on the system or the process had issues. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T3746116957"] = "Pandoc is not available on the system or the process had issues." + +-- Pandoc was not installed successfully, because the archive type is unknown. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T3962211670"] = "Pandoc was not installed successfully, because the archive type is unknown." + +-- It seems that Pandoc is not installed. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T567205144"] = "It seems that Pandoc is not installed." + +-- The latest Pandoc version was not found, installing version {0} instead. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T726914939"] = "The latest Pandoc version was not found, installing version {0} instead." + -- The table AUTHORS does not exist or is using an invalid syntax. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::PLUGINBASE::T1068328139"] = "The table AUTHORS does not exist or is using an invalid syntax." diff --git a/app/MindWork AI Studio/Tools/Pandoc.cs b/app/MindWork AI Studio/Tools/Pandoc.cs index 2f0d7bd1..3c12e618 100644 --- a/app/MindWork AI Studio/Tools/Pandoc.cs +++ b/app/MindWork AI Studio/Tools/Pandoc.cs @@ -1,58 +1,56 @@ using System.Diagnostics; +using System.Formats.Tar; using System.IO.Compression; -using System.Runtime.InteropServices; +using System.Reflection; using System.Text.RegularExpressions; +using AIStudio.Tools.Metadata; using AIStudio.Tools.Services; +using SharedTools; + namespace AIStudio.Tools; public static partial class Pandoc { - private const string CPU_ARCHITECTURE = "win-x64"; + private static string TB(string fallbackEN) => PluginSystem.I18N.I.T(fallbackEN, typeof(Pandoc).Namespace, nameof(Pandoc)); + + private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly(); + private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute()!; + private static readonly RID CPU_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID(); + private const string DOWNLOAD_URL = "https://github.com/jgm/pandoc/releases/download"; private const string LATEST_URL = "https://github.com/jgm/pandoc/releases/latest"; - private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger("PandocService"); - private static readonly Version MINIMUM_REQUIRED_VERSION = new (3, 6); - private static readonly Version FALLBACK_VERSION = new (3, 7, 0, 1); + private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger("Pandoc"); + private static readonly Version MINIMUM_REQUIRED_VERSION = new (3, 7, 0, 2); + private static readonly Version FALLBACK_VERSION = new (3, 7, 0, 2); /// - /// Checks if pandoc is available on the system and can be started as a process or present in AiStudio's data dir + /// Prepares a Pandoc process by using the Pandoc process builder. /// - /// Global rust service to access file system and data dir - /// Controls if snackbars are shown to the user - /// True, if pandoc is available and the minimum required version is met, else False. - public static async Task CheckAvailabilityAsync(RustService rustService, bool showMessages = true) - { - var installDir = await GetPandocDataFolder(rustService); - var subdirectories = Directory.GetDirectories(installDir); + /// The Pandoc process builder with default settings. + public static PandocProcessBuilder PreparePandocProcess() => PandocProcessBuilder.Create(); - if (subdirectories.Length > 1) - { - await InstallAsync(rustService); - return true; - } - - if (HasPandoc(installDir)) return true; - + /// + /// Checks if pandoc is available on the system and can be started as a process or is present in AI Studio's data dir. + /// + /// Global rust service to access file system and data dir. + /// Controls if snackbars are shown to the user. + /// True, if pandoc is available and the minimum required version is met, else false. + public static async Task CheckAvailabilityAsync(RustService rustService, bool showMessages = true) + { try { - var startInfo = new ProcessStartInfo - { - FileName = GetPandocExecutableName(), - Arguments = "--version", - RedirectStandardOutput = true, - UseShellExecute = false, - CreateNoWindow = true - }; - using var process = Process.Start(startInfo); + var preparedProcess = await PreparePandocProcess().AddArgument("--version").BuildAsync(rustService); + using var process = Process.Start(preparedProcess.StartInfo); if (process == null) { if (showMessages) - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Help, "The pandoc process could not be started.")); - LOG.LogInformation("The pandoc process was not started, it was null"); - return false; + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Help, TB("Was not able to check the Pandoc installation."))); + + LOG.LogInformation("The Pandoc process was not started, it was null"); + return new(false, TB("Was not able to check the Pandoc installation."), false, string.Empty, preparedProcess.IsLocal); } var output = await process.StandardOutput.ReadToEndAsync(); @@ -60,65 +58,48 @@ public static partial class Pandoc if (process.ExitCode != 0) { if (showMessages) - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Error, $"The pandoc process exited unexpectedly.")); - LOG.LogError("The pandoc process was exited with code {ProcessExitCode}", process.ExitCode); - return false; + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Error, TB("Pandoc is not available on the system or the process had issues."))); + + LOG.LogError("The Pandoc process was exited with code {ProcessExitCode}", process.ExitCode); + return new(false, TB("Pandoc is not available on the system or the process had issues."), false, string.Empty, preparedProcess.IsLocal); } var versionMatch = PandocCmdRegex().Match(output); if (!versionMatch.Success) { if (showMessages) - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Terminal, $"pandoc --version returned an invalid format.")); - LOG.LogError("pandoc --version returned an invalid format:\n {Output}", output); - return false; + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Terminal, TB("Was not able to validate the Pandoc installation."))); + + LOG.LogError("Pandoc --version returned an invalid format: {Output}", output); + return new(false, TB("Was not able to validate the Pandoc installation."), false, string.Empty, preparedProcess.IsLocal); } + var versions = versionMatch.Groups[1].Value; var installedVersion = Version.Parse(versions); + var installedVersionString = installedVersion.ToString(); if (installedVersion >= MINIMUM_REQUIRED_VERSION) { if (showMessages) - await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, $"Pandoc {installedVersion.ToString()} is installed.")); - return true; + await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, string.Format(TB("Pandoc v{0} is installed."), installedVersionString))); + + LOG.LogInformation("Pandoc v{0} is installed and matches the required version (v{1})", installedVersionString, MINIMUM_REQUIRED_VERSION.ToString()); + return new(true, string.Empty, true, installedVersionString, preparedProcess.IsLocal); } if (showMessages) - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Build, $"Pandoc {installedVersion.ToString()} is installed, but it doesn't match the required version ({MINIMUM_REQUIRED_VERSION.ToString()}).")); - LOG.LogInformation("Pandoc {Installed} is installed, but it does not match the required version ({Requirement})", installedVersion.ToString(), MINIMUM_REQUIRED_VERSION.ToString()); - return false; - + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Build, string.Format(TB("Pandoc v{0} is installed, but it doesn't match the required version (v{1})."), installedVersionString, MINIMUM_REQUIRED_VERSION.ToString()))); + + LOG.LogWarning("Pandoc v{0} is installed, but it does not match the required version (v{1})", installedVersionString, MINIMUM_REQUIRED_VERSION.ToString()); + return new(true, string.Format(TB("Pandoc v{0} is installed, but it does not match the required version (v{1})."), installedVersionString, MINIMUM_REQUIRED_VERSION.ToString()), false, installedVersionString, preparedProcess.IsLocal); } catch (Exception e) { if (showMessages) - await MessageBus.INSTANCE.SendError(new (@Icons.Material.Filled.AppsOutage, "Pandoc is not installed.")); - LOG.LogError("Pandoc is not installed and threw an exception:\n {Message}", e.Message); - return false; - } - } - - private static bool HasPandoc(string pandocDirectory) - { - try - { - var subdirectories = Directory.GetDirectories(pandocDirectory); - - foreach (var subdirectory in subdirectories) - { - var pandocPath = Path.Combine(subdirectory, "pandoc.exe"); - if (File.Exists(pandocPath)) - { - return true; - } - } - - return false; - } - catch (Exception ex) - { - LOG.LogInformation("Pandoc is not installed in the data directory and might have thrown and error:\n{ErrorMessage}", ex.Message); - return false; + await MessageBus.INSTANCE.SendError(new (@Icons.Material.Filled.AppsOutage, TB("It seems that Pandoc is not installed."))); + + LOG.LogError("Pandoc is not installed and threw an exception: {0}", e.Message); + return new(false, TB("It seems that Pandoc is not installed."), false, string.Empty, false); } } @@ -129,70 +110,79 @@ public static partial class Pandoc /// None public static async Task InstallAsync(RustService rustService) { + var latestVersion = await FetchLatestVersionAsync(); var installDir = await GetPandocDataFolder(rustService); ClearFolder(installDir); + LOG.LogInformation("Trying to install Pandoc v{0} to '{1}'...", latestVersion, installDir); + try { if (!Directory.Exists(installDir)) Directory.CreateDirectory(installDir); - - using var client = new HttpClient(); - var uri = await GenerateUriAsync(); - var response = await client.GetAsync(uri); - if (!response.IsSuccessStatusCode) + // Create a temporary file to download the archive to: + var pandocTempDownloadFile = Path.GetTempFileName(); + + // + // Download the latest Pandoc archive from GitHub: + // + var uri = await GenerateArchiveUriAsync(); + using (var client = new HttpClient()) { - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Error, $"Pandoc was not installed successfully, because the download archive was not found.")); - LOG.LogError("Pandoc was not installed, the release archive was not found (Status Code {StatusCode}):\n{Uri}\n{Message}", response.StatusCode, uri, response.RequestMessage); - return; - } - var fileBytes = await response.Content.ReadAsByteArrayAsync(); + var response = await client.GetAsync(uri); + if (!response.IsSuccessStatusCode) + { + await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.Error, TB("Pandoc was not installed successfully, because the archive was not found."))); + LOG.LogError("Pandoc was not installed successfully, because the archive was not found (status code {0}): url='{1}', message='{2}'", response.StatusCode, uri, response.RequestMessage); + return; + } - if (uri.Contains(".zip")) - { - var tempZipPath = Path.Join(Path.GetTempPath(), "pandoc.zip"); - await File.WriteAllBytesAsync(tempZipPath, fileBytes); - ZipFile.ExtractToDirectory(tempZipPath, installDir); - File.Delete(tempZipPath); + // Download the archive to the temporary file: + await using var tempFileStream = File.Create(pandocTempDownloadFile); + await response.Content.CopyToAsync(tempFileStream); } - else if (uri.Contains(".tar.gz")) + + if (uri.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) { - var tempTarPath = Path.Join(Path.GetTempPath(), "pandoc.tar.gz"); - await File.WriteAllBytesAsync(tempTarPath, fileBytes); - ZipFile.ExtractToDirectory(tempTarPath, installDir); - File.Delete(tempTarPath); + ZipFile.ExtractToDirectory(pandocTempDownloadFile, installDir); + } + else if (uri.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase)) + { + await using var tgzStream = File.Open(pandocTempDownloadFile, FileMode.Open, FileAccess.Read, FileShare.Read); + await using var uncompressedStream = new GZipStream(tgzStream, CompressionMode.Decompress); + await TarFile.ExtractToDirectoryAsync(uncompressedStream, installDir, true); } else { - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Error, $"Pandoc was not installed successfully, because the download archive type is unknown.")); - LOG.LogError("Pandoc was not installed, the download archive is unknown:\n {Uri}", uri); + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Error, TB("Pandoc was not installed successfully, because the archive type is unknown."))); + LOG.LogError("Pandoc was not installed, the archive is unknown: url='{0}'", uri); return; } - await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, - $"Pandoc {await FetchLatestVersionAsync()} was installed successfully.")); + File.Delete(pandocTempDownloadFile); + + await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, string.Format(TB("Pandoc v{0} was installed successfully."), latestVersion))); + LOG.LogInformation("Pandoc v{0} was installed successfully.", latestVersion); } catch (Exception ex) { - Console.WriteLine($"Fehler: {ex.Message}"); + LOG.LogError(ex, "An error occurred while installing Pandoc."); } } private static void ClearFolder(string path) { - if (!Directory.Exists(path)) return; + if (!Directory.Exists(path)) + return; try { - foreach (var dir in Directory.GetDirectories(path)) - { - Directory.Delete(dir, true); - } + Directory.Delete(path, true); } catch (Exception ex) { - LOG.LogError(ex, "Error clearing pandoc folder."); + LOG.LogError(ex, "Error clearing pandoc installation directory."); } } @@ -207,18 +197,17 @@ public static partial class Pandoc if (!response.IsSuccessStatusCode) { - LOG.LogError("Code {StatusCode}: Could not fetch Pandoc's latest page:\n {Response}", response.StatusCode, response.RequestMessage); - await MessageBus.INSTANCE.SendWarning(new (Icons.Material.Filled.Warning, $"The latest pandoc version was not found, installing version {FALLBACK_VERSION.ToString()} instead.")); + LOG.LogError("Code {StatusCode}: Could not fetch Pandoc's latest page: {Response}", response.StatusCode, response.RequestMessage); + await MessageBus.INSTANCE.SendWarning(new (Icons.Material.Filled.Warning, string.Format(TB("The latest Pandoc version was not found, installing version {0} instead."), FALLBACK_VERSION.ToString()))); return FALLBACK_VERSION.ToString(); } var htmlContent = await response.Content.ReadAsStringAsync(); - var versionMatch = LatestVersionRegex().Match(htmlContent); if (!versionMatch.Success) { - LOG.LogError("The latest version regex returned nothing:\n {Value}", versionMatch.Groups.ToString()); - await MessageBus.INSTANCE.SendWarning(new (Icons.Material.Filled.Warning, $"The latest pandoc version was not found, installing version {FALLBACK_VERSION.ToString()} instead.")); + LOG.LogError("The latest version regex returned nothing: {0}", versionMatch.Groups.ToString()); + await MessageBus.INSTANCE.SendWarning(new (Icons.Material.Filled.Warning, string.Format(TB("The latest Pandoc version was not found, installing version {0} instead."), FALLBACK_VERSION.ToString()))); return FALLBACK_VERSION.ToString(); } @@ -227,20 +216,35 @@ public static partial class Pandoc } /// - /// Reads the systems architecture to find the correct archive + /// Reads the systems architecture to find the correct archive. /// - /// Full URI to the right archive in Pandoc's repo - public static async Task GenerateUriAsync() + /// Full URI to the right archive in Pandoc's repository. + public static async Task GenerateArchiveUriAsync() { var version = await FetchLatestVersionAsync(); var baseUri = $"{DOWNLOAD_URL}/{version}/pandoc-{version}-"; return CPU_ARCHITECTURE switch { - "win-x64" => $"{baseUri}windows-x86_64.zip", - "osx-x64" => $"{baseUri}x86_64-macOS.zip", - "osx-arm64" => $"{baseUri}arm64-macOS.zip", - "linux-x64" => $"{baseUri}linux-amd64.tar.gz", - "linux-arm" => $"{baseUri}linux-arm64.tar.gz", + // + // Unfortunately, pandoc is not yet available for ARM64 Windows systems, + // so we have to use the x86_64 version for now. ARM Windows contains + // an x86_64 emulation layer, so it should work fine for now. + // + // Pandoc would be available for ARM64 Windows, but the Haskell compiler + // does not support ARM64 Windows yet. Here are the related issues: + // + // - Haskell compiler: https://gitlab.haskell.org/ghc/ghc/-/issues/24603 + // - Haskell ARM MR: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13856 + // - Pandoc ARM64: https://github.com/jgm/pandoc/issues/10095 + // + RID.WIN_X64 or RID.WIN_ARM64 => $"{baseUri}windows-x86_64.zip", + + RID.OSX_X64 => $"{baseUri}x86_64-macOS.zip", + RID.OSX_ARM64 => $"{baseUri}arm64-macOS.zip", + + RID.LINUX_X64 => $"{baseUri}linux-amd64.tar.gz", + RID.LINUX_ARM64 => $"{baseUri}linux-arm64.tar.gz", + _ => string.Empty, }; } @@ -256,25 +260,34 @@ public static partial class Pandoc switch (CPU_ARCHITECTURE) { - case "win-x64": + // + // Unfortunately, pandoc is not yet available for ARM64 Windows systems, + // so we have to use the x86_64 version for now. ARM Windows contains + // an x86_64 emulation layer, so it should work fine for now. + // + // Pandoc would be available for ARM64 Windows, but the Haskell compiler + // does not support ARM64 Windows yet. Here are the related issues: + // + // - Haskell compiler: https://gitlab.haskell.org/ghc/ghc/-/issues/24603 + // - Haskell ARM MR: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13856 + // - Pandoc ARM64: https://github.com/jgm/pandoc/issues/10095 + // + case RID.WIN_X64 or RID.WIN_ARM64: return $"{baseUri}windows-x86_64.msi"; - case "osx-x64": + + case RID.OSX_X64: return $"{baseUri}x86_64-macOS.pkg"; - case "osx-arm64": - return $"{baseUri}arm64-macOS.pkg\n"; + + case RID.OSX_ARM64: + return $"{baseUri}arm64-macOS.pkg"; + default: - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Terminal, $"Installers are not available on {CPU_ARCHITECTURE} systems.")); + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Terminal, string.Format(TB("Installers are not available on {0} systems."), CPU_ARCHITECTURE.ToUserFriendlyName()))); return string.Empty; } } - /// - /// Reads the os platform to determine the used executable name - /// - /// Name of the pandoc executable - private static string GetPandocExecutableName() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "pandoc.exe" : "pandoc"; - - private static async Task GetPandocDataFolder(RustService rustService) => Path.Join(await rustService.GetDataDirectory(), "pandoc"); + public static async Task GetPandocDataFolder(RustService rustService) => Path.Join(await rustService.GetDataDirectory(), "pandoc"); [GeneratedRegex(@"pandoc(?:\.exe)?\s*([0-9]+\.[0-9]+(?:\.[0-9]+)?(?:\.[0-9]+)?)")] private static partial Regex PandocCmdRegex(); diff --git a/app/MindWork AI Studio/Tools/PandocExecutable.cs b/app/MindWork AI Studio/Tools/PandocExecutable.cs new file mode 100644 index 00000000..862d8c43 --- /dev/null +++ b/app/MindWork AI Studio/Tools/PandocExecutable.cs @@ -0,0 +1,3 @@ +namespace AIStudio.Tools; + +public readonly record struct PandocExecutable(string Executable, bool IsLocalInstallation); \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/PandocInstallation.cs b/app/MindWork AI Studio/Tools/PandocInstallation.cs new file mode 100644 index 00000000..41444447 --- /dev/null +++ b/app/MindWork AI Studio/Tools/PandocInstallation.cs @@ -0,0 +1,3 @@ +namespace AIStudio.Tools; + +public readonly record struct PandocInstallation(bool CheckWasSuccessful, string ErrorMessage, bool IsAvailable, string Version, bool IsLocalInstallation); \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/PandocPreparedProcess.cs b/app/MindWork AI Studio/Tools/PandocPreparedProcess.cs new file mode 100644 index 00000000..f4e351e6 --- /dev/null +++ b/app/MindWork AI Studio/Tools/PandocPreparedProcess.cs @@ -0,0 +1,10 @@ +using System.Diagnostics; + +namespace AIStudio.Tools; + +public sealed class PandocPreparedProcess(ProcessStartInfo startInfo, bool isLocal) +{ + public ProcessStartInfo StartInfo => startInfo; + + public bool IsLocal => isLocal; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/PandocProcessBuilder.cs b/app/MindWork AI Studio/Tools/PandocProcessBuilder.cs new file mode 100644 index 00000000..bd2184d0 --- /dev/null +++ b/app/MindWork AI Studio/Tools/PandocProcessBuilder.cs @@ -0,0 +1,135 @@ +using System.Diagnostics; +using System.Reflection; +using System.Text; + +using AIStudio.Tools.Metadata; +using AIStudio.Tools.Services; + +using SharedTools; + +namespace AIStudio.Tools; + +public sealed class PandocProcessBuilder +{ + private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly(); + private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute()!; + private static readonly RID CPU_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID(); + + private string? providedInputFile; + private string? providedOutputFile; + private string? providedInputFormat; + private string? providedOutputFormat; + + private readonly List additionalArguments = new(); + + private PandocProcessBuilder() + { + } + + public static PandocProcessBuilder Create() => new(); + + public PandocProcessBuilder WithInputFile(string inputFile) + { + this.providedInputFile = inputFile; + return this; + } + + public PandocProcessBuilder WithOutputFile(string outputFile) + { + this.providedOutputFile = outputFile; + return this; + } + + public PandocProcessBuilder WithInputFormat(string inputFormat) + { + this.providedInputFormat = inputFormat; + return this; + } + + public PandocProcessBuilder WithOutputFormat(string outputFormat) + { + this.providedOutputFormat = outputFormat; + return this; + } + + public PandocProcessBuilder AddArgument(string argument) + { + this.additionalArguments.Add(argument); + return this; + } + + public async Task BuildAsync(RustService rustService) + { + var sbArguments = new StringBuilder(); + + if(!string.IsNullOrWhiteSpace(this.providedInputFile)) + sbArguments.Append(this.providedInputFile); + + if(!string.IsNullOrWhiteSpace(this.providedInputFormat)) + sbArguments.Append($" -f {this.providedInputFormat}"); + + if(!string.IsNullOrWhiteSpace(this.providedOutputFormat)) + sbArguments.Append($" -t {this.providedOutputFormat}"); + + foreach (var additionalArgument in this.additionalArguments) + sbArguments.Append($" {additionalArgument}"); + + if(!string.IsNullOrWhiteSpace(this.providedOutputFile)) + sbArguments.Append($" -o {this.providedOutputFile}"); + + var pandocExecutable = await PandocExecutablePath(rustService); + return new (new ProcessStartInfo + { + FileName = pandocExecutable.Executable, + Arguments = sbArguments.ToString(), + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }, pandocExecutable.IsLocalInstallation); + } + + /// + /// Returns the path to the pandoc executable. + /// + /// + /// Any local installation of pandoc will be preferred over the system-wide installation. + /// When a local installation is found, its absolute path will be returned. In case no local + /// installation is found, the name of the pandoc executable will be returned. + /// + /// Global rust service to access file system and data dir. + /// Path to the pandoc executable. + private static async Task PandocExecutablePath(RustService rustService) + { + // + // First, we try to find the pandoc executable in the data directory. + // Any local installation should be preferred over the system-wide installation. + // + var localInstallationRootDirectory = await Pandoc.GetPandocDataFolder(rustService); + try + { + var executableName = PandocExecutableName; + var subdirectories = Directory.GetDirectories(localInstallationRootDirectory, "*", SearchOption.AllDirectories); + foreach (var subdirectory in subdirectories) + { + var pandocPath = Path.Combine(subdirectory, executableName); + if (File.Exists(pandocPath)) + return new(pandocPath, true); + } + } + catch + { + // ignored + } + + // + // When no local installation was found, we assume that the pandoc executable is in the system PATH. + // + return new(PandocExecutableName, false); + } + + /// + /// Reads the os platform to determine the used executable name. + /// + public static string PandocExecutableName => CPU_ARCHITECTURE is RID.WIN_ARM64 or RID.WIN_X64 ? "pandoc.exe" : "pandoc"; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/wwwroot/app.js b/app/MindWork AI Studio/wwwroot/app.js index bf1eb31c..aa6b8e2b 100644 --- a/app/MindWork AI Studio/wwwroot/app.js +++ b/app/MindWork AI Studio/wwwroot/app.js @@ -25,14 +25,4 @@ window.clearDiv = function (divName) { window.scrollToBottom = function(element) { element.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'nearest' }); -} - -window.triggerDownload = function(url, filename) { - const a = document.createElement('a'); - a.href = url; - a.setAttribute('download', filename); - a.style.display = 'none'; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); } \ No newline at end of file diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.46.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.46.md index 2c4b5e56..fdba1c09 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.9.46.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.46.md @@ -1,3 +1,4 @@ # v0.9.46, build 221 (2025-06-xx xx:xx UTC) - Added the ability to configure the maximum number of results returned per request for all data sources. Please note that this feature remains in preview and is not visible to all users. -- Added more text content to the I18N system & added the German translation for it. \ No newline at end of file +- Added more text content to the I18N system & added the German translation for it. +- Added the Pandoc integration, which enables us to use Pandoc for data processing (e.g., RAG) and for generating files (e.g., Office documents). We thank Nils `nilskruthoff` for the excellent contribution. \ No newline at end of file diff --git a/app/SourceCodeRules/SourceCodeRules/NamingAnalyzers/LocalConstantsAnalyzer.cs b/app/SourceCodeRules/SourceCodeRules/NamingAnalyzers/LocalConstantsAnalyzer.cs index da0e130e..3c7e5b25 100644 --- a/app/SourceCodeRules/SourceCodeRules/NamingAnalyzers/LocalConstantsAnalyzer.cs +++ b/app/SourceCodeRules/SourceCodeRules/NamingAnalyzers/LocalConstantsAnalyzer.cs @@ -59,5 +59,5 @@ public sealed class LocalConstantsAnalyzer : DiagnosticAnalyzer } private static bool IsUpperCase(string name) => name.All(c => char.IsUpper(c) || char.IsDigit(c) || c == '_') && - !string.IsNullOrEmpty(name) && name.Any(char.IsLetter); + !string.IsNullOrWhiteSpace(name) && name.Any(char.IsLetter); } \ No newline at end of file diff --git a/runtime/src/file_data.rs b/runtime/src/file_data.rs index b1e5ff54..dee8174e 100644 --- a/runtime/src/file_data.rs +++ b/runtime/src/file_data.rs @@ -7,7 +7,6 @@ use file_format::{FileFormat, Kind}; use futures::{Stream, StreamExt}; use pdfium_render::prelude::Pdfium; use tokio::io::AsyncBufReadExt; -use tokio::process::Command; use tokio::sync::mpsc; use tokio_stream::wrappers::ReceiverStream; use rocket::Shutdown; @@ -16,6 +15,7 @@ use rocket::tokio::select; use rocket::serde::Serialize; use rocket::get; use crate::api_token::APIToken; +use crate::pandoc::PandocProcessBuilder; use crate::pdfium::PdfiumInit; #[derive(Debug, Serialize)] @@ -255,12 +255,13 @@ async fn convert_with_pandoc( from: &str, to: &str, ) -> Result { - let output = Command::new("pandoc") - .arg(file_path) - .args(["-f", from, "-t", to]) - .output() - .await?; - + let output = PandocProcessBuilder::new() + .with_input_file(file_path) + .with_input_format(from) + .with_output_format(to) + .build() + .command.output().await?; + let stream = stream! { if output.status.success() { match String::from_utf8(output.stdout.clone()) { diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index cb79a81c..7868a7a4 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -11,4 +11,5 @@ pub mod runtime_api; pub mod certificate; pub mod file_data; pub mod metadata; -pub mod pdfium; \ No newline at end of file +pub mod pdfium; +pub mod pandoc; \ No newline at end of file diff --git a/runtime/src/pandoc.rs b/runtime/src/pandoc.rs new file mode 100644 index 00000000..47ca1626 --- /dev/null +++ b/runtime/src/pandoc.rs @@ -0,0 +1,169 @@ +use std::path::{Path, PathBuf}; +use std::fs; +use tokio::process::Command; +use crate::environment::DATA_DIRECTORY; +use crate::metadata::META_DATA; + +pub struct PandocExecutable { + pub executable: String, + pub is_local_installation: bool, +} + +pub struct PandocPreparedProcess { + pub command: Command, + pub is_local_installation: bool, +} + +pub struct PandocProcessBuilder { + provided_input_file: Option, + provided_output_file: Option, + provided_input_format: Option, + provided_output_format: Option, + additional_arguments: Vec, +} + +impl Default for PandocProcessBuilder { + fn default() -> Self { + Self::new() + } +} + +impl PandocProcessBuilder { + pub fn new() -> Self { + Self { + provided_input_file: None, + provided_output_file: None, + provided_input_format: None, + provided_output_format: None, + additional_arguments: Vec::new(), + } + } + + pub fn with_input_file>(mut self, input_file: S) -> Self { + self.provided_input_file = Some(input_file.into()); + self + } + + pub fn with_output_file>(mut self, output_file: S) -> Self { + self.provided_output_file = Some(output_file.into()); + self + } + + pub fn with_input_format>(mut self, input_format: S) -> Self { + self.provided_input_format = Some(input_format.into()); + self + } + + pub fn with_output_format>(mut self, output_format: S) -> Self { + self.provided_output_format = Some(output_format.into()); + self + } + + pub fn add_argument>(mut self, argument: S) -> Self { + self.additional_arguments.push(argument.into()); + self + } + + pub fn build(self) -> PandocPreparedProcess { + let mut arguments = Vec::new(); + if let Some(input_file) = &self.provided_input_file { + arguments.push(input_file.clone()); + } + + if let Some(input_format) = &self.provided_input_format { + arguments.push("-f".to_string()); + arguments.push(input_format.clone()); + } + + if let Some(output_format) = &self.provided_output_format { + arguments.push("-t".to_string()); + arguments.push(output_format.clone()); + } + + for additional_argument in &self.additional_arguments { + arguments.push(additional_argument.clone()); + } + + if let Some(output_file) = &self.provided_output_file { + arguments.push("-o".to_string()); + arguments.push(output_file.clone()); + } + + let pandoc_executable = Self::pandoc_executable_path(); + let mut command = Command::new(&pandoc_executable.executable); + command.args(&arguments); + + PandocPreparedProcess { + command, + is_local_installation: pandoc_executable.is_local_installation, + } + } + + /// Returns the path to the pandoc executable. + /// + /// Any local installation of pandoc will be preferred over the system-wide installation. + /// When a local installation is found, its absolute path will be returned. In case no local + /// installation is found, the name of the pandoc executable will be returned. + fn pandoc_executable_path() -> PandocExecutable { + // First, we try to find the pandoc executable in the data directory. + // Any local installation should be preferred over the system-wide installation. + let data_folder = PathBuf::from(DATA_DIRECTORY.get().unwrap()); + let local_installation_root_directory = data_folder.join("pandoc"); + + if local_installation_root_directory.exists() { + let executable_name = Self::pandoc_executable_name(); + + if let Ok(entries) = fs::read_dir(&local_installation_root_directory) { + for entry in entries.flatten() { + let path = entry.path(); + if path.is_dir() { + if let Ok(pandoc_path) = Self::find_executable_in_dir(&path, &executable_name) { + return PandocExecutable { + executable: pandoc_path.to_string_lossy().to_string(), + is_local_installation: true, + }; + } + } + } + } + } + + // When no local installation was found, we assume that the pandoc executable is in the system PATH: + PandocExecutable { + executable: Self::pandoc_executable_name(), + is_local_installation: false, + } + } + + fn find_executable_in_dir(dir: &Path, executable_name: &str) -> Result> { + let pandoc_path = dir.join(executable_name); + if pandoc_path.exists() && pandoc_path.is_file() { + return Ok(pandoc_path); + } + + // Recursively search in subdirectories + if let Ok(entries) = fs::read_dir(dir) { + for entry in entries.flatten() { + let path = entry.path(); + if path.is_dir() { + if let Ok(found_path) = Self::find_executable_in_dir(&path, executable_name) { + return Ok(found_path); + } + } + } + } + + Err("Executable not found".into()) + } + + /// Reads the os platform to determine the used executable name. + fn pandoc_executable_name() -> String { + let metadata = META_DATA.lock().unwrap(); + let metadata = metadata.as_ref().unwrap(); + + match metadata.architecture.as_str() { + "win-arm64" | "win-x64" => "pandoc.exe".to_string(), + _ => "pandoc".to_string(), + } + } +} \ No newline at end of file