From 953d75efd9e81a619301df83a19604b7ead2479c Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 19 Oct 2025 14:39:05 +0200 Subject: [PATCH 01/42] Fixed order of inherit instruction --- app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor index bada49bf..997b6637 100644 --- a/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor +++ b/app/MindWork AI Studio/Assistants/ERI/AssistantERI.razor @@ -1,7 +1,8 @@ @attribute [Route(Routes.ASSISTANT_ERI)] +@inherits AssistantBaseCore + @using AIStudio.Settings.DataModel @using MudExtensions -@inherits AssistantBaseCore @T("You can imagine it like this: Hypothetically, when Wikipedia implemented the ERI, it would vectorize all pages using an embedding method. All of Wikipedia’s data would remain with Wikipedia, including the vector database (decentralized approach). Then, any AI Studio user could add Wikipedia as a data source to significantly reduce the hallucination of the LLM in knowledge questions.") From 72e36366b648c8a1b9571503ab42a35ea8b15ac0 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 19 Oct 2025 14:39:40 +0200 Subject: [PATCH 02/42] Draft of document analysis assistant --- .../DocumentAnalysisAssistant.razor | 65 +++++ .../DocumentAnalysisAssistant.razor.cs | 262 ++++++++++++++++++ .../Assistants/I18N/allTexts.lua | 126 +++++++++ .../SettingsDialogDocumentAnalysis.razor | 28 ++ .../SettingsDialogDocumentAnalysis.razor.cs | 3 + app/MindWork AI Studio/Pages/Assistants.razor | 6 + app/MindWork AI Studio/Routes.razor.cs | 1 + .../Settings/DataModel/Data.cs | 2 + .../DataModel/DataDocumentAnalysis.cs | 18 ++ .../DataModel/DataDocumentAnalysisPolicy.cs | 47 ++++ .../Settings/DataModel/PreviewFeatures.cs | 1 + .../DataModel/PreviewFeaturesExtensions.cs | 1 + .../DataModel/PreviewVisibilityExtensions.cs | 1 + app/MindWork AI Studio/Tools/Components.cs | 1 + 14 files changed, 562 insertions(+) create mode 100644 app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor create mode 100644 app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs create mode 100644 app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor create mode 100644 app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysis.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysisPolicy.cs diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor new file mode 100644 index 00000000..0f266cc7 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -0,0 +1,65 @@ +@attribute [Route(Routes.ASSISTANT_DOCUMENT_ANALYSIS)] +@inherits AssistantBaseCore + +@using AIStudio.Settings.DataModel + + +
+ + + @T("Document analysis policies") + + + + @T("Here you have the option to save different policies for various document analysis assistants and switch between them.") + + +@if(this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Count is 0) +{ + + @T("You have not yet added any document analysis policies.") + +} +else +{ + + @foreach (var policy in this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies) + { + + @policy.PolicyName + + } + +} + + + + @T("Add policy") + + + @T("Delete this policy") + + + +
+ + + + + @T("Common settings") + + + + + + + @T("Input and output rules") + + + + + + + TODO + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs new file mode 100644 index 00000000..2cc6dbd7 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -0,0 +1,262 @@ +using System.Text; + +using AIStudio.Chat; +using AIStudio.Dialogs; +using AIStudio.Dialogs.Settings; +using AIStudio.Settings.DataModel; + +using Microsoft.AspNetCore.Components; + +using DialogOptions = AIStudio.Dialogs.DialogOptions; + +namespace AIStudio.Assistants.DocumentAnalysis; + +public partial class DocumentAnalysisAssistant : AssistantBaseCore +{ + [Inject] + private IDialogService DialogService { get; init; } = null!; + + public override Tools.Components Component => Tools.Components.DOCUMENT_ANALYSIS_ASSISTANT; + + protected override string Title => T("Document Analysis Assistant"); + + protected override string Description => T( + """ + The document analysis assistant helps you to analyze and extract information from documents + based on predefined policies. You can create, edit, and manage document analysis policies + that define how documents should be processed and what information should be extracted. + Some policies might be protected by your organization and cannot be modified or deleted. + """); + + protected override string SystemPrompt + { + get + { + var sb = new StringBuilder(); + return sb.ToString(); + } + } + + protected override IReadOnlyList FooterButtons => []; + + protected override bool ShowEntireChatThread => true; + + protected override bool ShowSendTo => true; + + protected override string SubmitText => T("Analyze document"); + + protected override Func SubmitAction => this.Analyze; + + protected override bool SubmitDisabled => this.IsNoPolicySelected; + + protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with + { + SystemPrompt = SystemPrompts.DEFAULT, + }; + + protected override void ResetForm() + { + if (!this.MightPreselectValues()) + { + this.policyName = string.Empty; + this.policyDescription = string.Empty; + this.policyIsProtected = false; + this.policyAnalysisRules = string.Empty; + this.policyOutputRules = string.Empty; + } + } + + protected override bool MightPreselectValues() + { + if (this.selectedPolicy is not null) + { + this.policyName = this.selectedPolicy.PolicyName; + this.policyDescription = this.selectedPolicy.PolicyDescription; + this.policyIsProtected = this.selectedPolicy.IsProtected; + this.policyAnalysisRules = this.selectedPolicy.AnalysisRules; + this.policyOutputRules = this.selectedPolicy.OutputRules; + + return true; + } + + return false; + } + + protected override async Task OnFormChange() + { + await this.AutoSave(); + } + + #region Overrides of AssistantBase + + protected override async Task OnInitializedAsync() + { + this.selectedPolicy = this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.FirstOrDefault(); + if(this.selectedPolicy is null) + { + await this.AddPolicy(); + this.selectedPolicy = this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.First(); + } + + await base.OnInitializedAsync(); + } + + #endregion + + private async Task AutoSave(bool force = false) + { + if(this.selectedPolicy is null) + return; + + if(!force && this.selectedPolicy.IsProtected) + return; + + if(!force && this.policyIsProtected) + return; + + this.selectedPolicy.PreselectedProvider = this.providerSettings.Id; + + this.selectedPolicy.PolicyName = this.policyName; + this.selectedPolicy.PolicyDescription = this.policyDescription; + this.selectedPolicy.IsProtected = this.policyIsProtected; + this.selectedPolicy.AnalysisRules = this.policyAnalysisRules; + this.selectedPolicy.OutputRules = this.policyOutputRules; + + await this.SettingsManager.StoreSettings(); + } + + private DataDocumentAnalysisPolicy? selectedPolicy; + private bool policyIsProtected; + private string policyName = string.Empty; + private string policyDescription = string.Empty; + private string policyAnalysisRules = string.Empty; + private string policyOutputRules = string.Empty; + + private bool IsNoPolicySelectedOrProtected => this.selectedPolicy is null || this.selectedPolicy.IsProtected; + + private bool IsNoPolicySelected => this.selectedPolicy is null; + + private void SelectedPolicyChanged(DataDocumentAnalysisPolicy? policy) + { + this.selectedPolicy = policy; + this.ResetForm(); + } + + private async Task AddPolicy() + { + this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Add(new () + { + PolicyName = string.Format(T("Policy {0}"), DateTimeOffset.UtcNow), + }); + + await this.SettingsManager.StoreSettings(); + } + + private async Task RemovePolicy() + { + if(this.selectedPolicy is null) + return; + + if(this.selectedPolicy.IsProtected) + return; + + var dialogParameters = new DialogParameters + { + { x => x.Message, string.Format(T("Are you sure you want to delete the document analysis policy '{0}'?"), this.selectedPolicy.PolicyName) }, + }; + + var dialogReference = await this.DialogService.ShowAsync(T("Delete document analysis policy"), dialogParameters, DialogOptions.FULLSCREEN); + var dialogResult = await dialogReference.Result; + if (dialogResult is null || dialogResult.Canceled) + return; + + this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Remove(this.selectedPolicy); + this.selectedPolicy = null; + this.ResetForm(); + + await this.SettingsManager.StoreSettings(); + this.form?.ResetValidation(); + } + + /// + /// Gets called when the policy name was changed by typing. + /// + /// + /// This method is used to update the policy name in the selected policy. + /// Otherwise, the users would be confused when they change the name and the changes are not reflected in the UI. + /// + private void PolicyNameWasChanged() + { + if(this.selectedPolicy is null) + return; + + if(this.selectedPolicy.IsProtected) + return; + + this.selectedPolicy.PolicyName = this.policyName; + } + + private async Task PolicyProtectionWasChanged(bool state) + { + if(this.selectedPolicy is null) + return; + + this.policyIsProtected = state; + this.selectedPolicy.IsProtected = state; + await this.AutoSave(true); + } + + private string? ValidatePolicyName(string name) + { + if(string.IsNullOrWhiteSpace(name)) + return T("Please provide a name for your policy. This name will be used to identify the policy in AI Studio."); + + if(name.Length is > 60 or < 6) + return T("The name of your policy must be between 6 and 60 characters long."); + + if(this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies.Where(n => n != this.selectedPolicy).Any(n => n.PolicyName == name)) + return T("A policy with this name already exists. Please choose a different name."); + + return null; + } + + private string? ValidatePolicyDescription(string description) + { + if(string.IsNullOrWhiteSpace(description)) + return T("Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy."); + + if(description.Length is < 32 or > 512) + return T("The description of your policy must be between 32 and 512 characters long."); + + return null; + } + + private string? ValidateAnalysisRules(string analysisRules) + { + if(string.IsNullOrWhiteSpace(analysisRules)) + return T("Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents."); + + return null; + } + + private string? ValidateOutputRules(string outputRules) + { + if(string.IsNullOrWhiteSpace(outputRules)) + return T("Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis."); + + return null; + } + + private async Task Analyze() + { + if (this.IsNoPolicySelectedOrProtected) + return; + + await this.AutoSave(); + await this.form!.Validate(); + if (!this.inputIsValid) + return; + + #warning TODO + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index d4572354..7728d11d 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -382,6 +382,96 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T -- None UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T810547195"] = "None" +-- Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1182372158"] = "Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio." + +-- Settings +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1258653480"] = "Settings" + +-- No, the policy can be edited +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1286595725"] = "No, the policy can be edited" + +-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents." + +-- Input and output rules +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Input and output rules" + +-- Yes, protect this policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy" + +-- Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1786783201"] = "Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio." + +-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy." + +-- Common settings +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings" + +-- Analyze document +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2053296240"] = "Analyze document" + +-- Document analysis policies +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2064879144"] = "Document analysis policies" + +-- The name of your policy must be between 6 and 60 characters long. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "The name of your policy must be between 6 and 60 characters long." + +-- Are you sure you want to delete the document analysis policy '{0}'? +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2582525917"] = "Are you sure you want to delete the document analysis policy '{0}'?" + +-- Document analysis +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2708005534"] = "Document analysis" + +-- Policy name +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name" + +-- Analysis rules +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3108719748"] = "Analysis rules" + +-- Delete this policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3119086260"] = "Delete this policy" + +-- Policy {0} +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Policy {0}" + +-- The description of your policy must be between 32 and 512 characters long. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "The description of your policy must be between 32 and 512 characters long." + +-- Add policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3357792182"] = "Add policy" + +-- You have not yet added any document analysis policies. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3394850216"] = "You have not yet added any document analysis policies." + +-- Document Analysis Assistant +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T348883878"] = "Document Analysis Assistant" + +-- A policy with this name already exists. Please choose a different name. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3584374593"] = "A policy with this name already exists. Please choose a different name." + +-- Output rules +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3918193587"] = "Output rules" + +-- Please provide a name for your policy. This name will be used to identify the policy in AI Studio. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4040507702"] = "Please provide a name for your policy. This name will be used to identify the policy in AI Studio." + +-- Delete document analysis policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4293094335"] = "Delete document analysis policy" + +-- Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T652187065"] = "Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis." + +-- Policy description +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Policy description" + +-- Would you like to protect this policy so that you cannot accidentally edit or delete it? +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T80597472"] = "Would you like to protect this policy so that you cannot accidentally edit or delete it?" + +-- Here you have the option to save different policies for various document analysis assistants and switch between them. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Here you have the option to save different policies for various document analysis assistants and switch between them." + -- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input." @@ -3604,6 +3694,33 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473 -- Local Directory UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory" +-- When enabled, you can preselect some ERI server options. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1280666275"] = "When enabled, you can preselect some ERI server options." + +-- Assistant: Document Analysis +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistant: Document Analysis" + +-- Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1870328357"] = "Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function." + +-- Would you like to preselect one of your profiles? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2221665527"] = "Would you like to preselect one of your profiles?" + +-- Preselect document analysis options? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Preselect document analysis options?" + +-- No document analysis options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "No document analysis options are preselected" + +-- Close +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3448155331"] = "Close" + +-- Document analysis options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3945756386"] = "Document analysis options are preselected" + +-- Preselect one of your profiles? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T4004501229"] = "Preselect one of your profiles?" + -- When enabled, you can preselect some ERI server options. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options." @@ -4477,6 +4594,9 @@ 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." +-- Analyze a document regarding defined rules and extract key information. +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1271524187"] = "Analyze a document regarding defined rules and extract key information." + -- Business UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T131837803"] = "Business" @@ -4522,6 +4642,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2547582747"] = "Synonyms" -- Find synonyms for a given word or phrase. UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2712131461"] = "Find synonyms for a given word or phrase." +-- Document Analysis +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2770149758"] = "Document Analysis" + -- AI Studio Development UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2830810750"] = "AI Studio Development" @@ -5044,6 +5167,9 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1587 -- Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1847148141"] = "Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files" +-- Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1848209619"] = "Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents" + -- Plugins: Preview of our plugin system where you can extend the functionality of the app UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2056842933"] = "Plugins: Preview of our plugin system where you can extend the functionality of the app" diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor new file mode 100644 index 00000000..7cdd4455 --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor @@ -0,0 +1,28 @@ +@using AIStudio.Settings +@inherits SettingsDialogBase + + + + + + + @T("Assistant: Document Analysis") + + + + + + + + + + @T("Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function.") + + + + + + @T("Close") + + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor.cs new file mode 100644 index 00000000..caafcb44 --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor.cs @@ -0,0 +1,3 @@ +namespace AIStudio.Dialogs.Settings; + +public partial class SettingsDialogDocumentAnalysis : SettingsDialogBase; \ No newline at end of file diff --git a/app/MindWork AI Studio/Pages/Assistants.razor b/app/MindWork AI Studio/Pages/Assistants.razor index d7fe0bed..1cd72a5f 100644 --- a/app/MindWork AI Studio/Pages/Assistants.razor +++ b/app/MindWork AI Studio/Pages/Assistants.razor @@ -26,6 +26,12 @@ + + @if (PreviewFeatures.PRE_DOCUMENT_ANALYSIS_2025.IsEnabled(this.SettingsManager)) + { + + } + diff --git a/app/MindWork AI Studio/Routes.razor.cs b/app/MindWork AI Studio/Routes.razor.cs index d59bffac..836cab0e 100644 --- a/app/MindWork AI Studio/Routes.razor.cs +++ b/app/MindWork AI Studio/Routes.razor.cs @@ -27,5 +27,6 @@ public sealed partial class Routes public const string ASSISTANT_BIAS = "/assistant/bias-of-the-day"; public const string ASSISTANT_ERI = "/assistant/eri"; public const string ASSISTANT_AI_STUDIO_I18N = "/assistant/ai-studio/i18n"; + public const string ASSISTANT_DOCUMENT_ANALYSIS = "/assistant/document-analysis"; // ReSharper restore InconsistentNaming } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/Data.cs b/app/MindWork AI Studio/Settings/DataModel/Data.cs index 0e825aa0..8c8a1ef8 100644 --- a/app/MindWork AI Studio/Settings/DataModel/Data.cs +++ b/app/MindWork AI Studio/Settings/DataModel/Data.cs @@ -84,6 +84,8 @@ public sealed class Data public DataCoding Coding { get; init; } = new(); public DataERI ERI { get; init; } = new(); + + public DataDocumentAnalysis DocumentAnalysis { get; init; } = new(x => x.DocumentAnalysis); public DataTextSummarizer TextSummarizer { get; init; } = new(); diff --git a/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysis.cs b/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysis.cs new file mode 100644 index 00000000..c0f58d6f --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysis.cs @@ -0,0 +1,18 @@ +using System.Linq.Expressions; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataDocumentAnalysis(Expression>? configSelection = null) +{ + /// + /// The default constructor for the JSON deserializer. + /// + public DataDocumentAnalysis() : this(null) + { + } + + /// + /// Configured document analysis policies. + /// + public List Policies { get; set; } = []; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysisPolicy.cs b/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysisPolicy.cs new file mode 100644 index 00000000..a71a1478 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysisPolicy.cs @@ -0,0 +1,47 @@ +using AIStudio.Provider; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataDocumentAnalysisPolicy +{ + /// + /// Preselect the policy name? + /// + public string PolicyName { get; set; } = string.Empty; + + /// + /// Preselect the policy description? + /// + public string PolicyDescription { get; set; } = string.Empty; + + /// + /// Is this policy protected? If so, it cannot be deleted or modified by the user. + /// This is useful for policies that are distributed by the organization. + /// + public bool IsProtected { get; set; } + + /// + /// The rules for the document analysis policy. + /// + public string AnalysisRules { get; set; } = string.Empty; + + /// + /// The rules for the output of the document analysis, e.g., the desired format, structure, etc. + /// + public string OutputRules { get; set; } = string.Empty; + + /// + /// The minimum confidence level required for a provider to be considered. + /// + public ConfidenceLevel MinimumProviderConfidence { get; set; } = ConfidenceLevel.NONE; + + /// + /// Which LLM provider should be preselected? + /// + public string PreselectedProvider { get; set; } = string.Empty; + + /// + /// Preselect a profile? + /// + public string PreselectedProfile { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/PreviewFeatures.cs b/app/MindWork AI Studio/Settings/DataModel/PreviewFeatures.cs index 85acedec..49aad8d0 100644 --- a/app/MindWork AI Studio/Settings/DataModel/PreviewFeatures.cs +++ b/app/MindWork AI Studio/Settings/DataModel/PreviewFeatures.cs @@ -11,4 +11,5 @@ public enum PreviewFeatures PRE_PLUGINS_2025, PRE_READ_PDF_2025, + PRE_DOCUMENT_ANALYSIS_2025, } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/PreviewFeaturesExtensions.cs b/app/MindWork AI Studio/Settings/DataModel/PreviewFeaturesExtensions.cs index 3736dd80..e80495b2 100644 --- a/app/MindWork AI Studio/Settings/DataModel/PreviewFeaturesExtensions.cs +++ b/app/MindWork AI Studio/Settings/DataModel/PreviewFeaturesExtensions.cs @@ -13,6 +13,7 @@ public static class PreviewFeaturesExtensions PreviewFeatures.PRE_PLUGINS_2025 => TB("Plugins: Preview of our plugin system where you can extend the functionality of the app"), PreviewFeatures.PRE_READ_PDF_2025 => TB("Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files"), + PreviewFeatures.PRE_DOCUMENT_ANALYSIS_2025 => TB("Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents"), _ => TB("Unknown preview feature") }; diff --git a/app/MindWork AI Studio/Settings/DataModel/PreviewVisibilityExtensions.cs b/app/MindWork AI Studio/Settings/DataModel/PreviewVisibilityExtensions.cs index f80939f6..bd648b24 100644 --- a/app/MindWork AI Studio/Settings/DataModel/PreviewVisibilityExtensions.cs +++ b/app/MindWork AI Studio/Settings/DataModel/PreviewVisibilityExtensions.cs @@ -20,6 +20,7 @@ public static class PreviewVisibilityExtensions if (visibility >= PreviewVisibility.PROTOTYPE) { features.Add(PreviewFeatures.PRE_RAG_2024); + features.Add(PreviewFeatures.PRE_DOCUMENT_ANALYSIS_2025); } if (visibility >= PreviewVisibility.EXPERIMENTAL) diff --git a/app/MindWork AI Studio/Tools/Components.cs b/app/MindWork AI Studio/Tools/Components.cs index 94148d5e..1004188c 100644 --- a/app/MindWork AI Studio/Tools/Components.cs +++ b/app/MindWork AI Studio/Tools/Components.cs @@ -18,6 +18,7 @@ public enum Components JOB_POSTING_ASSISTANT, BIAS_DAY_ASSISTANT, ERI_ASSISTANT, + DOCUMENT_ANALYSIS_ASSISTANT, // ReSharper disable InconsistentNaming I18N_ASSISTANT, From 6fa566224de35af10e82501f9195f4d74776acb6 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 19 Oct 2025 14:52:08 +0200 Subject: [PATCH 03/42] Changed title for settings --- .../Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 0f266cc7..31c45ab9 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -44,7 +44,7 @@ else
- + @T("Common settings") From 4f04c0933ebb9fdf3f46a05b146f43a7928fbff5 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 19 Oct 2025 14:52:17 +0200 Subject: [PATCH 04/42] Added todo --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 2cc6dbd7..78f7f02c 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -33,6 +33,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore Date: Sun, 19 Oct 2025 14:52:46 +0200 Subject: [PATCH 05/42] Optimized header of analysis --- .../Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 31c45ab9..d7728d03 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -59,7 +59,7 @@ else - + TODO \ No newline at end of file From c36c83dad5cddce7199d26369174570eb956bec2 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 19 Oct 2025 14:53:05 +0200 Subject: [PATCH 06/42] Added WIP section for exporting --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor | 8 ++++++++ app/MindWork AI Studio/Assistants/I18N/allTexts.lua | 9 ++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index d7728d03..ab74ba71 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -57,6 +57,14 @@ else + + + @T("Preparation for enterprise distribution") + + + + Export policy as configuration section + diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 7728d11d..32413781 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -385,9 +385,6 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T -- Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1182372158"] = "Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio." --- Settings -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1258653480"] = "Settings" - -- No, the policy can be edited UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1286595725"] = "No, the policy can be edited" @@ -415,6 +412,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Document analysis policies UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2064879144"] = "Document analysis policies" +-- Definition +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T222998208"] = "Definition" + -- The name of your policy must be between 6 and 60 characters long. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "The name of your policy must be between 6 and 60 characters long." @@ -454,6 +454,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Output rules UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3918193587"] = "Output rules" +-- Preparation for enterprise distribution +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T39557294"] = "Preparation for enterprise distribution" + -- Please provide a name for your policy. This name will be used to identify the policy in AI Studio. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4040507702"] = "Please provide a name for your policy. This name will be used to identify the policy in AI Studio." From 2f92ced7009fd19e2c801eeda1ce6a07651a5426 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 20 Oct 2025 15:51:27 +0200 Subject: [PATCH 07/42] Refactored enum name retrieval for components --- app/MindWork AI Studio/Tools/ComponentsExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs index a2126970..af72f638 100644 --- a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs +++ b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs @@ -45,7 +45,7 @@ public static class ComponentsExtensions Components.CHAT => TB("New Chat"), - _ => Enum.GetName(typeof(Components), component)!, + _ => Enum.GetName(component)!, }; public static ComponentsData GetData(this Components destination) => destination switch From 76384e6eab9763b7ba76bfd5b1937f5eaa91afe5 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 20 Oct 2025 15:59:46 +0200 Subject: [PATCH 08/42] Added support for Document Analysis Assistant in components and events --- app/MindWork AI Studio/Tools/ComponentsExtensions.cs | 2 ++ app/MindWork AI Studio/Tools/Event.cs | 1 + 2 files changed, 3 insertions(+) diff --git a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs index af72f638..b4f0dd5a 100644 --- a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs +++ b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs @@ -42,6 +42,7 @@ public static class ComponentsExtensions Components.JOB_POSTING_ASSISTANT => TB("Job Posting Assistant"), Components.ERI_ASSISTANT => TB("ERI Server"), Components.I18N_ASSISTANT => TB("Localization Assistant"), + Components.DOCUMENT_ANALYSIS_ASSISTANT => TB("Document Analysis Assistant"), Components.CHAT => TB("New Chat"), @@ -62,6 +63,7 @@ public static class ComponentsExtensions Components.SYNONYMS_ASSISTANT => new(Event.SEND_TO_SYNONYMS_ASSISTANT, Routes.ASSISTANT_SYNONYMS), Components.MY_TASKS_ASSISTANT => new(Event.SEND_TO_MY_TASKS_ASSISTANT, Routes.ASSISTANT_MY_TASKS), Components.JOB_POSTING_ASSISTANT => new(Event.SEND_TO_JOB_POSTING_ASSISTANT, Routes.ASSISTANT_JOB_POSTING), + Components.DOCUMENT_ANALYSIS_ASSISTANT => new(Event.SEND_TO_DOCUMENT_ANALYSIS_ASSISTANT, Routes.ASSISTANT_DOCUMENT_ANALYSIS), Components.CHAT => new(Event.SEND_TO_CHAT, Routes.CHAT), diff --git a/app/MindWork AI Studio/Tools/Event.cs b/app/MindWork AI Studio/Tools/Event.cs index fcf32604..8d8ce415 100644 --- a/app/MindWork AI Studio/Tools/Event.cs +++ b/app/MindWork AI Studio/Tools/Event.cs @@ -47,4 +47,5 @@ public enum Event SEND_TO_SYNONYMS_ASSISTANT, SEND_TO_MY_TASKS_ASSISTANT, SEND_TO_JOB_POSTING_ASSISTANT, + SEND_TO_DOCUMENT_ANALYSIS_ASSISTANT, } \ No newline at end of file From 857e58648ded2c3b32e285c01216ba14fc7dac92 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 20 Oct 2025 16:00:02 +0200 Subject: [PATCH 09/42] Added todos --- app/MindWork AI Studio/Tools/ComponentsExtensions.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs index b4f0dd5a..f69f0c34 100644 --- a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs +++ b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs @@ -86,6 +86,9 @@ public static class ComponentsExtensions Components.JOB_POSTING_ASSISTANT => settingsManager.ConfigurationData.JobPostings.PreselectOptions ? settingsManager.ConfigurationData.JobPostings.MinimumProviderConfidence : default, Components.BIAS_DAY_ASSISTANT => settingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions ? settingsManager.ConfigurationData.BiasOfTheDay.MinimumProviderConfidence : default, Components.ERI_ASSISTANT => settingsManager.ConfigurationData.ERI.PreselectOptions ? settingsManager.ConfigurationData.ERI.MinimumProviderConfidence : default, + + #warning Add minimum confidence for DOCUMENT_ANALYSIS_ASSISTANT: + //Components.DOCUMENT_ANALYSIS_ASSISTANT => settingsManager.ConfigurationData.DocumentAnalysis.PreselectOptions ? settingsManager.ConfigurationData.DocumentAnalysis.MinimumProviderConfidence : default, _ => default, }; @@ -110,6 +113,9 @@ public static class ComponentsExtensions Components.BIAS_DAY_ASSISTANT => settingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.BiasOfTheDay.PreselectedProvider) : null, Components.ERI_ASSISTANT => settingsManager.ConfigurationData.ERI.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.ERI.PreselectedProvider) : null, Components.I18N_ASSISTANT => settingsManager.ConfigurationData.I18N.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.I18N.PreselectedProvider) : null, + + #warning Add preselected provider for DOCUMENT_ANALYSIS_ASSISTANT: + //Components.DOCUMENT_ANALYSIS_ASSISTANT => settingsManager.ConfigurationData.DocumentAnalysis.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.DocumentAnalysis.PreselectedProvider) : null, Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Chat.PreselectedProvider) : null, @@ -132,6 +138,9 @@ public static class ComponentsExtensions Components.MY_TASKS_ASSISTANT => settingsManager.ConfigurationData.MyTasks.PreselectOptions ? settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.MyTasks.PreselectedProfile) : default, Components.BIAS_DAY_ASSISTANT => settingsManager.ConfigurationData.BiasOfTheDay.PreselectOptions ? settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.BiasOfTheDay.PreselectedProfile) : default, Components.ERI_ASSISTANT => settingsManager.ConfigurationData.ERI.PreselectOptions ? settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.ERI.PreselectedProfile) : default, + + #warning Add preselected profile for DOCUMENT_ANALYSIS_ASSISTANT: + // Components.DOCUMENT_ANALYSIS_ASSISTANT => settingsManager.ConfigurationData.DocumentAnalysis.PreselectOptions ? settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.DocumentAnalysis.PreselectedProfile) : default, Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Chat.PreselectedProfile) : default, From 1486528491a8c2065ea8596ac4ea996ccda0abf6 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 20 Oct 2025 16:00:38 +0200 Subject: [PATCH 10/42] Updated the all texts file --- app/MindWork AI Studio/Assistants/I18N/allTexts.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 32413781..a1e5bacf 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -5293,6 +5293,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2684676843"] = "Text Su -- Synonym Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2921123194"] = "Synonym Assistant" +-- Document Analysis Assistant +UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T348883878"] = "Document Analysis Assistant" + -- Translation Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T3887962308"] = "Translation Assistant" From cd9d6b225875fcebfe0fe0b60ac892b163e66cfc Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 20 Oct 2025 16:04:03 +0200 Subject: [PATCH 11/42] Prepared handling of deferred content --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 78f7f02c..3a5a10b9 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -98,6 +98,11 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore(Event.SEND_TO_DOCUMENT_ANALYSIS_ASSISTANT).FirstOrDefault(); + // if (deferredContent is not null) + #warning Add handling of deferred content -> load into input area + //this. await base.OnInitializedAsync(); } From a6a52989b80fd81cd21af2e594cefa4f927d3782 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 20 Oct 2025 18:46:56 +0200 Subject: [PATCH 12/42] Enhance policy protection feature and add managed policy property --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor | 2 +- .../Settings/DataModel/DataDocumentAnalysisPolicy.cs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index ab74ba71..18c0e258 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -50,7 +50,7 @@ else - + @T("Input and output rules") diff --git a/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysisPolicy.cs b/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysisPolicy.cs index a71a1478..aae8ede1 100644 --- a/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysisPolicy.cs +++ b/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysisPolicy.cs @@ -16,10 +16,15 @@ public sealed class DataDocumentAnalysisPolicy /// /// Is this policy protected? If so, it cannot be deleted or modified by the user. - /// This is useful for policies that are distributed by the organization. /// public bool IsProtected { get; set; } + /// + /// Is this a managed policy? Managed policies are created and managed by the organization + /// and cannot be modified or deleted by the user. + /// + public bool IsManaged { get; set; } + /// /// The rules for the document analysis policy. /// From ce302e7b98acf998742ab5464e1ff31b14c0fb82 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 21 Oct 2025 15:13:18 +0200 Subject: [PATCH 13/42] Added debug logging --- runtime/src/app_window.rs | 141 +++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 69 deletions(-) diff --git a/runtime/src/app_window.rs b/runtime/src/app_window.rs index b551b0f0..a03a3440 100644 --- a/runtime/src/app_window.rs +++ b/runtime/src/app_window.rs @@ -1,6 +1,6 @@ use std::sync::Mutex; use std::time::Duration; -use log::{error, info, trace, warn}; +use log::{debug, error, info, trace, warn}; use once_cell::sync::Lazy; use rocket::{get, post}; use rocket::serde::json::Json; @@ -46,84 +46,87 @@ pub fn start_tauri() { .build(tauri::generate_context!()) .expect("Error while running Tauri application"); - app.run(|app_handle, event| match event { - - tauri::RunEvent::WindowEvent { event, label, .. } => { - match event { - tauri::WindowEvent::CloseRequested { .. } => { - warn!(Source = "Tauri"; "Window '{label}': close was requested."); - } - - tauri::WindowEvent::Destroyed => { - warn!(Source = "Tauri"; "Window '{label}': was destroyed."); - } - - tauri::WindowEvent::FileDrop(files) => { - info!(Source = "Tauri"; "Window '{label}': files were dropped: {files:?}"); - } - - _ => (), - } + app.run(|app_handle, event| { + if !matches!(event, tauri::RunEvent::MainEventsCleared) { + debug!(Source = "Tauri"; "Event received: {event:?}"); } - - tauri::RunEvent::Updater(updater_event) => { - match updater_event { - - tauri::UpdaterEvent::UpdateAvailable { body, date, version } => { - let body_len = body.len(); - info!(Source = "Tauri"; "Updater: update available: body size={body_len} time={date:?} version={version}"); - } - - tauri::UpdaterEvent::Pending => { - info!(Source = "Tauri"; "Updater: update is pending!"); - } - - tauri::UpdaterEvent::DownloadProgress { chunk_length, content_length: _ } => { - trace!(Source = "Tauri"; "Updater: downloading chunk of {chunk_length} bytes"); - } - - tauri::UpdaterEvent::Downloaded => { - info!(Source = "Tauri"; "Updater: update has been downloaded!"); - warn!(Source = "Tauri"; "Try to stop the .NET server now..."); - - if is_prod() { - stop_dotnet_server(); - } else { - warn!(Source = "Tauri"; "Development environment detected; do not stop the .NET server."); - } - } - - tauri::UpdaterEvent::Updated => { - info!(Source = "Tauri"; "Updater: app has been updated"); - warn!(Source = "Tauri"; "Try to restart the app now..."); - - if is_prod() { - app_handle.restart(); - } else { - warn!(Source = "Tauri"; "Development environment detected; do not restart the app."); + + match event { + tauri::RunEvent::WindowEvent { event, label, .. } => { + match event { + tauri::WindowEvent::CloseRequested { .. } => { + warn!(Source = "Tauri"; "Window '{label}': close was requested."); } - } + tauri::WindowEvent::Destroyed => { + warn!(Source = "Tauri"; "Window '{label}': was destroyed."); + } - tauri::UpdaterEvent::AlreadyUpToDate => { - info!(Source = "Tauri"; "Updater: app is already up to date"); - } + tauri::WindowEvent::FileDrop(files) => { + info!(Source = "Tauri"; "Window '{label}': files were dropped: {files:?}"); + } - tauri::UpdaterEvent::Error(error) => { - warn!(Source = "Tauri"; "Updater: failed to update: {error}"); + _ => (), } } - } - tauri::RunEvent::ExitRequested { .. } => { - warn!(Source = "Tauri"; "Run event: exit was requested."); - } + tauri::RunEvent::Updater(updater_event) => { + match updater_event { + tauri::UpdaterEvent::UpdateAvailable { body, date, version } => { + let body_len = body.len(); + info!(Source = "Tauri"; "Updater: update available: body size={body_len} time={date:?} version={version}"); + } - tauri::RunEvent::Ready => { - info!(Source = "Tauri"; "Run event: Tauri app is ready."); - } + tauri::UpdaterEvent::Pending => { + info!(Source = "Tauri"; "Updater: update is pending!"); + } - _ => {} + tauri::UpdaterEvent::DownloadProgress { chunk_length, content_length: _ } => { + trace!(Source = "Tauri"; "Updater: downloading chunk of {chunk_length} bytes"); + } + + tauri::UpdaterEvent::Downloaded => { + info!(Source = "Tauri"; "Updater: update has been downloaded!"); + warn!(Source = "Tauri"; "Try to stop the .NET server now..."); + + if is_prod() { + stop_dotnet_server(); + } else { + warn!(Source = "Tauri"; "Development environment detected; do not stop the .NET server."); + } + } + + tauri::UpdaterEvent::Updated => { + info!(Source = "Tauri"; "Updater: app has been updated"); + warn!(Source = "Tauri"; "Try to restart the app now..."); + + if is_prod() { + app_handle.restart(); + } else { + warn!(Source = "Tauri"; "Development environment detected; do not restart the app."); + } + } + + tauri::UpdaterEvent::AlreadyUpToDate => { + info!(Source = "Tauri"; "Updater: app is already up to date"); + } + + tauri::UpdaterEvent::Error(error) => { + warn!(Source = "Tauri"; "Updater: failed to update: {error}"); + } + } + } + + tauri::RunEvent::ExitRequested { .. } => { + warn!(Source = "Tauri"; "Run event: exit was requested."); + } + + tauri::RunEvent::Ready => { + info!(Source = "Tauri"; "Run event: Tauri app is ready."); + } + + _ => {} + } }); warn!(Source = "Tauri"; "Tauri app was stopped."); From 0441c9c78bcf580c567b0830d1ed6c616593be9c Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 21 Oct 2025 15:14:54 +0200 Subject: [PATCH 14/42] Added another handler for window file drop events --- runtime/src/app_window.rs | 9 +++++++++ runtime/tauri.conf.json | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/runtime/src/app_window.rs b/runtime/src/app_window.rs index a03a3440..57bf80d1 100644 --- a/runtime/src/app_window.rs +++ b/runtime/src/app_window.rs @@ -28,6 +28,15 @@ pub fn start_tauri() { let app = tauri::Builder::default() .setup(move |app| { let window = app.get_window("main").expect("Failed to get main window."); + + // Register a callback for file drop events: + window.on_window_event(|event| + if let tauri::WindowEvent::FileDrop(files) = event { + info!(Source = "Tauri"; "files were dropped: {files:?}"); + } + ); + + // Save the main window for later access: *MAIN_WINDOW.lock().unwrap() = Some(window); info!(Source = "Bootloader Tauri"; "Setup is running."); diff --git a/runtime/tauri.conf.json b/runtime/tauri.conf.json index ed4161f5..e85077b5 100644 --- a/runtime/tauri.conf.json +++ b/runtime/tauri.conf.json @@ -40,7 +40,8 @@ "resizable": true, "title": "MindWork AI Studio", "width": 1920, - "height": 1080 + "height": 1080, + "fileDropEnabled": true } ], "security": { From 398fd613ecc13c2f9ea20321a09e1ad0d8985f4f Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 21 Oct 2025 18:12:42 +0200 Subject: [PATCH 15/42] Refactor StartMaintenance method to return void and simplify maintenance loop --- .../Tools/Services/TemporaryChatService.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/MindWork AI Studio/Tools/Services/TemporaryChatService.cs b/app/MindWork AI Studio/Tools/Services/TemporaryChatService.cs index ab2f39e7..61a6e4c8 100644 --- a/app/MindWork AI Studio/Tools/Services/TemporaryChatService.cs +++ b/app/MindWork AI Studio/Tools/Services/TemporaryChatService.cs @@ -24,24 +24,24 @@ public sealed class TemporaryChatService(ILogger logger, S return; } - await this.StartMaintenance(); + this.StartMaintenance(); while (!stoppingToken.IsCancellationRequested) { await Task.Delay(CHECK_INTERVAL, stoppingToken); - await this.StartMaintenance(); + this.StartMaintenance(); } } #endregion - private Task StartMaintenance() + private void StartMaintenance() { logger.LogInformation("Starting maintenance of temporary chat storage."); var temporaryDirectories = Path.Join(SettingsManager.DataDirectory, "tempChats"); if(!Directory.Exists(temporaryDirectories)) { logger.LogWarning("Temporary chat storage directory does not exist. End maintenance."); - return Task.CompletedTask; + return; } foreach (var tempChatDirPath in Directory.EnumerateDirectories(temporaryDirectories)) @@ -71,7 +71,6 @@ public sealed class TemporaryChatService(ILogger logger, S } logger.LogInformation("Finished maintenance of temporary chat storage."); - return Task.CompletedTask; } public static void Initialize() From 77bd3b389c46a9bc62bd8f4037ab3321f947b70e Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 21 Oct 2025 19:18:54 +0200 Subject: [PATCH 16/42] Implemented the .NET side of Tauri event stream handling --- app/MindWork AI Studio/Program.cs | 5 ++ app/MindWork AI Studio/Tools/Event.cs | 1 + .../Tools/Rust/TauriEvent.cs | 3 ++ .../Tools/Rust/TauriEventType.cs | 11 ++++ .../Tools/Services/RustService.Events.cs | 53 +++++++++++++++++++ .../Tools/Services/RustService.cs | 13 +++-- 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 app/MindWork AI Studio/Tools/Rust/TauriEvent.cs create mode 100644 app/MindWork AI Studio/Tools/Rust/TauriEventType.cs create mode 100644 app/MindWork AI Studio/Tools/Services/RustService.Events.cs diff --git a/app/MindWork AI Studio/Program.cs b/app/MindWork AI Studio/Program.cs index a4d9c2b4..2514a67f 100644 --- a/app/MindWork AI Studio/Program.cs +++ b/app/MindWork AI Studio/Program.cs @@ -133,6 +133,11 @@ internal sealed class Program builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); + + // ReSharper disable AccessToDisposedClosure + builder.Services.AddHostedService(_ => rust); + // ReSharper restore AccessToDisposedClosure + builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddHubOptions(options => diff --git a/app/MindWork AI Studio/Tools/Event.cs b/app/MindWork AI Studio/Tools/Event.cs index 8d8ce415..9f612f04 100644 --- a/app/MindWork AI Studio/Tools/Event.cs +++ b/app/MindWork AI Studio/Tools/Event.cs @@ -14,6 +14,7 @@ public enum Event SHOW_ERROR, SHOW_WARNING, SHOW_SUCCESS, + TAURI_EVENT_RECEIVED, // Update events: USER_SEARCH_FOR_UPDATE, diff --git a/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs b/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs new file mode 100644 index 00000000..140522be --- /dev/null +++ b/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs @@ -0,0 +1,3 @@ +namespace AIStudio.Tools.Rust; + +public readonly record struct TauriEvent(TauriEventType Type, List Payload); \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs b/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs new file mode 100644 index 00000000..2710c16b --- /dev/null +++ b/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs @@ -0,0 +1,11 @@ +namespace AIStudio.Tools.Rust; + +public enum TauriEventType +{ + WINDOW_FOCUSED, + WINDOW_NOT_FOCUSED, + + FILE_DROP_HOVERED, + FILE_DROP_DROPPED, + FILE_DROP_CANCELED, +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Events.cs b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs new file mode 100644 index 00000000..539c3d06 --- /dev/null +++ b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs @@ -0,0 +1,53 @@ +using System.Text.Json; + +using AIStudio.Tools.Rust; + +namespace AIStudio.Tools.Services; + +public partial class RustService +{ + private async Task StartStreamTauriEvents(CancellationToken stopToken) + { + try + { + while (!stopToken.IsCancellationRequested) + { + try + { + await using var stream = await this.http.GetStreamAsync("/events", stopToken); + using var reader = new StreamReader(stream); + while(!reader.EndOfStream) + { + var line = await reader.ReadLineAsync(stopToken); + if (string.IsNullOrWhiteSpace(line)) + continue; + + var tauriEvent = JsonSerializer.Deserialize(line, this.jsonRustSerializerOptions); + if (tauriEvent != default) + await MessageBus.INSTANCE.SendMessage(null, Event.TAURI_EVENT_RECEIVED, tauriEvent); + } + } + + // The cancellation token was triggered, exit the loop: + catch (OperationCanceledException) + { + break; + } + + // Some other error occurred, log it and retry after a delay: + catch (Exception e) + { + this.logger!.LogError("Error while streaming Tauri events: {Message}", e.Message); + await Task.Delay(TimeSpan.FromSeconds(3), stopToken); + } + } + } + + // The cancellation token was triggered, exit the method: + catch (OperationCanceledException) + { + } + + this.logger!.LogWarning("Stopped streaming Tauri events."); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Services/RustService.cs b/app/MindWork AI Studio/Tools/Services/RustService.cs index 38fab8cc..56032b65 100644 --- a/app/MindWork AI Studio/Tools/Services/RustService.cs +++ b/app/MindWork AI Studio/Tools/Services/RustService.cs @@ -8,7 +8,7 @@ namespace AIStudio.Tools.Services; /// /// Calling Rust functions. /// -public sealed partial class RustService : IDisposable +public sealed partial class RustService : BackgroundService { private readonly HttpClient http; @@ -59,11 +59,18 @@ public sealed partial class RustService : IDisposable this.encryptor = encryptionService; } - #region IDisposable + #region Overrides of BackgroundService - public void Dispose() + protected override async Task ExecuteAsync(CancellationToken stopToken) + { + this.logger?.LogInformation("The Rust service was initialized."); + await this.StartStreamTauriEvents(stopToken); + } + + public override void Dispose() { this.http.Dispose(); + base.Dispose(); } #endregion From 085cf29fedea03fc6b237db04b29f8c4cf7e2e66 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 22 Oct 2025 20:20:01 +0200 Subject: [PATCH 17/42] Enhance file drop handling and add logging for events --- runtime/src/app_window.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/runtime/src/app_window.rs b/runtime/src/app_window.rs index 57bf80d1..ee932355 100644 --- a/runtime/src/app_window.rs +++ b/runtime/src/app_window.rs @@ -7,7 +7,7 @@ use rocket::serde::json::Json; use rocket::serde::Serialize; use serde::Deserialize; use tauri::updater::UpdateResponse; -use tauri::{Manager, PathResolver, Window}; +use tauri::{FileDropEvent, Manager, PathResolver, Window}; use tauri::api::dialog::blocking::FileDialogBuilder; use tokio::time; use crate::api_token::APIToken; @@ -31,8 +31,30 @@ pub fn start_tauri() { // Register a callback for file drop events: window.on_window_event(|event| - if let tauri::WindowEvent::FileDrop(files) = event { - info!(Source = "Tauri"; "files were dropped: {files:?}"); + match event { + tauri::WindowEvent::FileDrop(drop_event) => { + match drop_event { + FileDropEvent::Hovered(files) => { + info!(Source = "Tauri"; "Files hovered over the window: {files:?}"); + }, + + FileDropEvent::Dropped(files) => { + info!(Source = "Tauri"; "Files dropped on the window: {files:?}"); + }, + + FileDropEvent::Cancelled => { + info!(Source = "Tauri"; "File drop was cancelled."); + }, + + _ => {} + } + }, + + tauri::WindowEvent::Focused(state) => { + info!(Source = "Tauri"; "Window focus changed: focused={state}"); + }, + + _ => {} } ); From 2ecaaa70c414f0f3b949c21bcce7d14a154d2256 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Fri, 24 Oct 2025 13:17:39 +0200 Subject: [PATCH 18/42] Fixed spelling --- .../de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 7e93a9dc..a80befc1 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 @@ -1573,7 +1573,7 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T527187983"] = " 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." +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-Ballast, 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." -- Limitations of Existing Solutions UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1086130692"] = "Einschränkungen bestehender Lösungen" @@ -4678,7 +4678,7 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T617579208"] = "Kostenlos" UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T649448159"] = "Unabhängigkeit" -- No bloatware -UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T858047957"] = "Keinen unnötigen Software-Balast" +UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T858047957"] = "Keinen unnötigen Software-Ballast" -- Here's what makes MindWork AI Studio stand out: UI_TEXT_CONTENT["AISTUDIO::PAGES::HOME::T873851215"] = "Das zeichnet MindWork AI Studio aus:" From dca43b6c1e912699eab4d16b2db6be33ab324a0e Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 27 Oct 2025 14:05:05 +0100 Subject: [PATCH 19/42] Formatting --- runtime/src/file_data.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/src/file_data.rs b/runtime/src/file_data.rs index f05b18b5..969f19e1 100644 --- a/runtime/src/file_data.rs +++ b/runtime/src/file_data.rs @@ -27,6 +27,7 @@ pub struct Chunk { pub stream_id: String, pub metadata: Metadata, } + impl Chunk { pub fn new(content: String, metadata: Metadata) -> Self { Chunk { content, stream_id: String::new(), metadata } From 15d7359c59be5552d5af7365589903c613d62888 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 27 Oct 2025 14:37:15 +0100 Subject: [PATCH 20/42] Implemented the Tauri events stream for the Rust server and the .NET client --- .../Settings/TolerantEnumConverter.cs | 76 +++++- .../Tools/Rust/TauriEvent.cs | 7 +- .../Tools/Rust/TauriEventType.cs | 7 + .../Tools/Services/RustService.Events.cs | 26 +- .../Tools/Services/RustService.cs | 11 + runtime/src/app_window.rs | 254 ++++++++++++++---- runtime/src/runtime_api.rs | 1 + 7 files changed, 323 insertions(+), 59 deletions(-) diff --git a/app/MindWork AI Studio/Settings/TolerantEnumConverter.cs b/app/MindWork AI Studio/Settings/TolerantEnumConverter.cs index c3f8fcd0..51bccea4 100644 --- a/app/MindWork AI Studio/Settings/TolerantEnumConverter.cs +++ b/app/MindWork AI Studio/Settings/TolerantEnumConverter.cs @@ -1,3 +1,4 @@ +using System.Text; using System.Text.Json; using System.Text.Json.Serialization; @@ -9,6 +10,9 @@ namespace AIStudio.Settings; /// /// When the target enum value does not exist, the value will be the default value. /// This converter handles enum values as property names and values. +///

+/// We assume that enum names are in UPPER_SNAKE_CASE, and the JSON strings may be +/// in any case style (e.g., camelCase, PascalCase, snake_case, UPPER_SNAKE_CASE, etc.) ///
public sealed class TolerantEnumConverter : JsonConverter { @@ -16,30 +20,46 @@ public sealed class TolerantEnumConverter : JsonConverter public override bool CanConvert(Type typeToConvert) => typeToConvert.IsEnum; - public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override object? Read(ref Utf8JsonReader reader, Type enumType, JsonSerializerOptions options) { // Is this token a string? if (reader.TokenType == JsonTokenType.String) + { // Try to use that string as the name of the enum value: - if (Enum.TryParse(typeToConvert, reader.GetString(), out var result)) + var text = reader.GetString(); + + // Convert the text to UPPER_SNAKE_CASE: + text = ConvertToUpperSnakeCase(text); + + // Try to parse the enum value: + if (Enum.TryParse(enumType, text, out var result)) return result; + } // In any other case, we will return the default enum value: - LOG.LogWarning($"Cannot read '{reader.GetString()}' as '{typeToConvert.Name}' enum; token type: {reader.TokenType}"); - return Activator.CreateInstance(typeToConvert); + LOG.LogWarning($"Cannot read '{reader.GetString()}' as '{enumType.Name}' enum; token type: {reader.TokenType}"); + return Activator.CreateInstance(enumType); } - public override object ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override object ReadAsPropertyName(ref Utf8JsonReader reader, Type enumType, JsonSerializerOptions options) { // Is this token a property name? if (reader.TokenType == JsonTokenType.PropertyName) + { // Try to use that property name as the name of the enum value: - if (Enum.TryParse(typeToConvert, reader.GetString(), out var result)) + var text = reader.GetString(); + + // Convert the text to UPPER_SNAKE_CASE: + text = ConvertToUpperSnakeCase(text); + + // Try to parse the enum value: + if (Enum.TryParse(enumType, text, out var result)) return result; + } // In any other case, we will return the default enum value: - LOG.LogWarning($"Cannot read '{reader.GetString()}' as '{typeToConvert.Name}' enum; token type: {reader.TokenType}"); - return Activator.CreateInstance(typeToConvert)!; + LOG.LogWarning($"Cannot read '{reader.GetString()}' as '{enumType.Name}' enum; token type: {reader.TokenType}"); + return Activator.CreateInstance(enumType)!; } public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) @@ -51,4 +71,44 @@ public sealed class TolerantEnumConverter : JsonConverter { writer.WritePropertyName(value.ToString()!); } + + /// + /// Converts a string to UPPER_SNAKE_CASE. + /// + /// The text to convert. + /// The converted text as UPPER_SNAKE_CASE. + private static string ConvertToUpperSnakeCase(string? text) + { + // Handle null or empty strings: + if (string.IsNullOrWhiteSpace(text)) + return string.Empty; + + // Create a string builder with the same length as the + // input text. We will add underscores as needed, which + // may increase the length -- we cannot predict how many + // underscores will be added, so we just start with the + // original length: + var sb = new StringBuilder(text.Length); + + // State to track if the last character was lowercase. + // This helps to determine when to add underscores: + var lastCharWasLowerCase = false; + + // Iterate through each character in the input text: + foreach(var c in text) + { + // If the current character is uppercase and the last + // character was lowercase, we need to add an underscore: + if (char.IsUpper(c) && lastCharWasLowerCase) + sb.Append('_'); + + // Append the uppercase version of the current character: + sb.Append(char.ToUpperInvariant(c)); + + // Keep track of whether the current character is lowercase: + lastCharWasLowerCase = char.IsLower(c); + } + + return sb.ToString(); + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs b/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs index 140522be..c060e63a 100644 --- a/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs +++ b/app/MindWork AI Studio/Tools/Rust/TauriEvent.cs @@ -1,3 +1,8 @@ namespace AIStudio.Tools.Rust; -public readonly record struct TauriEvent(TauriEventType Type, List Payload); \ No newline at end of file +/// +/// The data structure for a Tauri event sent from the Rust backend to the C# frontend. +/// +/// The type of the Tauri event. +/// The payload of the Tauri event. +public readonly record struct TauriEvent(TauriEventType EventType, List Payload); \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs b/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs index 2710c16b..2cd1c792 100644 --- a/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs +++ b/app/MindWork AI Studio/Tools/Rust/TauriEventType.cs @@ -1,7 +1,14 @@ namespace AIStudio.Tools.Rust; +/// +/// The type of Tauri events we can receive. +/// public enum TauriEventType { + NONE, + PING, + UNKNOWN, + WINDOW_FOCUSED, WINDOW_NOT_FOCUSED, diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Events.cs b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs index 539c3d06..4bb0fd63 100644 --- a/app/MindWork AI Studio/Tools/Services/RustService.Events.cs +++ b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs @@ -6,24 +6,46 @@ namespace AIStudio.Tools.Services; public partial class RustService { + /// + /// Consume the Tauri event stream and forward relevant events to the message bus. + /// + /// Cancellation token to stop the stream. private async Task StartStreamTauriEvents(CancellationToken stopToken) { + // Outer try-catch to handle cancellation: try { while (!stopToken.IsCancellationRequested) { + // Inner try-catch to handle streaming issues: try { + // Open the event stream: await using var stream = await this.http.GetStreamAsync("/events", stopToken); + + + // Read events line by line: using var reader = new StreamReader(stream); - while(!reader.EndOfStream) + + // Read until the end of the stream or cancellation: + while(!reader.EndOfStream && !stopToken.IsCancellationRequested) { + // Read the next line of JSON from the stream: var line = await reader.ReadLineAsync(stopToken); + + // Skip empty lines: if (string.IsNullOrWhiteSpace(line)) continue; + // Deserialize the Tauri event: var tauriEvent = JsonSerializer.Deserialize(line, this.jsonRustSerializerOptions); - if (tauriEvent != default) + + // Log the received event for debugging: + this.logger!.LogDebug("Received Tauri event: {Event}", tauriEvent); + + // Forward relevant events to the message bus: + if (tauriEvent != default && tauriEvent.EventType is not TauriEventType.NONE + and not TauriEventType.UNKNOWN and not TauriEventType.PING) await MessageBus.INSTANCE.SendMessage(null, Event.TAURI_EVENT_RECEIVED, tauriEvent); } } diff --git a/app/MindWork AI Studio/Tools/Services/RustService.cs b/app/MindWork AI Studio/Tools/Services/RustService.cs index 56032b65..41628992 100644 --- a/app/MindWork AI Studio/Tools/Services/RustService.cs +++ b/app/MindWork AI Studio/Tools/Services/RustService.cs @@ -1,6 +1,10 @@ using System.Security.Cryptography; using System.Text.Json; +using AIStudio.Settings; + +using Version = System.Version; + // ReSharper disable NotAccessedPositionalProperty.Local namespace AIStudio.Tools.Services; @@ -15,6 +19,7 @@ public sealed partial class RustService : BackgroundService private readonly JsonSerializerOptions jsonRustSerializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, + Converters = { new TolerantEnumConverter() }, }; private ILogger? logger; @@ -61,9 +66,15 @@ public sealed partial class RustService : BackgroundService #region Overrides of BackgroundService + /// + /// The main execution loop of the Rust service as a background thread. + /// + /// The cancellation token to stop the service. protected override async Task ExecuteAsync(CancellationToken stopToken) { this.logger?.LogInformation("The Rust service was initialized."); + + // Start consuming Tauri events: await this.StartStreamTauriEvents(stopToken); } diff --git a/runtime/src/app_window.rs b/runtime/src/app_window.rs index ee932355..b08f17ca 100644 --- a/runtime/src/app_window.rs +++ b/runtime/src/app_window.rs @@ -3,12 +3,14 @@ use std::time::Duration; use log::{debug, error, info, trace, warn}; use once_cell::sync::Lazy; use rocket::{get, post}; +use rocket::response::stream::TextStream; use rocket::serde::json::Json; use rocket::serde::Serialize; use serde::Deserialize; use tauri::updater::UpdateResponse; -use tauri::{FileDropEvent, Manager, PathResolver, Window}; +use tauri::{FileDropEvent, UpdaterEvent, RunEvent, Manager, PathResolver, Window, WindowEvent}; use tauri::api::dialog::blocking::FileDialogBuilder; +use tokio::sync::broadcast; use tokio::time; use crate::api_token::APIToken; use crate::dotnet::stop_dotnet_server; @@ -22,41 +24,61 @@ static MAIN_WINDOW: Lazy>> = Lazy::new(|| Mutex::new(None)) /// The update response coming from the Tauri updater. static CHECK_UPDATE_RESPONSE: Lazy>>> = Lazy::new(|| Mutex::new(None)); +/// The event broadcast sender for Tauri events. +static EVENT_BROADCAST: Lazy>>> = Lazy::new(|| Mutex::new(None)); + /// Starts the Tauri app. pub fn start_tauri() { info!("Starting Tauri app..."); + + // Create the event broadcast channel: + let (event_sender, root_event_receiver) = broadcast::channel(100); + + // Save a copy of the event broadcast sender for later use: + *EVENT_BROADCAST.lock().unwrap() = Some(event_sender.clone()); + + // When the last receiver is dropped, we lose the ability to send events. + // Therefore, we spawn a task that keeps the root receiver alive: + tauri::async_runtime::spawn(async move { + let mut root_receiver = root_event_receiver; + loop { + match root_receiver.recv().await { + Ok(event) => { + debug!(Source = "Tauri"; "Tauri event received: location=root receiver , event={event:?}"); + }, + + Err(broadcast::error::RecvError::Lagged(skipped)) => { + warn!(Source = "Tauri"; "Root event receiver lagged, skipped {skipped} messages."); + }, + + Err(broadcast::error::RecvError::Closed) => { + warn!(Source = "Tauri"; "Root event receiver channel closed."); + return; + }, + } + } + }); + let app = tauri::Builder::default() .setup(move |app| { + + // Get the main window: let window = app.get_window("main").expect("Failed to get main window."); - // Register a callback for file drop events: - window.on_window_event(|event| - match event { - tauri::WindowEvent::FileDrop(drop_event) => { - match drop_event { - FileDropEvent::Hovered(files) => { - info!(Source = "Tauri"; "Files hovered over the window: {files:?}"); - }, - - FileDropEvent::Dropped(files) => { - info!(Source = "Tauri"; "Files dropped on the window: {files:?}"); - }, - - FileDropEvent::Cancelled => { - info!(Source = "Tauri"; "File drop was cancelled."); - }, - - _ => {} - } - }, - - tauri::WindowEvent::Focused(state) => { - info!(Source = "Tauri"; "Window focus changed: focused={state}"); - }, - - _ => {} - } - ); + // Register a callback for window events, such as file drops. We have to use + // this handler in addition to the app event handler, because file drop events + // are only available in the window event handler (is a bug, cf. https://github.com/tauri-apps/tauri/issues/14338): + window.on_window_event(move |event| { + debug!(Source = "Tauri"; "Tauri event received: location=window event handler, event={event:?}"); + let event_to_send = Event::from_window_event(event); + let sender = event_sender.clone(); + tauri::async_runtime::spawn(async move { + match sender.send(event_to_send) { + Ok(_) => {}, + Err(error) => error!(Source = "Tauri"; "Failed to channel window event: {error}"), + } + }); + }); // Save the main window for later access: *MAIN_WINDOW.lock().unwrap() = Some(window); @@ -65,6 +87,7 @@ pub fn start_tauri() { let data_path = app.path_resolver().app_local_data_dir().unwrap(); let data_path = data_path.join("data"); + // Get and store the data and config directories: DATA_DIRECTORY.set(data_path.to_str().unwrap().to_string()).map_err(|_| error!("Was not abe to set the data directory.")).unwrap(); CONFIG_DIRECTORY.set(app.path_resolver().app_config_dir().unwrap().to_str().unwrap().to_string()).map_err(|_| error!("Was not able to set the config directory.")).unwrap(); @@ -77,46 +100,43 @@ pub fn start_tauri() { .build(tauri::generate_context!()) .expect("Error while running Tauri application"); + // The app event handler: app.run(|app_handle, event| { - if !matches!(event, tauri::RunEvent::MainEventsCleared) { - debug!(Source = "Tauri"; "Event received: {event:?}"); + if !matches!(event, RunEvent::MainEventsCleared) { + debug!(Source = "Tauri"; "Tauri event received: location=app event handler , event={event:?}"); } match event { - tauri::RunEvent::WindowEvent { event, label, .. } => { + RunEvent::WindowEvent { event, label, .. } => { match event { - tauri::WindowEvent::CloseRequested { .. } => { + WindowEvent::CloseRequested { .. } => { warn!(Source = "Tauri"; "Window '{label}': close was requested."); } - tauri::WindowEvent::Destroyed => { + WindowEvent::Destroyed => { warn!(Source = "Tauri"; "Window '{label}': was destroyed."); } - tauri::WindowEvent::FileDrop(files) => { - info!(Source = "Tauri"; "Window '{label}': files were dropped: {files:?}"); - } - _ => (), } } - tauri::RunEvent::Updater(updater_event) => { + RunEvent::Updater(updater_event) => { match updater_event { - tauri::UpdaterEvent::UpdateAvailable { body, date, version } => { + UpdaterEvent::UpdateAvailable { body, date, version } => { let body_len = body.len(); info!(Source = "Tauri"; "Updater: update available: body size={body_len} time={date:?} version={version}"); } - tauri::UpdaterEvent::Pending => { + UpdaterEvent::Pending => { info!(Source = "Tauri"; "Updater: update is pending!"); } - tauri::UpdaterEvent::DownloadProgress { chunk_length, content_length: _ } => { + UpdaterEvent::DownloadProgress { chunk_length, content_length: _ } => { trace!(Source = "Tauri"; "Updater: downloading chunk of {chunk_length} bytes"); } - tauri::UpdaterEvent::Downloaded => { + UpdaterEvent::Downloaded => { info!(Source = "Tauri"; "Updater: update has been downloaded!"); warn!(Source = "Tauri"; "Try to stop the .NET server now..."); @@ -127,7 +147,7 @@ pub fn start_tauri() { } } - tauri::UpdaterEvent::Updated => { + UpdaterEvent::Updated => { info!(Source = "Tauri"; "Updater: app has been updated"); warn!(Source = "Tauri"; "Try to restart the app now..."); @@ -138,21 +158,21 @@ pub fn start_tauri() { } } - tauri::UpdaterEvent::AlreadyUpToDate => { + UpdaterEvent::AlreadyUpToDate => { info!(Source = "Tauri"; "Updater: app is already up to date"); } - tauri::UpdaterEvent::Error(error) => { + UpdaterEvent::Error(error) => { warn!(Source = "Tauri"; "Updater: failed to update: {error}"); } } } - tauri::RunEvent::ExitRequested { .. } => { + RunEvent::ExitRequested { .. } => { warn!(Source = "Tauri"; "Run event: exit was requested."); } - tauri::RunEvent::Ready => { + RunEvent::Ready => { info!(Source = "Tauri"; "Run event: Tauri app is ready."); } @@ -167,6 +187,144 @@ pub fn start_tauri() { } } +/// Our event API endpoint for Tauri events. We try to send an endless stream of events to the client. +/// If no events are available for a certain time, we send a ping event to keep the connection alive. +/// When the client disconnects, the stream is closed. But we try to not lose events in between. +/// The client is expected to reconnect automatically when the connection is closed and continue +/// listening for events. +#[get("/events")] +pub async fn get_event_stream(_token: APIToken) -> TextStream![String] { + // Get the lock to the event broadcast sender: + let event_broadcast_lock = EVENT_BROADCAST.lock().unwrap(); + + // Get and subscribe to the event receiver: + let mut event_receiver = event_broadcast_lock.as_ref() + .expect("Event sender not initialized.") + .subscribe(); + + // Drop the lock to allow other access to the sender: + drop(event_broadcast_lock); + + // Create the event stream: + TextStream! { + loop { + // Wait at most 3 seconds for an event: + match time::timeout(Duration::from_secs(3), event_receiver.recv()).await { + + // Case: we received an event + Ok(Ok(event)) => { + // Serialize the event to JSON. Important is that the entire event + // is serialized as a single line so that the client can parse it + // correctly: + let event_json = serde_json::to_string(&event).unwrap(); + yield event_json; + + // The client expects a newline after each event because we are using + // a method to read the stream line-by-line: + yield "\n".to_string(); + }, + + // Case: we lagged behind and missed some events + Ok(Err(broadcast::error::RecvError::Lagged(skipped))) => { + warn!(Source = "Tauri"; "Event receiver lagged, skipped {skipped} messages."); + }, + + // Case: the event channel was closed + Ok(Err(broadcast::error::RecvError::Closed)) => { + warn!(Source = "Tauri"; "Event receiver channel closed."); + return; + }, + + // Case: timeout. We will send a ping event to keep the connection alive. + Err(_) => { + let ping_event = Event::new(TauriEventType::Ping, Vec::new()); + + // Again, we have to serialize the event as a single line: + let event_json = serde_json::to_string(&ping_event).unwrap(); + yield event_json; + + // The client expects a newline after each event because we are using + // a method to read the stream line-by-line: + yield "\n".to_string(); + }, + } + } + } +} + +/// Data structure representing a Tauri event for our event API. +#[derive(Debug, Clone, Serialize)] +pub struct Event { + pub event_type: TauriEventType, + pub payload: Vec, +} + +/// Implementation of the Event struct. +impl Event { + + /// Creates a new Event instance. + pub fn new(event_type: TauriEventType, payload: Vec) -> Self { + Event { + payload, + event_type, + } + } + + /// Creates an Event instance from a Tauri WindowEvent. + pub fn from_window_event(window_event: &WindowEvent) -> Self { + match window_event { + WindowEvent::FileDrop(drop_event) => { + match drop_event { + FileDropEvent::Hovered(files) => Event::new(TauriEventType::FileDropHovered, + files.iter().map(|f| f.to_string_lossy().to_string()).collect(), + ), + + FileDropEvent::Dropped(files) => Event::new(TauriEventType::FileDropDropped, + files.iter().map(|f| f.to_string_lossy().to_string()).collect(), + ), + + FileDropEvent::Cancelled => Event::new(TauriEventType::FileDropCanceled, + Vec::new(), + ), + + _ => Event::new(TauriEventType::Unknown, + Vec::new(), + ), + } + }, + + WindowEvent::Focused(state) => if *state { + Event::new(TauriEventType::WindowFocused, + Vec::new(), + ) + } else { + Event::new(TauriEventType::WindowNotFocused, + Vec::new(), + ) + }, + + _ => Event::new(TauriEventType::Unknown, + Vec::new(), + ), + } + } +} + +/// The types of Tauri events we can send through our event API. +#[derive(Debug, Serialize, Clone)] +pub enum TauriEventType { + None, + Ping, + Unknown, + + WindowFocused, + WindowNotFocused, + + FileDropHovered, + FileDropDropped, + FileDropCanceled, +} + /// Changes the location of the main window to the given URL. pub async fn change_location_to(url: &str) { // Try to get the main window. If it is not available yet, wait for it: diff --git a/runtime/src/runtime_api.rs b/runtime/src/runtime_api.rs index b700af5b..aec48001 100644 --- a/runtime/src/runtime_api.rs +++ b/runtime/src/runtime_api.rs @@ -68,6 +68,7 @@ pub fn start_runtime_api() { crate::dotnet::dotnet_port, crate::dotnet::dotnet_ready, crate::clipboard::set_clipboard, + crate::app_window::get_event_stream, crate::app_window::check_for_update, crate::app_window::install_update, crate::app_window::select_directory, From 0125215111867c4c0ca869db225cb90e70b44719 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 27 Oct 2025 14:54:32 +0100 Subject: [PATCH 21/42] Improved logging --- .../Tools/Services/RustService.Events.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Events.cs b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs index 4bb0fd63..e4d72a0f 100644 --- a/app/MindWork AI Studio/Tools/Services/RustService.Events.cs +++ b/app/MindWork AI Studio/Tools/Services/RustService.Events.cs @@ -40,13 +40,15 @@ public partial class RustService // Deserialize the Tauri event: var tauriEvent = JsonSerializer.Deserialize(line, this.jsonRustSerializerOptions); - // Log the received event for debugging: - this.logger!.LogDebug("Received Tauri event: {Event}", tauriEvent); - // Forward relevant events to the message bus: - if (tauriEvent != default && tauriEvent.EventType is not TauriEventType.NONE - and not TauriEventType.UNKNOWN and not TauriEventType.PING) + if (tauriEvent != default && tauriEvent.EventType + is not TauriEventType.NONE + and not TauriEventType.UNKNOWN + and not TauriEventType.PING) + { + this.logger!.LogDebug("Received Tauri event {EventType} with {NumPayloadItems} payload items.", tauriEvent.EventType, tauriEvent.Payload.Count); await MessageBus.INSTANCE.SendMessage(null, Event.TAURI_EVENT_RECEIVED, tauriEvent); + } } } From 211f8acbddd87bf0ae30ce5c8f50e8d089f57835 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 27 Oct 2025 15:17:20 +0100 Subject: [PATCH 22/42] Added the "attach documents" component --- .../DocumentAnalysisAssistant.razor | 2 +- .../DocumentAnalysisAssistant.razor.cs | 13 +-- .../Assistants/I18N/allTexts.lua | 9 ++ .../Components/AttachDocuments.razor | 15 ++++ .../Components/AttachDocuments.razor.cs | 88 +++++++++++++++++++ 5 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 app/MindWork AI Studio/Components/AttachDocuments.razor create mode 100644 app/MindWork AI Studio/Components/AttachDocuments.razor.cs diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 18c0e258..febcbc63 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -68,6 +68,6 @@ else - TODO + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 3a5a10b9..f6b1b0d6 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -33,7 +33,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore true; - protected override string SubmitText => T("Analyze document"); + protected override string SubmitText => T("Analyze documents"); protected override Func SubmitAction => this.Analyze; @@ -99,10 +99,9 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore(Event.SEND_TO_DOCUMENT_ANALYSIS_ASSISTANT).FirstOrDefault(); - // if (deferredContent is not null) - #warning Add handling of deferred content -> load into input area - //this. + var receivedDeferredContent = MessageBus.INSTANCE.CheckDeferredMessages(Event.SEND_TO_DOCUMENT_ANALYSIS_ASSISTANT).FirstOrDefault(); + if (receivedDeferredContent is not null) + this.deferredContent = receivedDeferredContent; await base.OnInitializedAsync(); } @@ -137,6 +136,8 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore loadedDocumentPaths = []; private bool IsNoPolicySelectedOrProtected => this.selectedPolicy is null || this.selectedPolicy.IsProtected; diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index a1e5bacf..af004e3c 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -1459,6 +1459,15 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4188329028"] = "No, kee -- Open Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Settings" +-- Images are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T298062956"] = "Images are not supported yet" + +-- Executables are not allowed +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T4167762413"] = "Executables are not allowed" + +-- Select a file to attach +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T595772870"] = "Select a file to attach" + -- Changelog UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHANGELOG::T3017574265"] = "Changelog" diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor b/app/MindWork AI Studio/Components/AttachDocuments.razor new file mode 100644 index 00000000..f86d4aa8 --- /dev/null +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor @@ -0,0 +1,15 @@ +@inherits MSGComponentBase + + + + + Drag and drop files here or click to attach documents. + + @foreach (var fileInfo in this.DocumentPaths.Select(file => new FileInfo(file))) + { + + } + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs new file mode 100644 index 00000000..cf1b88cc --- /dev/null +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs @@ -0,0 +1,88 @@ +using AIStudio.Tools.Rust; +using AIStudio.Tools.Services; + +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components; + +public partial class AttachDocuments : MSGComponentBase +{ + [Parameter] + public List DocumentPaths { get; set; } = []; + + [Parameter] + public EventCallback> DocumentPathsChanged { get; set; } + + [Parameter] + public Func, Task> OnChange { get; set; } = _ => Task.CompletedTask; + + [Inject] + private RustService RustService { get; init; } = null!; + + #region Overrides of MSGComponentBase + + protected override async Task OnInitializedAsync() + { + this.ApplyFilters([], [ Event.TAURI_EVENT_RECEIVED ]); + await base.OnInitializedAsync(); + } + + protected override async Task ProcessIncomingMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default + { + switch (triggeredEvent) + { + case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_HOVERED }: + this.SetDragClass(); + break; + + case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_DROPPED, Payload: var paths }: + this.ClearDragClass(); + foreach (var path in paths) + this.DocumentPaths.Add(path); + await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); + await this.OnChange(this.DocumentPaths); + break; + + case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_CANCELED }: + this.ClearDragClass(); + break; + } + } + + #endregion + + private const string DEFAULT_DRAG_CLASS = "relative rounded-lg border-2 border-dashed pa-4 mt-4 mud-width-full mud-height-full"; + + private string dragClass = DEFAULT_DRAG_CLASS; + + private async Task AddFilesManually() + { + var selectedFile = await this.RustService.SelectFile(T("Select a file to attach")); + if (selectedFile.UserCancelled) + return; + + if (!File.Exists(selectedFile.SelectedFilePath)) + return; + + var ext = Path.GetExtension(selectedFile.SelectedFilePath).TrimStart('.'); + if (Array.Exists(FileTypeFilter.Executables.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase))) + { + await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.AppBlocking, T("Executables are not allowed"))); + return; + } + + if (Array.Exists(FileTypeFilter.AllImages.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase))) + { + await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.ImageNotSupported, T("Images are not supported yet"))); + return; + } + + this.DocumentPaths.Add(selectedFile.SelectedFilePath); + await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); + await this.OnChange(this.DocumentPaths); + } + + private void SetDragClass() => this.dragClass = $"{DEFAULT_DRAG_CLASS} mud-border-primary"; + + private void ClearDragClass() => this.dragClass = DEFAULT_DRAG_CLASS; +} \ No newline at end of file From a7ebc117c558d63a17c761ee3ee12b6d5e609fb0 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 27 Oct 2025 15:30:55 +0100 Subject: [PATCH 23/42] Allow to load documents as analysis & output rules --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index febcbc63..829dcba2 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -56,7 +56,10 @@ else @T("Input and output rules") + + + @T("Preparation for enterprise distribution") From a88382dc95fdb047a81d2b0993d218a20907cbb1 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 08:13:56 +0100 Subject: [PATCH 24/42] Refactor to use HashSet for document path management --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor.cs | 2 +- app/MindWork AI Studio/Components/AttachDocuments.razor.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index f6b1b0d6..90ac2c7c 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -137,7 +137,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore loadedDocumentPaths = []; + private HashSet loadedDocumentPaths = []; private bool IsNoPolicySelectedOrProtected => this.selectedPolicy is null || this.selectedPolicy.IsProtected; diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs index cf1b88cc..9b446ca9 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs @@ -8,13 +8,13 @@ namespace AIStudio.Components; public partial class AttachDocuments : MSGComponentBase { [Parameter] - public List DocumentPaths { get; set; } = []; + public HashSet DocumentPaths { get; set; } = []; [Parameter] - public EventCallback> DocumentPathsChanged { get; set; } + public EventCallback> DocumentPathsChanged { get; set; } [Parameter] - public Func, Task> OnChange { get; set; } = _ => Task.CompletedTask; + public Func, Task> OnChange { get; set; } = _ => Task.CompletedTask; [Inject] private RustService RustService { get; init; } = null!; From 1f82155b130f5b2d42fe9d68cb79349c4b667a41 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 09:41:07 +0100 Subject: [PATCH 25/42] Enhance drag-and-drop with hover detection and logging --- .../DocumentAnalysisAssistant.razor | 2 +- .../Components/AttachDocuments.razor | 26 +++++------ .../Components/AttachDocuments.razor.cs | 46 ++++++++++++++++--- app/MindWork AI Studio/Tools/EventHandlers.cs | 14 ++++++ 4 files changed, 68 insertions(+), 20 deletions(-) create mode 100644 app/MindWork AI Studio/Tools/EventHandlers.cs diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 829dcba2..67bbfaee 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -71,6 +71,6 @@ else - + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor b/app/MindWork AI Studio/Components/AttachDocuments.razor index f86d4aa8..f49f38a3 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor @@ -1,15 +1,15 @@ @inherits MSGComponentBase - - - - Drag and drop files here or click to attach documents. - - @foreach (var fileInfo in this.DocumentPaths.Select(file => new FileInfo(file))) - { - - } - - \ No newline at end of file +
+ + + + @T("Drag and drop files here or click to attach documents.") + + @foreach (var fileInfo in this.DocumentPaths.Select(file => new FileInfo(file))) + { + + } + + +
\ No newline at end of file diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs index 9b446ca9..f8fb79a0 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs @@ -7,6 +7,9 @@ namespace AIStudio.Components; public partial class AttachDocuments : MSGComponentBase { + [Parameter] + public string Name { get; set; } = string.Empty; + [Parameter] public HashSet DocumentPaths { get; set; } = []; @@ -16,6 +19,9 @@ public partial class AttachDocuments : MSGComponentBase [Parameter] public Func, Task> OnChange { get; set; } = _ => Task.CompletedTask; + [Inject] + private ILogger Logger { get; set; } = null!; + [Inject] private RustService RustService { get; init; } = null!; @@ -32,19 +38,29 @@ public partial class AttachDocuments : MSGComponentBase switch (triggeredEvent) { case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_HOVERED }: + if(!this.isComponentHovered) + { + this.Logger.LogDebug("Attach documents component '{Name}' is not hovered, ignoring file drop hovered event.", this.Name); + return; + } + this.SetDragClass(); + this.StateHasChanged(); break; case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_DROPPED, Payload: var paths }: - this.ClearDragClass(); + if(!this.isComponentHovered) + { + this.Logger.LogDebug("Attach documents component '{Name}' is not hovered, ignoring file drop dropped event.", this.Name); + return; + } + + #warning Filter unsupported files foreach (var path in paths) this.DocumentPaths.Add(path); await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); await this.OnChange(this.DocumentPaths); - break; - - case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_CANCELED }: - this.ClearDragClass(); + this.StateHasChanged(); break; } } @@ -54,6 +70,8 @@ public partial class AttachDocuments : MSGComponentBase private const string DEFAULT_DRAG_CLASS = "relative rounded-lg border-2 border-dashed pa-4 mt-4 mud-width-full mud-height-full"; private string dragClass = DEFAULT_DRAG_CLASS; + + private bool isComponentHovered; private async Task AddFilesManually() { @@ -82,7 +100,23 @@ public partial class AttachDocuments : MSGComponentBase await this.OnChange(this.DocumentPaths); } - private void SetDragClass() => this.dragClass = $"{DEFAULT_DRAG_CLASS} mud-border-primary"; + private void SetDragClass() => this.dragClass = $"{DEFAULT_DRAG_CLASS} mud-border-primary border-4"; private void ClearDragClass() => this.dragClass = DEFAULT_DRAG_CLASS; + + private void OnMouseEnter(EventArgs _) + { + this.Logger.LogDebug("Attach documents component '{Name}' is hovered.", this.Name); + this.isComponentHovered = true; + this.SetDragClass(); + this.StateHasChanged(); + } + + private void OnMouseLeave(EventArgs _) + { + this.Logger.LogDebug("Attach documents component '{Name}' is no longer hovered.", this.Name); + this.isComponentHovered = false; + this.ClearDragClass(); + this.StateHasChanged(); + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/EventHandlers.cs b/app/MindWork AI Studio/Tools/EventHandlers.cs new file mode 100644 index 00000000..bc68af6c --- /dev/null +++ b/app/MindWork AI Studio/Tools/EventHandlers.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Tools; + +/// +/// Add handling for more DOM events to Blazor components. +/// +/// +/// See https://learn.microsoft.com/en-us/aspnet/core/blazor/components/event-handling. It is important +/// that this class is named EventHandlers. +/// +[EventHandler("onmouseenter", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)] +[EventHandler("onmouseleave", typeof(EventArgs), enableStopPropagation: true, enablePreventDefault: true)] +public static class EventHandlers; \ No newline at end of file From 45ab5338b4a8da7cfdf178c8f2245728486639f5 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 09:41:45 +0100 Subject: [PATCH 26/42] Add "Clear file list" button to AttachDocuments component --- app/MindWork AI Studio/Components/AttachDocuments.razor | 3 +++ app/MindWork AI Studio/Components/AttachDocuments.razor.cs | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor b/app/MindWork AI Studio/Components/AttachDocuments.razor index f49f38a3..383d343f 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor @@ -12,4 +12,7 @@ } + + @T("Clear file list") + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs index f8fb79a0..576c9b1b 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs @@ -99,6 +99,13 @@ public partial class AttachDocuments : MSGComponentBase await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); await this.OnChange(this.DocumentPaths); } + + private async Task ClearAllFiles() + { + this.DocumentPaths.Clear(); + await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); + await this.OnChange(this.DocumentPaths); + } private void SetDragClass() => this.dragClass = $"{DEFAULT_DRAG_CLASS} mud-border-primary border-4"; From 80bf87d71df7701e6b2e12b5d468d08e93662da5 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 10:08:54 +0100 Subject: [PATCH 27/42] Add video file filtering and validation methods --- .../Components/AttachDocuments.razor.cs | 45 +++++++++++++------ .../Components/ReadFileContent.razor.cs | 6 +++ .../Tools/Rust/FileTypeFilter.cs | 4 +- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs index 576c9b1b..8fc7370c 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs @@ -55,9 +55,14 @@ public partial class AttachDocuments : MSGComponentBase return; } - #warning Filter unsupported files foreach (var path in paths) + { + if(!await this.IsFileExtensionValid(path)) + continue; + this.DocumentPaths.Add(path); + } + await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); await this.OnChange(this.DocumentPaths); this.StateHasChanged(); @@ -82,24 +87,38 @@ public partial class AttachDocuments : MSGComponentBase if (!File.Exists(selectedFile.SelectedFilePath)) return; - var ext = Path.GetExtension(selectedFile.SelectedFilePath).TrimStart('.'); - if (Array.Exists(FileTypeFilter.Executables.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase))) - { - await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.AppBlocking, T("Executables are not allowed"))); + if (!await this.IsFileExtensionValid(selectedFile.SelectedFilePath)) return; - } - - if (Array.Exists(FileTypeFilter.AllImages.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase))) - { - await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.ImageNotSupported, T("Images are not supported yet"))); - return; - } this.DocumentPaths.Add(selectedFile.SelectedFilePath); await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); await this.OnChange(this.DocumentPaths); } - + + private async Task IsFileExtensionValid(string selectedFile) + { + var ext = Path.GetExtension(selectedFile).TrimStart('.'); + if (Array.Exists(FileTypeFilter.Executables.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase))) + { + await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.AppBlocking, this.T("Executables are not allowed"))); + return false; + } + + if (Array.Exists(FileTypeFilter.AllImages.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase))) + { + await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.ImageNotSupported, this.T("Images are not supported yet"))); + return false; + } + + if (Array.Exists(FileTypeFilter.AllVideos.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase))) + { + await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.FeaturedVideo, this.T("Videos are not supported yet"))); + return false; + } + + return true; + } + private async Task ClearAllFiles() { this.DocumentPaths.Clear(); diff --git a/app/MindWork AI Studio/Components/ReadFileContent.razor.cs b/app/MindWork AI Studio/Components/ReadFileContent.razor.cs index 86bafebe..17814e16 100644 --- a/app/MindWork AI Studio/Components/ReadFileContent.razor.cs +++ b/app/MindWork AI Studio/Components/ReadFileContent.razor.cs @@ -38,6 +38,12 @@ public partial class ReadFileContent : MSGComponentBase return; } + if (Array.Exists(FileTypeFilter.AllVideos.FilterExtensions, x => x.Equals(ext, StringComparison.OrdinalIgnoreCase))) + { + await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.FeaturedVideo, this.T("Videos are not supported yet"))); + return; + } + var fileContent = await this.RustService.ReadArbitraryFileData(selectedFile.SelectedFilePath, int.MaxValue); await this.FileContentChanged.InvokeAsync(fileContent); } diff --git a/app/MindWork AI Studio/Tools/Rust/FileTypeFilter.cs b/app/MindWork AI Studio/Tools/Rust/FileTypeFilter.cs index bf0ac5b2..d755184e 100644 --- a/app/MindWork AI Studio/Tools/Rust/FileTypeFilter.cs +++ b/app/MindWork AI Studio/Tools/Rust/FileTypeFilter.cs @@ -19,7 +19,9 @@ public readonly record struct FileTypeFilter(string FilterName, string[] FilterE public static FileTypeFilter AllOffice => new(TB("All Office Files"), ["docx", "xlsx", "pptx", "doc", "xls", "ppt", "pdf"]); - public static FileTypeFilter AllImages => new(TB("All Image Files"), ["jpg", "jpeg", "png", "gif", "bmp", "tiff"]); + public static FileTypeFilter AllImages => new(TB("All Image Files"), ["jpg", "jpeg", "png", "gif", "bmp", "tiff", "svg", "webp", "heic"]); + + public static FileTypeFilter AllVideos => new(TB("All Video Files"), ["mp4", "avi", "mkv", "mov", "wmv", "flv", "webm"]); public static FileTypeFilter Executables => new(TB("Executable Files"), ["exe", "app", "bin", "appimage"]); } \ No newline at end of file From b6399967e5c61010721c0d39fd32052275b1a0db Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 10:19:32 +0100 Subject: [PATCH 28/42] Added todo --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 90ac2c7c..21754b72 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -136,6 +136,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore loadedDocumentPaths = []; From 679591dba13ace249a3358518d4dc7b9ed49550b Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 10:19:54 +0100 Subject: [PATCH 29/42] Add Text parameter to customize button label --- app/MindWork AI Studio/Components/ReadFileContent.razor | 9 ++++++++- .../Components/ReadFileContent.razor.cs | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/Components/ReadFileContent.razor b/app/MindWork AI Studio/Components/ReadFileContent.razor index f9e33fc8..05a63722 100644 --- a/app/MindWork AI Studio/Components/ReadFileContent.razor +++ b/app/MindWork AI Studio/Components/ReadFileContent.razor @@ -1,4 +1,11 @@ @inherits MSGComponentBase - @T("Use file content as input") + @if (string.IsNullOrWhiteSpace(this.Text)) + { + @T("Use file content as input") + } + else + { + @this.Text + } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ReadFileContent.razor.cs b/app/MindWork AI Studio/Components/ReadFileContent.razor.cs index 17814e16..b5f00fd2 100644 --- a/app/MindWork AI Studio/Components/ReadFileContent.razor.cs +++ b/app/MindWork AI Studio/Components/ReadFileContent.razor.cs @@ -7,6 +7,9 @@ namespace AIStudio.Components; public partial class ReadFileContent : MSGComponentBase { + [Parameter] + public string Text { get; set; } = string.Empty; + [Parameter] public string FileContent { get; set; } = string.Empty; From 121c3ec5a0f96efb0960428508b298f33be8088f Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 10:20:02 +0100 Subject: [PATCH 30/42] Add Text parameter to ReadFileContent buttons --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 67bbfaee..721f350f 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -56,10 +56,10 @@ else @T("Input and output rules")
- + - + @T("Preparation for enterprise distribution") From c0951b16ccc84389f97ca05c9e11f7fa93d8a9c0 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 10:24:04 +0100 Subject: [PATCH 31/42] Remove unused constructor from DataDocumentAnalysis --- app/MindWork AI Studio/Settings/DataModel/Data.cs | 2 +- .../Settings/DataModel/DataDocumentAnalysis.cs | 11 +---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/app/MindWork AI Studio/Settings/DataModel/Data.cs b/app/MindWork AI Studio/Settings/DataModel/Data.cs index 8c8a1ef8..c07ab3d6 100644 --- a/app/MindWork AI Studio/Settings/DataModel/Data.cs +++ b/app/MindWork AI Studio/Settings/DataModel/Data.cs @@ -85,7 +85,7 @@ public sealed class Data public DataERI ERI { get; init; } = new(); - public DataDocumentAnalysis DocumentAnalysis { get; init; } = new(x => x.DocumentAnalysis); + public DataDocumentAnalysis DocumentAnalysis { get; init; } = new(); public DataTextSummarizer TextSummarizer { get; init; } = new(); diff --git a/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysis.cs b/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysis.cs index c0f58d6f..c6961270 100644 --- a/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysis.cs +++ b/app/MindWork AI Studio/Settings/DataModel/DataDocumentAnalysis.cs @@ -1,16 +1,7 @@ -using System.Linq.Expressions; - namespace AIStudio.Settings.DataModel; -public sealed class DataDocumentAnalysis(Expression>? configSelection = null) +public sealed class DataDocumentAnalysis { - /// - /// The default constructor for the JSON deserializer. - /// - public DataDocumentAnalysis() : this(null) - { - } - /// /// Configured document analysis policies. /// From 1891bca5e00f13d9d35629b5ffddecb78e0eb577 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 10:24:14 +0100 Subject: [PATCH 32/42] Updated --- .../Assistants/I18N/allTexts.lua | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index af004e3c..fc787487 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -406,12 +406,12 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Common settings UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings" --- Analyze document -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2053296240"] = "Analyze document" - -- Document analysis policies UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2064879144"] = "Document analysis policies" +-- Load output rules from document +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2168201568"] = "Load output rules from document" + -- Definition UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T222998208"] = "Definition" @@ -427,6 +427,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Policy name UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name" +-- Analyze documents +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2894951609"] = "Analyze documents" + -- Analysis rules UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3108719748"] = "Analysis rules" @@ -451,6 +454,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- A policy with this name already exists. Please choose a different name. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3584374593"] = "A policy with this name already exists. Please choose a different name." +-- Load analysis rules from document +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3813558135"] = "Load analysis rules from document" + -- Output rules UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3918193587"] = "Output rules" @@ -1459,9 +1465,18 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4188329028"] = "No, kee -- Open Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Settings" +-- Drag and drop files here or click to attach documents. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T1647829151"] = "Drag and drop files here or click to attach documents." + +-- Videos are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2928927510"] = "Videos are not supported yet" + -- Images are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T298062956"] = "Images are not supported yet" +-- Clear file list +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T3759696136"] = "Clear file list" + -- Executables are not allowed UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T4167762413"] = "Executables are not allowed" @@ -1765,6 +1780,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Provider" +-- Videos are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos are not supported yet" + -- Images are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Images are not supported yet" @@ -5743,6 +5761,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::RAG::RAGPROCESSES::AISRCSELWITHRETCTXVAL::T377 -- Executable Files UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2217313358"] = "Executable Files" +-- All Video Files +UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2850789856"] = "All Video Files" + -- PDF Files UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T3108466742"] = "PDF Files" From ee6734b9e7c9429d76981dd519bb09e8e4c60fff Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 10:24:28 +0100 Subject: [PATCH 33/42] Updated todos --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 21754b72..a3f49106 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -136,7 +136,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore loadedDocumentPaths = []; @@ -265,6 +265,6 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore Date: Tue, 28 Oct 2025 16:29:21 +0100 Subject: [PATCH 34/42] Show name and description --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 721f350f..12774219 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -71,6 +71,16 @@ else + + @T("Description") + + + @this.selectedPolicy?.PolicyDescription + + + + @T("Documents for the analysis") + \ No newline at end of file From d1cdb47d81a5ceb82cb35e591917b617a83d1848 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Tue, 28 Oct 2025 16:30:02 +0100 Subject: [PATCH 35/42] Added I18N and the German translation --- .../DocumentAnalysisAssistant.razor | 2 +- .../DocumentAnalysisAssistant.razor.cs | 8 +- .../Assistants/I18N/allTexts.lua | 18 +- .../SettingsDialogDocumentAnalysis.razor | 2 +- .../plugin.lua | 174 ++++++++++++++++++ .../plugin.lua | 174 ++++++++++++++++++ 6 files changed, 366 insertions(+), 12 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 12774219..5255ec8f 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -66,7 +66,7 @@ else - Export policy as configuration section + @T("Export policy as configuration section") diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index a3f49106..5df8dfac 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -20,13 +20,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore T("Document Analysis Assistant"); - protected override string Description => T( - """ - The document analysis assistant helps you to analyze and extract information from documents - based on predefined policies. You can create, edit, and manage document analysis policies - that define how documents should be processed and what information should be extracted. - Some policies might be protected by your organization and cannot be modified or deleted. - """); + protected override string Description => T("The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted."); protected override string SystemPrompt { diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index fc787487..cdc1c77a 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -394,6 +394,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Input and output rules UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Input and output rules" +-- Description +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1725856265"] = "Description" + -- Yes, protect this policy UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy" @@ -406,6 +409,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Common settings UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings" +-- The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted." + -- Document analysis policies UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2064879144"] = "Document analysis policies" @@ -418,6 +424,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- The name of your policy must be between 6 and 60 characters long. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "The name of your policy must be between 6 and 60 characters long." +-- Export policy as configuration section +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2556564432"] = "Export policy as configuration section" + -- Are you sure you want to delete the document analysis policy '{0}'? UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2582525917"] = "Are you sure you want to delete the document analysis policy '{0}'?" @@ -430,6 +439,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Analyze documents UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2894951609"] = "Analyze documents" +-- Documents for the analysis +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3030664641"] = "Documents for the analysis" + -- Analysis rules UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3108719748"] = "Analysis rules" @@ -3724,9 +3736,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473 -- Local Directory UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory" --- When enabled, you can preselect some ERI server options. -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1280666275"] = "When enabled, you can preselect some ERI server options." - -- Assistant: Document Analysis UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistant: Document Analysis" @@ -3739,6 +3748,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2 -- Preselect document analysis options? UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Preselect document analysis options?" +-- When enabled, you can preselect some document analysis options. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2301091111"] = "When enabled, you can preselect some document analysis options." + -- No document analysis options are preselected UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "No document analysis options are preselected" diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor index 7cdd4455..2b9744b0 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDocumentAnalysis.razor @@ -11,7 +11,7 @@ - + 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 a80befc1..9a9cdeff 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 @@ -384,6 +384,117 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T -- None UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T810547195"] = "Keine" +-- Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1182372158"] = "Bitte geben Sie eine kurze Beschreibung Ihres Regelwerks an. Beschreiben oder erklären Sie, was das Regelwerk bewirkt. Diese Beschreibung wird den Benutzern in AI Studio angezeigt." + +-- No, the policy can be edited +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1286595725"] = "Nein, das Regelwerk kann bearbeitet werden." + +-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Bitte geben Sie eine Beschreibung Ihrer Analysekriterien an. Diese Regeln werden verwendet, um die KI anzuweisen, wie die Dokumente analysiert werden sollen." + +-- Analysis and output rules +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Analyse- und Ausgaberegeln" + +-- Description +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1725856265"] = "Beschreibung" + +-- Yes, protect this policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Ja, dieses Regelwerk schützen" + +-- Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1786783201"] = "Bitte geben Sie Ihrem Regelwerk einen Namen, der den beabsichtigten Zweck beschreibt. Der Name wird den Nutzern in AI Studio angezeigt." + +-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Bitte geben Sie eine Beschreibung für Ihr Regelwerk an. Diese Beschreibung wird verwendet, um Benutzer über den Zweck Ihres Regelwerks zur Dokumentenanalyse zu informieren." + +-- Common settings +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Allgemeine Einstellungen" + +-- The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "Der Assistent für Dokumentenanalysen hilft Ihnen dabei, Informationen aus Dokumenten basierend auf vordefinierten Regelwerken zu analysieren und zu extrahieren. Sie können Regelwerke für die Dokumentenanalyse erstellen, bearbeiten und verwalten, die festlegen, wie Dokumente verarbeitet werden und welche Informationen extrahiert werden sollen. Einige Regelwerke könnten durch Ihre Organisation geschützt sein und können nicht geändert oder gelöscht werden." + +-- Document analysis policies +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2064879144"] = "Regelwerke zur Dokumentenanalyse" + +-- Load output rules from document +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2168201568"] = "Regeln für die Ausgabe aus einem Dokument laden" + +-- Definition +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T222998208"] = "Definition" + +-- The name of your policy must be between 6 and 60 characters long. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "Der Name Ihres Regelwerks muss zwischen 6 und 60 Zeichen lang sein." + +-- Export policy as configuration section +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2556564432"] = "Exportieren Sie das Regelwerk als Konfigurationsabschnitt" + +-- Are you sure you want to delete the document analysis policy '{0}'? +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2582525917"] = "Möchten Sie das Regelwerk '{0}' wirklich löschen?" + +-- Document analysis +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2708005534"] = "Dokumentenanalyse" + +-- Policy name +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Name des Regelwerks" + +-- Analyze documents +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2894951609"] = "Dokumente analysieren" + +-- Documents for the analysis +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3030664641"] = "Dokumente für die Analyse" + +-- Analysis rules +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3108719748"] = "Regeln zur Analyse" + +-- Delete this policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3119086260"] = "Dieses Regelwerk löschen" + +-- Policy {0} +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Regelwerk {0}" + +-- The description of your policy must be between 32 and 512 characters long. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "Die Beschreibung des Regelwerks muss zwischen 32 und 512 Zeichen lang sein." + +-- Add policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3357792182"] = "Regelwerk hinzufügen" + +-- You have not yet added any document analysis policies. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3394850216"] = "Sie haben keine Regelwerke zur Dokumentenanalyse hinzugefügt." + +-- Document Analysis Assistant +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T348883878"] = "Assistent für die Analyse von Dokumenten" + +-- A policy with this name already exists. Please choose a different name. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3584374593"] = "Ein Regelwerk mit diesem Namen existiert bereits. Bitte wählen Sie einen anderen Namen." + +-- Load analysis rules from document +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3813558135"] = "Regeln für die Analyse aus einem Dokument laden" + +-- Output rules +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3918193587"] = "Regeln für die Ausgabe" + +-- Preparation for enterprise distribution +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T39557294"] = "Vorbereitung für den Unternehmenseinsatz" + +-- Please provide a name for your policy. This name will be used to identify the policy in AI Studio. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4040507702"] = "Bitte geben Sie einen Namen für Ihr Regelwerk an. Dieser Name wird verwendet, um das Regelwerk in AI Studio zu identifizieren." + +-- Delete document analysis policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4293094335"] = "Regelwerk löschen" + +-- Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T652187065"] = "Bitte geben Sie eine Beschreibung der Regeln für die Ausgabe an. Diese Regeln werden verwendet, um die KI anzuweisen, wie die Ausgabe der Analyse formatiert werden soll." + +-- Policy description +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Regelwerkbeschreibung" + +-- Would you like to protect this policy so that you cannot accidentally edit or delete it? +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T80597472"] = "Möchten Sie dieses Regelwerk schützen, damit Sie es nicht versehentlich bearbeiten oder löschen können?" + +-- Here you have the option to save different policies for various document analysis assistants and switch between them. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Hier haben Sie die Möglichkeit, verschiedene Regelwerke für unterschiedliche Dokumentenanalysen zu speichern und zwischen ihnen zu wechseln." + -- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Geben Sie eine Liste von Stichpunkten sowie einige Basisinformationen für eine E-Mail ein. Der Assistent erstellt anschließend eine E-Mail auf Grundlage ihrer Angaben." @@ -1368,6 +1479,24 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4188329028"] = "Nein, b -- Open Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Einstellungen öffnen" +-- Drag and drop files here or click to attach documents. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T1647829151"] = "Dateien hierher ziehen und ablegen oder klicken, um Dokumente anzuhängen." + +-- Videos are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2928927510"] = "Videos werden noch nicht unterstützt." + +-- Images are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T298062956"] = "Bilder werden noch nicht unterstützt." + +-- Clear file list +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T3759696136"] = "Dateiliste löschen" + +-- Executables are not allowed +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T4167762413"] = "Ausführbare Dateien sind nicht erlaubt" + +-- Select a file to attach +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T595772870"] = "Datei zum Anhängen auswählen" + -- Changelog UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHANGELOG::T3017574265"] = "Änderungsprotokoll" @@ -1665,6 +1794,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "Hier k -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Anbieter" +-- Videos are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos werden noch nicht unterstützt." + -- Images are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Bilder werden derzeit nicht unterstützt" @@ -3606,6 +3738,33 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473 -- Local Directory UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Lokaler Ordner" +-- Assistant: Document Analysis +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistent: Dokumentenanalyse" + +-- Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1870328357"] = "Die meisten Optionen für die Analyse von Dokumenten können im Assistenten angepasst und direkt gespeichert werden. Dafür verfügt der Assistent über eine automatische Speicherfunktion." + +-- Would you like to preselect one of your profiles? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2221665527"] = "Möchten Sie eines Ihrer Profile vorab auswählen?" + +-- Preselect document analysis options? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Dokumentenanalyse-Optionen vorab auswählen?" + +-- When enabled, you can preselect some document analysis options. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2301091111"] = "Wenn aktiviert, können Sie einige Dokumentanalyse-Optionen vorab auswählen." + +-- No document analysis options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "Keine Dokumentenanalyse-Optionen sind vorausgewählt." + +-- Close +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3448155331"] = "Schließen" + +-- Document analysis options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3945756386"] = "Dokumentenanalyse-Optionen sind vorausgewählt." + +-- Preselect one of your profiles? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T4004501229"] = "Eines Ihrer Profile vorauswählen?" + -- When enabled, you can preselect some ERI server options. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "Wenn aktiviert, können Sie einige ERI-Serveroptionen vorauswählen." @@ -4479,6 +4638,9 @@ 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." +-- Analyze a document regarding defined rules and extract key information. +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1271524187"] = "Analysiere ein Dokument hinsichtlich festgelegter Regeln und extrahiere wichtige Informationen." + -- Business UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T131837803"] = "Business" @@ -4524,6 +4686,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2547582747"] = "Synonyme" -- Find synonyms for a given word or phrase. UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2712131461"] = "Finde Synonyme für ein angegebenes Wort oder eine Phrase." +-- Document Analysis +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2770149758"] = "Dokumentenanalyse" + -- AI Studio Development UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2830810750"] = "AI Studio Entwicklung" @@ -5046,6 +5211,9 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1587 -- Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1847148141"] = "PDF-Dateien einlesen: Vorschau unseres PDF-Lesesystems, mit dem Sie Text aus PDF-Dateien einlesen können" +-- Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1848209619"] = "Dokumentenanalyse: Vorschau auf unsere Dokumentenanalyse, mit dem Sie Informationen aus Dokumenten analysieren und extrahieren können." + -- Plugins: Preview of our plugin system where you can extend the functionality of the app UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2056842933"] = "Plugins: Vorschau auf unser Pluginsystems, mit dem Sie die Funktionalität der App erweitern können" @@ -5166,6 +5334,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2684676843"] = "Texte z -- Synonym Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2921123194"] = "Synonym-Assistent" +-- Document Analysis Assistant +UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T348883878"] = "Dokumentenanalyse-Assistent" + -- Translation Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T3887962308"] = "Übersetzungs-Assistent" @@ -5604,6 +5775,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::RAG::RAGPROCESSES::AISRCSELWITHRETCTXVAL::T377 -- Executable Files UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2217313358"] = "Ausführbare Dateien" +-- All Video Files +UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2850789856"] = "Alle Videodateien" + -- PDF Files UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T3108466742"] = "PDF-Dateien" 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 f0a4d270..6d389504 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 @@ -384,6 +384,117 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T -- None UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::CODING::COMMONCODINGLANGUAGEEXTENSIONS::T810547195"] = "None" +-- Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1182372158"] = "Please provide a brief description of your policy. Describe or explain what your policy does. This description will be shown to users in AI Studio." + +-- No, the policy can be edited +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1286595725"] = "No, the policy can be edited" + +-- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents." + +-- Analysis and output rules +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Analysis and output rules" + +-- Description +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1725856265"] = "Description" + +-- Yes, protect this policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1762380857"] = "Yes, protect this policy" + +-- Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1786783201"] = "Please give your policy a name that provides information about the intended purpose. The name will be displayed to users in AI Studio." + +-- Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1837166236"] = "Please provide a description for your policy. This description will be used to inform users about the purpose of your document analysis policy." + +-- Common settings +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1963959073"] = "Common settings" + +-- The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T206207667"] = "The document analysis assistant helps you to analyze and extract information from documents based on predefined policies. You can create, edit, and manage document analysis policies that define how documents should be processed and what information should be extracted. Some policies might be protected by your organization and cannot be modified or deleted." + +-- Document analysis policies +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2064879144"] = "Document analysis policies" + +-- Load output rules from document +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2168201568"] = "Load output rules from document" + +-- Definition +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T222998208"] = "Definition" + +-- The name of your policy must be between 6 and 60 characters long. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "The name of your policy must be between 6 and 60 characters long." + +-- Export policy as configuration section +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2556564432"] = "Export policy as configuration section" + +-- Are you sure you want to delete the document analysis policy '{0}'? +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2582525917"] = "Are you sure you want to delete the document analysis policy '{0}'?" + +-- Document analysis +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2708005534"] = "Document analysis" + +-- Policy name +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2879019438"] = "Policy name" + +-- Analyze documents +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2894951609"] = "Analyze documents" + +-- Documents for the analysis +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3030664641"] = "Documents for the analysis" + +-- Analysis rules +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3108719748"] = "Analysis rules" + +-- Delete this policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3119086260"] = "Delete this policy" + +-- Policy {0} +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3157740273"] = "Policy {0}" + +-- The description of your policy must be between 32 and 512 characters long. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3285636934"] = "The description of your policy must be between 32 and 512 characters long." + +-- Add policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3357792182"] = "Add policy" + +-- You have not yet added any document analysis policies. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3394850216"] = "You have not yet added any document analysis policies." + +-- Document Analysis Assistant +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T348883878"] = "Document Analysis Assistant" + +-- A policy with this name already exists. Please choose a different name. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3584374593"] = "A policy with this name already exists. Please choose a different name." + +-- Load analysis rules from document +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3813558135"] = "Load analysis rules from document" + +-- Output rules +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T3918193587"] = "Output rules" + +-- Preparation for enterprise distribution +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T39557294"] = "Preparation for enterprise distribution" + +-- Please provide a name for your policy. This name will be used to identify the policy in AI Studio. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4040507702"] = "Please provide a name for your policy. This name will be used to identify the policy in AI Studio." + +-- Delete document analysis policy +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T4293094335"] = "Delete document analysis policy" + +-- Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T652187065"] = "Please provide a description of your output rules. This rules will be used to instruct the AI on how to format the output of the analysis." + +-- Policy description +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T748735777"] = "Policy description" + +-- Would you like to protect this policy so that you cannot accidentally edit or delete it? +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T80597472"] = "Would you like to protect this policy so that you cannot accidentally edit or delete it?" + +-- Here you have the option to save different policies for various document analysis assistants and switch between them. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T848153710"] = "Here you have the option to save different policies for various document analysis assistants and switch between them." + -- Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::EMAIL::ASSISTANTEMAIL::T1143222914"] = "Provide a list of bullet points and some basic information for an e-mail. The assistant will generate an e-mail based on that input." @@ -1368,6 +1479,24 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4188329028"] = "No, kee -- Open Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Settings" +-- Drag and drop files here or click to attach documents. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T1647829151"] = "Drag and drop files here or click to attach documents." + +-- Videos are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2928927510"] = "Videos are not supported yet" + +-- Images are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T298062956"] = "Images are not supported yet" + +-- Clear file list +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T3759696136"] = "Clear file list" + +-- Executables are not allowed +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T4167762413"] = "Executables are not allowed" + +-- Select a file to attach +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T595772870"] = "Select a file to attach" + -- Changelog UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHANGELOG::T3017574265"] = "Changelog" @@ -1665,6 +1794,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Provider" +-- Videos are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos are not supported yet" + -- Images are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Images are not supported yet" @@ -3606,6 +3738,33 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T774473 -- Local Directory UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory" +-- Assistant: Document Analysis +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1372406750"] = "Assistant: Document Analysis" + +-- Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T1870328357"] = "Most document analysis options can be customized and saved directly in the assistant. For this, the assistant has an auto-save function." + +-- Would you like to preselect one of your profiles? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2221665527"] = "Would you like to preselect one of your profiles?" + +-- Preselect document analysis options? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2230062650"] = "Preselect document analysis options?" + +-- When enabled, you can preselect some document analysis options. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T2301091111"] = "When enabled, you can preselect some document analysis options." + +-- No document analysis options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3317802895"] = "No document analysis options are preselected" + +-- Close +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3448155331"] = "Close" + +-- Document analysis options are preselected +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T3945756386"] = "Document analysis options are preselected" + +-- Preselect one of your profiles? +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDOCUMENTANALYSIS::T4004501229"] = "Preselect one of your profiles?" + -- When enabled, you can preselect some ERI server options. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options." @@ -4479,6 +4638,9 @@ 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." +-- Analyze a document regarding defined rules and extract key information. +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T1271524187"] = "Analyze a document regarding defined rules and extract key information." + -- Business UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T131837803"] = "Business" @@ -4524,6 +4686,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2547582747"] = "Synonyms" -- Find synonyms for a given word or phrase. UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2712131461"] = "Find synonyms for a given word or phrase." +-- Document Analysis +UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2770149758"] = "Document Analysis" + -- AI Studio Development UI_TEXT_CONTENT["AISTUDIO::PAGES::ASSISTANTS::T2830810750"] = "AI Studio Development" @@ -5046,6 +5211,9 @@ UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1587 -- Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1847148141"] = "Read PDF: Preview of our PDF reading system where you can read and extract text from PDF files" +-- Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents +UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T1848209619"] = "Document Analysis: Preview of our document analysis system where you can analyze and extract information from documents" + -- Plugins: Preview of our plugin system where you can extend the functionality of the app UI_TEXT_CONTENT["AISTUDIO::SETTINGS::DATAMODEL::PREVIEWFEATURESEXTENSIONS::T2056842933"] = "Plugins: Preview of our plugin system where you can extend the functionality of the app" @@ -5166,6 +5334,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2684676843"] = "Text Su -- Synonym Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T2921123194"] = "Synonym Assistant" +-- Document Analysis Assistant +UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T348883878"] = "Document Analysis Assistant" + -- Translation Assistant UI_TEXT_CONTENT["AISTUDIO::TOOLS::COMPONENTSEXTENSIONS::T3887962308"] = "Translation Assistant" @@ -5604,6 +5775,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::RAG::RAGPROCESSES::AISRCSELWITHRETCTXVAL::T377 -- Executable Files UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2217313358"] = "Executable Files" +-- All Video Files +UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T2850789856"] = "All Video Files" + -- PDF Files UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPEFILTER::T3108466742"] = "PDF Files" From 2f124b1c5e02199901e1218dc92544631e709202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Sch=C3=BCtt?= <20603780+peerschuett@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:43:03 +0100 Subject: [PATCH 36/42] Erste Version der Prompts --- .../DocumentAnalysisAssistant.razor | 19 +++- .../DocumentAnalysisAssistant.razor.cs | 95 ++++++++++++++++++- .../Assistants/I18N/allTexts.lua | 6 +- 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 5255ec8f..53fd2a1a 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -41,24 +41,28 @@ else -
- - + @T("Common settings") + + + @T("Input and output rules") + + + @@ -68,12 +72,16 @@ else @T("Export policy as configuration section") + +
+ @T("Description") + @this.selectedPolicy?.PolicyDescription @@ -81,6 +89,11 @@ else @T("Documents for the analysis") + + + + +
\ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 5df8dfac..7cf73955 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -27,7 +27,39 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore 1) + { + sb.Append($"Your task is to analyse {this.loadedDocumentPaths.Count} documents."); + sb.Append("Different Documents are divided by a horizontal rule in markdown formatting followed by the name of the document."); + sb.Append(Environment.NewLine); + } + else + { + sb.Append("Your task is to analyse a single document."); + sb.Append(Environment.NewLine); + } + + var taskDescription = $""" + The analysis should be done using the policy analysis rules. + The output should be formatted according to the policy output rules. + The rule sets should be followed strictly. + Only use information given in the documents or in the policy. + Never add any information of your own to it. + Keep your answers precise, professional and factual. + Only answer with the correctly formatted analysis result and do not add any opening or closing remarks. + Answer in the language that is used by the policy or is stated in the output rules. + """; + + sb.Append(taskDescription); + sb.Append(Environment.NewLine); + + sb.Append(this.PromptGetActivePolicy()); + sb.Append(Environment.NewLine); + return sb.ToString(); } } @@ -249,6 +281,58 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore PromptLoadDocumentsContent() + { + if (this.loadedDocumentPaths.Count == 0) + { + return string.Empty; + } + + var sb = new StringBuilder(); + var count = 1; + foreach(var documentPath in this.loadedDocumentPaths) + { + sb.Append("---"); + sb.Append(Environment.NewLine); + sb.Append($"Document {count} file path: {documentPath}"); + sb.Append(Environment.NewLine); + sb.Append($"Document {count} content:"); + sb.Append(Environment.NewLine); + + var fileContent = await this.RustService.ReadArbitraryFileData(documentPath, int.MaxValue); + sb.Append($""" + ``` + {fileContent} + ``` + """); + sb.Append(Environment.NewLine); + sb.Append(Environment.NewLine); + count += 1; + } + + return sb.ToString(); + } + private async Task Analyze() { if (this.IsNoPolicySelectedOrProtected) @@ -259,6 +343,13 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore Date: Mon, 17 Nov 2025 15:44:58 +0100 Subject: [PATCH 37/42] Working on it --- .../DocumentAnalysisAssistant.razor | 8 ++-- .../DocumentAnalysisAssistant.razor.cs | 41 ++++++++++++------- .../Components/AttachDocuments.razor.cs | 10 ++++- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 53fd2a1a..e90e4d76 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -25,7 +25,7 @@ else @foreach (var policy in this.SettingsManager.ConfigurationData.DocumentAnalysis.Policies) { - + @policy.PolicyName } @@ -42,7 +42,7 @@ else - + @T("Common settings") @@ -69,7 +69,7 @@ else @T("Preparation for enterprise distribution") - + @T("Export policy as configuration section") @@ -90,7 +90,7 @@ else @T("Documents for the analysis") - + diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 7cf73955..2ac73af2 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -29,21 +29,21 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore 1) { sb.Append($"Your task is to analyse {this.loadedDocumentPaths.Count} documents."); sb.Append("Different Documents are divided by a horizontal rule in markdown formatting followed by the name of the document."); - sb.Append(Environment.NewLine); + sb.AppendLine(); } else { sb.Append("Your task is to analyse a single document."); - sb.Append(Environment.NewLine); + sb.AppendLine(); } - var taskDescription = $""" + var taskDescription = """ The analysis should be done using the policy analysis rules. The output should be formatted according to the policy output rules. The rule sets should be followed strictly. @@ -55,10 +55,9 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore PromptLoadDocumentsContent() { if (this.loadedDocumentPaths.Count == 0) - { return string.Empty; - } var sb = new StringBuilder(); var count = 1; foreach(var documentPath in this.loadedDocumentPaths) { sb.Append("---"); - sb.Append(Environment.NewLine); + sb.AppendLine(); sb.Append($"Document {count} file path: {documentPath}"); - sb.Append(Environment.NewLine); + sb.AppendLine(); sb.Append($"Document {count} content:"); - sb.Append(Environment.NewLine); + sb.AppendLine(); var fileContent = await this.RustService.ReadArbitraryFileData(documentPath, int.MaxValue); sb.Append($""" @@ -325,8 +322,8 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore, Task> OnChange { get; set; } = _ => Task.CompletedTask; + /// + /// Catch all documents that are hovered over the AI Studio window and not only over the drop zone. + /// + [Parameter] + public bool CatchAllDocuments { get; set; } + [Inject] private ILogger Logger { get; set; } = null!; @@ -38,7 +44,7 @@ public partial class AttachDocuments : MSGComponentBase switch (triggeredEvent) { case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_HOVERED }: - if(!this.isComponentHovered) + if(!this.isComponentHovered && !this.CatchAllDocuments) { this.Logger.LogDebug("Attach documents component '{Name}' is not hovered, ignoring file drop hovered event.", this.Name); return; @@ -49,7 +55,7 @@ public partial class AttachDocuments : MSGComponentBase break; case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_DROPPED, Payload: var paths }: - if(!this.isComponentHovered) + if(!this.isComponentHovered && !this.CatchAllDocuments) { this.Logger.LogDebug("Attach documents component '{Name}' is not hovered, ignoring file drop dropped event.", this.Name); return; From fe26495cd60565a2df38324137f13e8517ef5b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Sch=C3=BCtt?= <20603780+peerschuett@users.noreply.github.com> Date: Mon, 17 Nov 2025 17:26:22 +0100 Subject: [PATCH 38/42] Documents can now be removed individually --- .../Components/AttachDocuments.razor | 4 +++- .../Components/AttachDocuments.razor.cs | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor b/app/MindWork AI Studio/Components/AttachDocuments.razor index 383d343f..aa89ebe3 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor @@ -8,7 +8,9 @@ @foreach (var fileInfo in this.DocumentPaths.Select(file => new FileInfo(file))) { - + + + }
diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs index b553ec35..3f377bb5 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs @@ -151,4 +151,23 @@ public partial class AttachDocuments : MSGComponentBase this.ClearDragClass(); this.StateHasChanged(); } + + private async Task RemoveDocumentPathFromDocumentPaths(FileInfo file) + { + this.DocumentPaths.Remove(file.ToString()); + + await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths); + await this.OnChange(this.DocumentPaths); + } + + /// + /// The user might want to check what the Pandoc integration actually extracts from his file and therefore gives the LLM as input. + /// + /// The file to check. + private void InvestigateFile(FileInfo file) + { + # warning Implement Investigation of file + this.Logger.LogDebug("Investigate"); + return; + } } \ No newline at end of file From 2bc0e42d4514c41ecbe8fb785205979dbcdc6d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Sch=C3=BCtt?= <20603780+peerschuett@users.noreply.github.com> Date: Mon, 17 Nov 2025 17:32:41 +0100 Subject: [PATCH 39/42] I18n --- .../plugin.lua | 12 ++++++------ .../plugin.lua | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) 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 d37528fe..44b7558d 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 @@ -420,12 +420,12 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Load output rules from document UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2168201568"] = "Regeln für die Ausgabe aus einem Dokument laden" --- Definition -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T222998208"] = "Definition" - -- The name of your policy must be between 6 and 60 characters long. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "Der Name Ihres Regelwerks muss zwischen 6 und 60 Zeichen lang sein." +-- Policy definition +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2491168104"] = "Definition des Regelwerks" + -- Export policy as configuration section UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2556564432"] = "Exportieren Sie das Regelwerk als Konfigurationsabschnitt" @@ -1797,15 +1797,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "Hier k -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Anbieter" --- Videos are not supported yet -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos werden noch nicht unterstützt." - -- Pandoc Installation UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T185447014"] = "Pandoc-Installation" -- Pandoc may be required for importing files. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2596465560"] = "Pandoc wird möglicherweise zum Importieren von Dateien benötigt." +-- Videos are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos werden noch nicht unterstützt." + -- Images are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Bilder werden derzeit nicht unterstützt" 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 df94cd23..3c2f2228 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 @@ -420,12 +420,12 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Load output rules from document UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2168201568"] = "Load output rules from document" --- Definition -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T222998208"] = "Definition" - -- The name of your policy must be between 6 and 60 characters long. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2435013256"] = "The name of your policy must be between 6 and 60 characters long." +-- Policy definition +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2491168104"] = "Policy definition" + -- Export policy as configuration section UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T2556564432"] = "Export policy as configuration section" @@ -1797,15 +1797,15 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Provider" --- Videos are not supported yet -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos are not supported yet" - -- Pandoc Installation UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T185447014"] = "Pandoc Installation" -- Pandoc may be required for importing files. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2596465560"] = "Pandoc may be required for importing files." +-- Videos are not supported yet +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2928927510"] = "Videos are not supported yet" + -- Images are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Images are not supported yet" From 56c652f38dd83ca6f3deade69ec59bae364f2e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Sch=C3=BCtt?= <20603780+peerschuett@users.noreply.github.com> Date: Mon, 17 Nov 2025 17:52:28 +0100 Subject: [PATCH 40/42] Minor changes to layout --- .../DocumentAnalysis/DocumentAnalysisAssistant.razor | 10 ++++------ .../DocumentAnalysisAssistant.razor.cs | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index e90e4d76..00ee478d 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -42,7 +42,7 @@ else - + @T("Common settings") @@ -72,10 +72,9 @@ else @T("Export policy as configuration section") - -
+ @@ -93,7 +92,6 @@ else +
- - - \ No newline at end of file + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index 2ac73af2..e3bf3bc7 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -73,7 +73,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore SubmitAction => this.Analyze; - protected override bool SubmitDisabled => this.IsNoPolicySelected; + protected override bool SubmitDisabled => (this.IsNoPolicySelected || this.loadedDocumentPaths.Count==0); protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with { From 48dcf6bba928ecadb507473bbff7c93b4a602356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Sch=C3=BCtt?= <20603780+peerschuett@users.noreply.github.com> Date: Fri, 21 Nov 2025 14:12:46 +0100 Subject: [PATCH 41/42] Added a dialog to check if the document is loaded as the user expects --- .../Components/AttachDocuments.razor.cs | 15 +++++++++++++- .../Dialogs/PandocDocumentCheckDialog.razor | 20 +++++++++++++++++++ .../PandocDocumentCheckDialog.razor.cs | 20 +++++++++++++++++++ .../MindWork AI Studio.csproj | 6 ++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor create mode 100644 app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor.cs diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs index 3f377bb5..8ce46780 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs @@ -1,3 +1,4 @@ +using AIStudio.Dialogs; using AIStudio.Tools.Rust; using AIStudio.Tools.Services; @@ -5,6 +6,8 @@ using Microsoft.AspNetCore.Components; namespace AIStudio.Components; +using DialogOptions = AIStudio.Dialogs.DialogOptions; + public partial class AttachDocuments : MSGComponentBase { [Parameter] @@ -31,6 +34,9 @@ public partial class AttachDocuments : MSGComponentBase [Inject] private RustService RustService { get; init; } = null!; + [Inject] + private IDialogService DialogService { get; init; } = null!; + #region Overrides of MSGComponentBase protected override async Task OnInitializedAsync() @@ -164,10 +170,17 @@ public partial class AttachDocuments : MSGComponentBase /// The user might want to check what the Pandoc integration actually extracts from his file and therefore gives the LLM as input. /// /// The file to check. - private void InvestigateFile(FileInfo file) + private async Task InvestigateFile(FileInfo file) { # warning Implement Investigation of file this.Logger.LogDebug("Investigate"); + + var dialogParameters = new DialogParameters{}; + + var dialogReference = await this.DialogService.ShowAsync("Check document content", dialogParameters, DialogOptions.FULLSCREEN); + var dialogResult = await dialogReference.Result; + if (dialogResult is null || dialogResult.Canceled) + return; return; } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor b/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor new file mode 100644 index 00000000..e6f3cf7c --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor @@ -0,0 +1,20 @@ +@inherits MSGComponentBase + + + + + @T("Here you can check if Pandoc loads your file as expected.") + + + + + + @this.documentContent + + + + + @T("Cancel") + + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor.cs b/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor.cs new file mode 100644 index 00000000..361342d4 --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor.cs @@ -0,0 +1,20 @@ +using System.Formats.Asn1; +using AIStudio.Components; + +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Dialogs; + +/// +/// Check how your file will be loaded by Pandoc. +/// +public partial class PandocDocumentCheckDialog : MSGComponentBase +{ + [CascadingParameter] + private IMudDialogInstance MudDialog { get; set; } = null!; + + + private string documentContent = string.Empty; + + private void Cancel() => this.MudDialog.Cancel(); +} \ No newline at end of file diff --git a/app/MindWork AI Studio/MindWork AI Studio.csproj b/app/MindWork AI Studio/MindWork AI Studio.csproj index 5d39cb48..b559389c 100644 --- a/app/MindWork AI Studio/MindWork AI Studio.csproj +++ b/app/MindWork AI Studio/MindWork AI Studio.csproj @@ -61,6 +61,12 @@ + + + true + + + From 2d28105865a592abc74413222d2e0dd5dd68874f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Sch=C3=BCtt?= <20603780+peerschuett@users.noreply.github.com> Date: Fri, 21 Nov 2025 15:53:23 +0100 Subject: [PATCH 42/42] The PandocDocumentCheckDialog.razor now looks nicer. Also disabled the option to export policys to Lua, because it is not implemented yet. --- .../DocumentAnalysisAssistant.razor | 4 ++- .../Assistants/I18N/allTexts.lua | 21 ++++++++++++++ .../Components/AttachDocuments.razor.cs | 3 +- .../Dialogs/PandocDocumentCheckDialog.razor | 28 ++++++++++++++----- .../plugin.lua | 21 ++++++++++++++ .../plugin.lua | 21 ++++++++++++++ 6 files changed, 88 insertions(+), 10 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor index 00ee478d..2cefb7ac 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor @@ -69,9 +69,11 @@ else @T("Preparation for enterprise distribution") - + + @T("Export policy as configuration section") + diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 4d2e707a..c2b1cc0b 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -391,6 +391,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents." +-- Not implemented yet. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1568777658"] = "Not implemented yet." + -- Input and output rules UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Input and output rules" @@ -1483,6 +1486,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Set -- Drag and drop files here or click to attach documents. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T1647829151"] = "Drag and drop files here or click to attach documents." +-- Pandoc Load Document Preview +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2686523471"] = "Pandoc Load Document Preview" + -- Videos are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2928927510"] = "Videos are not supported yet" @@ -3112,6 +3118,21 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T504404155"] = "Accept the ter -- 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." +-- Test how Pandoc loads your document. See the raw content it produces before further processing. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T1481857352"] = "Test how Pandoc loads your document. See the raw content it produces before further processing." + +-- Content Loaded by Pandoc +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2147198279"] = "Content Loaded by Pandoc" + +-- This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2156541074"] = "This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected." + +-- Load document +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2394358670"] = "Load document" + +-- Cancel +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T900713019"] = "Cancel" + -- 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." diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs index 8ce46780..7b885842 100644 --- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs +++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs @@ -173,11 +173,10 @@ public partial class AttachDocuments : MSGComponentBase private async Task InvestigateFile(FileInfo file) { # warning Implement Investigation of file - this.Logger.LogDebug("Investigate"); var dialogParameters = new DialogParameters{}; - var dialogReference = await this.DialogService.ShowAsync("Check document content", dialogParameters, DialogOptions.FULLSCREEN); + var dialogReference = await this.DialogService.ShowAsync(T("Pandoc Load Document Preview"), dialogParameters, DialogOptions.FULLSCREEN); var dialogResult = await dialogReference.Result; if (dialogResult is null || dialogResult.Canceled) return; diff --git a/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor b/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor index e6f3cf7c..50e81235 100644 --- a/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor +++ b/app/MindWork AI Studio/Dialogs/PandocDocumentCheckDialog.razor @@ -1,16 +1,30 @@ @inherits MSGComponentBase + - - @T("Here you can check if Pandoc loads your file as expected.") + + + + @T("Test how Pandoc loads your document. See the raw content it produces before further processing.") - + - - - @this.documentContent - + + 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 44b7558d..15b818e4 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 @@ -393,6 +393,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Bitte geben Sie eine Beschreibung Ihrer Analysekriterien an. Diese Regeln werden verwendet, um die KI anzuweisen, wie die Dokumente analysiert werden sollen." +-- Not implemented yet. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1568777658"] = "Noch nicht implementiert." + -- Analysis and output rules UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Analyse- und Ausgaberegeln" @@ -1485,6 +1488,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Einstell -- Drag and drop files here or click to attach documents. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T1647829151"] = "Dateien hierher ziehen und ablegen oder klicken, um Dokumente anzuhängen." +-- Pandoc Load Document Preview +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2686523471"] = "Pandoc-Dokumentvorschau" + -- Videos are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2928927510"] = "Videos werden noch nicht unterstützt." @@ -3114,6 +3120,21 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T504404155"] = "Akzeptieren Si -- 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." +-- Test how Pandoc loads your document. See the raw content it produces before further processing. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T1481857352"] = "Testen Sie, wie Pandoc Ihr Dokument lädt, und überprüfen Sie ob der Inhalt korrekt geladen wird." + +-- Content Loaded by Pandoc +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2147198279"] = "Von Pandoc geladener Inhalt" + +-- This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2156541074"] = "Das ist der Inhalt, den Pandoc aus Ihrem Dokument geladen hat – einschließlich Überschriften, Listen und Formatierung. Überprüfen Sie damit, ob Ihr Dokument wie erwartet geladen wird." + +-- Load document +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2394358670"] = "Dokument laden" + +-- Cancel +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T900713019"] = "Abbrechen" + -- 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." 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 3c2f2228..f962cf75 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 @@ -393,6 +393,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTA -- Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents. UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1291179736"] = "Please provide a description of your analysis rules. This rules will be used to instruct the AI on how to analyze the documents." +-- Not implemented yet. +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1568777658"] = "Not implemented yet." + -- Analysis and output rules UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::DOCUMENTANALYSIS::DOCUMENTANALYSISASSISTANT::T1714738288"] = "Analysis and output rules" @@ -1485,6 +1488,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Set -- Drag and drop files here or click to attach documents. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T1647829151"] = "Drag and drop files here or click to attach documents." +-- Pandoc Load Document Preview +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2686523471"] = "Pandoc Load Document Preview" + -- Videos are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ATTACHDOCUMENTS::T2928927510"] = "Videos are not supported yet" @@ -3114,6 +3120,21 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDIALOG::T504404155"] = "Accept the ter -- 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." +-- Test how Pandoc loads your document. See the raw content it produces before further processing. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T1481857352"] = "Test how Pandoc loads your document. See the raw content it produces before further processing." + +-- Content Loaded by Pandoc +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2147198279"] = "Content Loaded by Pandoc" + +-- This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2156541074"] = "This is the content Pandoc loaded from your document — including headings, lists, and formatting. Use this to verify your document loads as expected." + +-- Load document +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T2394358670"] = "Load document" + +-- Cancel +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PANDOCDOCUMENTCHECKDIALOG::T900713019"] = "Cancel" + -- 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."