diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor b/app/MindWork AI Studio/Assistants/AssistantBase.razor index ba18f75..ac744a4 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor @@ -94,7 +94,7 @@ Reset - @if (this.AllowProfiles) + @if (this.AllowProfiles && this.ShowProfileSelection) { } diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs index c63659f..5bf8425 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs @@ -57,6 +57,8 @@ public abstract partial class AssistantBase : ComponentBase protected virtual bool ShowResult => true; protected virtual bool AllowProfiles => true; + + protected virtual bool ShowProfileSelection => true; protected virtual bool ShowDedicatedProgress => false; @@ -69,12 +71,12 @@ public abstract partial class AssistantBase : ComponentBase protected AIStudio.Settings.Provider providerSettings; protected MudForm? form; protected bool inputIsValid; + protected Profile currentProfile = Profile.NO_PROFILE; protected ChatThread? chatThread; private ContentBlock? resultingContentBlock; private string[] inputIssues = []; private bool isProcessing; - private Profile currentProfile = Profile.NO_PROFILE; #region Overrides of ComponentBase diff --git a/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor b/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor new file mode 100644 index 0000000..1b34dba --- /dev/null +++ b/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor @@ -0,0 +1,11 @@ +@attribute [Route(Routes.ASSISTANT_MY_TASKS)] +@inherits AssistantBaseCore + + + + + + + + Analyze text + \ No newline at end of file diff --git a/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor.cs b/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor.cs new file mode 100644 index 0000000..6eba246 --- /dev/null +++ b/app/MindWork AI Studio/Assistants/MyTasks/AssistantMyTasks.razor.cs @@ -0,0 +1,119 @@ +using AIStudio.Settings; + +namespace AIStudio.Assistants.MyTasks; + +public partial class AssistantMyTasks : AssistantBaseCore +{ + protected override Tools.Components Component => Tools.Components.MY_TASKS_ASSISTANT; + + protected override string Title => "My Tasks"; + + protected override string Description => + """ + You received a cryptic email that was sent to many recipients and you are now wondering + if you need to do something? Copy the email into the input field. You also need to select + a personal profile. In this profile, you should describe your role in the organization. + The AI will then try to give you hints on what your tasks might be. + """; + + protected override string SystemPrompt => + $""" + You are a friendly and professional business expert. You receive business emails, protocols, + reports, etc. as input. Additionally, you know the user's role in the organization. The user + wonders if any tasks arise for them in their role based on the text. You now try to give hints + and advice on whether and what the user should do. When you believe there are no tasks for the + user, you tell them this. You consider typical business etiquette in your advice. + + You write your advice in the following language: {this.SystemPromptLanguage()}. + """; + + protected override IReadOnlyList FooterButtons => []; + + protected override bool ShowProfileSelection => false; + + protected override void ResetFrom() + { + this.inputText = string.Empty; + if (!this.MightPreselectValues()) + { + this.selectedTargetLanguage = CommonLanguages.AS_IS; + this.customTargetLanguage = string.Empty; + } + } + + protected override bool MightPreselectValues() + { + if (this.SettingsManager.ConfigurationData.MyTasks.PreselectOptions) + { + this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage; + this.customTargetLanguage = this.SettingsManager.ConfigurationData.MyTasks.PreselectOtherLanguage; + return true; + } + + return false; + } + + private string inputText = string.Empty; + private CommonLanguages selectedTargetLanguage = CommonLanguages.AS_IS; + private string customTargetLanguage = string.Empty; + + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages(Event.SEND_TO_MY_TASKS_ASSISTANT).FirstOrDefault(); + if (deferredContent is not null) + this.inputText = deferredContent; + + await base.OnInitializedAsync(); + } + + #endregion + + private string? ValidatingText(string text) + { + if(string.IsNullOrWhiteSpace(text)) + return "Please provide some text as input. For example, an email."; + + return null; + } + + private string? ValidateProfile(Profile profile) + { + if(profile == default || profile == Profile.NO_PROFILE) + return "Please select one of your profiles."; + + return null; + } + + private string? ValidateCustomLanguage(string language) + { + if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language)) + return "Please provide a custom language."; + + return null; + } + + private string SystemPromptLanguage() + { + if(this.selectedTargetLanguage is CommonLanguages.AS_IS) + return "Use the same language as the input"; + + if(this.selectedTargetLanguage is CommonLanguages.OTHER) + return this.customTargetLanguage; + + return this.selectedTargetLanguage.Name(); + } + + private async Task AnalyzeText() + { + await this.form!.Validate(); + if (!this.inputIsValid) + return; + + this.CreateChatThread(); + var time = this.AddUserRequest(this.inputText); + + await this.AddAIResponseAsync(time); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ProfileFormSelection.razor b/app/MindWork AI Studio/Components/ProfileFormSelection.razor new file mode 100644 index 0000000..075a0b2 --- /dev/null +++ b/app/MindWork AI Studio/Components/ProfileFormSelection.razor @@ -0,0 +1,10 @@ +@using AIStudio.Settings + + + @foreach (var profile in this.SettingsManager.ConfigurationData.Profiles.GetAllProfiles()) + { + + @profile.Name + + } + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/ProfileFormSelection.razor.cs b/app/MindWork AI Studio/Components/ProfileFormSelection.razor.cs new file mode 100644 index 0000000..2b27e6c --- /dev/null +++ b/app/MindWork AI Studio/Components/ProfileFormSelection.razor.cs @@ -0,0 +1,26 @@ +using AIStudio.Settings; + +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components; + +public partial class ProfileFormSelection : ComponentBase +{ + [Parameter] + public Profile Profile { get; set; } = Profile.NO_PROFILE; + + [Parameter] + public EventCallback ProfileChanged { get; set; } + + [Parameter] + public Func Validation { get; set; } = _ => null; + + [Inject] + private SettingsManager SettingsManager { get; init; } = null!; + + private async Task SelectionChanged(Profile profile) + { + this.Profile = profile; + await this.ProfileChanged.InvokeAsync(profile); + } +} \ 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 e90492e..da377d7 100644 --- a/app/MindWork AI Studio/Pages/Assistants.razor +++ b/app/MindWork AI Studio/Pages/Assistants.razor @@ -22,6 +22,7 @@ + diff --git a/app/MindWork AI Studio/Pages/Settings.razor b/app/MindWork AI Studio/Pages/Settings.razor index 32f979c..5ba3b60 100644 --- a/app/MindWork AI Studio/Pages/Settings.razor +++ b/app/MindWork AI Studio/Pages/Settings.razor @@ -299,6 +299,19 @@ + + + + + + @if (this.SettingsManager.ConfigurationData.MyTasks.PreselectedTargetLanguage is CommonLanguages.OTHER) + { + + } + + + + diff --git a/app/MindWork AI Studio/Routes.razor.cs b/app/MindWork AI Studio/Routes.razor.cs index bb80908..f65d7ec 100644 --- a/app/MindWork AI Studio/Routes.razor.cs +++ b/app/MindWork AI Studio/Routes.razor.cs @@ -20,5 +20,6 @@ public sealed partial class Routes public const string ASSISTANT_EMAIL = "/assistant/email"; public const string ASSISTANT_LEGAL_CHECK = "/assistant/legal-check"; public const string ASSISTANT_SYNONYMS = "/assistant/synonyms"; + public const string ASSISTANT_MY_TASKS = "/assistant/my-tasks"; // 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 f1dc886..da8abc3 100644 --- a/app/MindWork AI Studio/Settings/DataModel/Data.cs +++ b/app/MindWork AI Studio/Settings/DataModel/Data.cs @@ -58,4 +58,6 @@ public sealed class Data public DataLegalCheck LegalCheck { get; set; } = new(); public DataSynonyms Synonyms { get; set; } = new(); + + public DataMyTasks MyTasks { get; set; } = new(); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataMyTasks.cs b/app/MindWork AI Studio/Settings/DataModel/DataMyTasks.cs new file mode 100644 index 0000000..9b848e4 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataMyTasks.cs @@ -0,0 +1,29 @@ +namespace AIStudio.Settings.DataModel; + +public sealed class DataMyTasks +{ + /// + /// Do you want to preselect any options? + /// + public bool PreselectOptions { get; set; } + + /// + /// Preselect the target language? + /// + public CommonLanguages PreselectedTargetLanguage { get; set; } + + /// + /// Preselect any other language? + /// + public string PreselectOtherLanguage { get; set; } = string.Empty; + + /// + /// The preselected provider. + /// + 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/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs index 428c518..e745921 100644 --- a/app/MindWork AI Studio/Settings/SettingsManager.cs +++ b/app/MindWork AI Studio/Settings/SettingsManager.cs @@ -129,6 +129,7 @@ public sealed class SettingsManager(ILogger logger) Tools.Components.EMAIL_ASSISTANT => this.ConfigurationData.EMail.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.EMail.PreselectedProvider) : default, Tools.Components.LEGAL_CHECK_ASSISTANT => this.ConfigurationData.LegalCheck.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.LegalCheck.PreselectedProvider) : default, Tools.Components.SYNONYMS_ASSISTANT => this.ConfigurationData.Synonyms.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.Synonyms.PreselectedProvider) : default, + Tools.Components.MY_TASKS_ASSISTANT => this.ConfigurationData.MyTasks.PreselectOptions ? this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.ConfigurationData.MyTasks.PreselectedProvider) : default, _ => default, }; @@ -148,6 +149,7 @@ public sealed class SettingsManager(ILogger logger) Tools.Components.CODING_ASSISTANT => this.ConfigurationData.Coding.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.Coding.PreselectedProfile) : default, Tools.Components.EMAIL_ASSISTANT => this.ConfigurationData.EMail.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.EMail.PreselectedProfile) : default, Tools.Components.LEGAL_CHECK_ASSISTANT => this.ConfigurationData.LegalCheck.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.LegalCheck.PreselectedProfile) : default, + Tools.Components.MY_TASKS_ASSISTANT => this.ConfigurationData.MyTasks.PreselectOptions ? this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.MyTasks.PreselectedProfile) : default, _ => default, }; diff --git a/app/MindWork AI Studio/Tools/Components.cs b/app/MindWork AI Studio/Tools/Components.cs index 693905c..1076585 100644 --- a/app/MindWork AI Studio/Tools/Components.cs +++ b/app/MindWork AI Studio/Tools/Components.cs @@ -14,6 +14,7 @@ public enum Components EMAIL_ASSISTANT, LEGAL_CHECK_ASSISTANT, SYNONYMS_ASSISTANT, + MY_TASKS_ASSISTANT, CHAT, } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Event.cs b/app/MindWork AI Studio/Tools/Event.cs index 84beba5..cacc17f 100644 --- a/app/MindWork AI Studio/Tools/Event.cs +++ b/app/MindWork AI Studio/Tools/Event.cs @@ -28,4 +28,5 @@ public enum Event SEND_TO_EMAIL_ASSISTANT, SEND_TO_LEGAL_CHECK_ASSISTANT, SEND_TO_SYNONYMS_ASSISTANT, + SEND_TO_MY_TASKS_ASSISTANT, } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/SendToExtensions.cs b/app/MindWork AI Studio/Tools/SendToExtensions.cs index fddb2aa..c8abe68 100644 --- a/app/MindWork AI Studio/Tools/SendToExtensions.cs +++ b/app/MindWork AI Studio/Tools/SendToExtensions.cs @@ -14,6 +14,7 @@ public static class SendToExtensions Components.EMAIL_ASSISTANT => "E-Mail Assistant", Components.LEGAL_CHECK_ASSISTANT => "Legal Check Assistant", Components.SYNONYMS_ASSISTANT => "Synonym Assistant", + Components.MY_TASKS_ASSISTANT => "My Tasks Assistant", Components.CHAT => "New Chat", @@ -32,6 +33,7 @@ public static class SendToExtensions Components.TEXT_SUMMARIZER_ASSISTANT => new(Event.SEND_TO_TEXT_SUMMARIZER_ASSISTANT, Routes.ASSISTANT_SUMMARIZER), Components.LEGAL_CHECK_ASSISTANT => new(Event.SEND_TO_LEGAL_CHECK_ASSISTANT, Routes.ASSISTANT_LEGAL_CHECK), 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.CHAT => new(Event.SEND_TO_CHAT, Routes.CHAT), diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.8.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.8.md new file mode 100644 index 0000000..37dcceb --- /dev/null +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.8.md @@ -0,0 +1,2 @@ +# v0.9.8, build 183 (2024-09-09 13:00 UTC) +- Added the "my tasks" assistant to analyze, e.g., business emails and extract related tasks for your role. \ No newline at end of file