From 6b7800b61507ec67a39563f89576fe65208486ca Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Mon, 5 Aug 2024 21:12:52 +0200 Subject: [PATCH] Add agenda assistant (#69) --- app/MindWork AI Studio/Chat/ContentText.cs | 2 +- .../Components/Blocks/Changelog.Logs.cs | 1 + .../Blocks/ConfigurationSlider.razor.cs | 25 + .../Components/Blocks/EnumSelection.razor | 17 + .../Components/Blocks/EnumSelection.razor.cs | 79 +++ .../Components/Blocks/EnumSelectionBase.cs | 8 + .../Components/Blocks/MudTextSlider.razor | 7 + .../Components/Blocks/MudTextSlider.razor.cs | 78 +++ .../Components/Blocks/MudTextSwitch.razor | 5 + .../Components/Blocks/MudTextSwitch.razor.cs | 30 ++ .../Components/Blocks/ProcessComponent.razor | 11 + .../Blocks/ProcessComponent.razor.cs | 16 + .../Components/Blocks/ProviderSelection.razor | 8 + .../Blocks/ProviderSelection.razor.cs | 26 + .../Components/Blocks/ReadWebContent.razor | 20 +- .../Components/Blocks/ReadWebContent.razor.cs | 11 +- .../Components/Layout/MainLayout.razor | 4 +- .../Components/Layout/MainLayout.razor.cs | 4 +- .../Pages/Agenda/AssistantAgenda.razor | 56 +++ .../Pages/Agenda/AssistantAgenda.razor.cs | 452 ++++++++++++++++++ .../Pages/Agenda/NumberParticipants.cs | 18 + .../Agenda/NumberParticipantsExtensions.cs | 24 + .../Components/Pages/Assistants.razor | 1 + .../Components/Pages/Chat.razor | 19 +- .../Components/Pages/Chat.razor.cs | 18 +- .../Pages/Coding/AssistantCoding.razor | 13 +- .../Pages/Coding/AssistantCoding.razor.cs | 10 +- .../IconFinder/AssistantIconFinder.razor | 9 +- .../IconFinder/AssistantIconFinder.razor.cs | 6 +- .../Components/Pages/Settings.razor | 309 ++++++------ .../AssistantTextSummarizer.razor | 41 +- .../AssistantTextSummarizer.razor.cs | 14 +- .../TextSummarizer/CommonLanguagePrompts.cs | 14 - .../Translation/AssistantTranslation.razor | 42 +- .../Translation/AssistantTranslation.razor.cs | 14 +- .../Translation/CommonLanguageExtension.cs | 13 - .../Settings/ConfigurationSelectData.cs | 16 + .../Settings/DataModel/Data.cs | 240 +--------- .../Settings/DataModel/DataAgenda.cs | 59 +++ .../Settings/DataModel/DataApp.cs | 25 + .../Settings/DataModel/DataChat.cs | 19 + .../Settings/DataModel/DataCoding.cs | 31 ++ .../Settings/DataModel/DataIconFinder.cs | 21 + .../DataModel/DataTextContentCleaner.cs | 14 + .../Settings/DataModel/DataTextSummarizer.cs | 53 ++ .../Settings/DataModel/DataTranslation.cs | 51 ++ .../Settings/DataModel/DataWorkspace.cs | 14 + .../DataModel/PreviousModels/DataV1V3.cs | 247 ++++++++++ .../Settings/SettingsManager.cs | 32 +- .../Settings/SettingsMigrations.cs | 141 +++++- app/MindWork AI Studio/Settings/Version.cs | 1 + .../Tools/CommonLanguageExtensions.cs | 23 + .../Tools/TemporaryChatService.cs | 4 +- app/MindWork AI Studio/Tools/UpdateService.cs | 4 +- .../wwwroot/changelog/v0.8.6.md | 3 +- .../wwwroot/changelog/v0.8.7.md | 16 +- metadata.txt | 10 +- runtime/Cargo.lock | 2 +- runtime/Cargo.toml | 2 +- runtime/tauri.conf.json | 2 +- 60 files changed, 1873 insertions(+), 582 deletions(-) create mode 100644 app/MindWork AI Studio/Components/Blocks/EnumSelection.razor create mode 100644 app/MindWork AI Studio/Components/Blocks/EnumSelection.razor.cs create mode 100644 app/MindWork AI Studio/Components/Blocks/EnumSelectionBase.cs create mode 100644 app/MindWork AI Studio/Components/Blocks/MudTextSlider.razor create mode 100644 app/MindWork AI Studio/Components/Blocks/MudTextSlider.razor.cs create mode 100644 app/MindWork AI Studio/Components/Blocks/MudTextSwitch.razor create mode 100644 app/MindWork AI Studio/Components/Blocks/MudTextSwitch.razor.cs create mode 100644 app/MindWork AI Studio/Components/Blocks/ProcessComponent.razor create mode 100644 app/MindWork AI Studio/Components/Blocks/ProcessComponent.razor.cs create mode 100644 app/MindWork AI Studio/Components/Blocks/ProviderSelection.razor create mode 100644 app/MindWork AI Studio/Components/Blocks/ProviderSelection.razor.cs create mode 100644 app/MindWork AI Studio/Components/Pages/Agenda/AssistantAgenda.razor create mode 100644 app/MindWork AI Studio/Components/Pages/Agenda/AssistantAgenda.razor.cs create mode 100644 app/MindWork AI Studio/Components/Pages/Agenda/NumberParticipants.cs create mode 100644 app/MindWork AI Studio/Components/Pages/Agenda/NumberParticipantsExtensions.cs delete mode 100644 app/MindWork AI Studio/Components/Pages/TextSummarizer/CommonLanguagePrompts.cs delete mode 100644 app/MindWork AI Studio/Components/Pages/Translation/CommonLanguageExtension.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataAgenda.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataApp.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataChat.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataCoding.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataIconFinder.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataTextContentCleaner.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataTextSummarizer.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataTranslation.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/DataWorkspace.cs create mode 100644 app/MindWork AI Studio/Settings/DataModel/PreviousModels/DataV1V3.cs diff --git a/app/MindWork AI Studio/Chat/ContentText.cs b/app/MindWork AI Studio/Chat/ContentText.cs index f125d4b..0354c75 100644 --- a/app/MindWork AI Studio/Chat/ContentText.cs +++ b/app/MindWork AI Studio/Chat/ContentText.cs @@ -70,7 +70,7 @@ public sealed class ContentText : IContent // Notify the UI that the content has changed, // depending on the energy saving mode: var now = DateTimeOffset.Now; - switch (settings.ConfigurationData.IsSavingEnergy) + switch (settings.ConfigurationData.App.IsSavingEnergy) { // Energy saving mode is off. We notify the UI // as fast as possible -- no matter the odds: diff --git a/app/MindWork AI Studio/Components/Blocks/Changelog.Logs.cs b/app/MindWork AI Studio/Components/Blocks/Changelog.Logs.cs index 833794a..a5a4d52 100644 --- a/app/MindWork AI Studio/Components/Blocks/Changelog.Logs.cs +++ b/app/MindWork AI Studio/Components/Blocks/Changelog.Logs.cs @@ -13,6 +13,7 @@ public partial class Changelog public static readonly Log[] LOGS = [ + new (169, "v0.8.7, build 169 (2024-08-01 19:08 UTC)", "v0.8.7.md"), new (168, "v0.8.6, build 168 (2024-08-01 19:50 UTC)", "v0.8.6.md"), new (167, "v0.8.5, build 167 (2024-07-28 16:44 UTC)", "v0.8.5.md"), new (166, "v0.8.4, build 166 (2024-07-26 06:53 UTC)", "v0.8.4.md"), diff --git a/app/MindWork AI Studio/Components/Blocks/ConfigurationSlider.razor.cs b/app/MindWork AI Studio/Components/Blocks/ConfigurationSlider.razor.cs index 0df46f3..238aad3 100644 --- a/app/MindWork AI Studio/Components/Blocks/ConfigurationSlider.razor.cs +++ b/app/MindWork AI Studio/Components/Blocks/ConfigurationSlider.razor.cs @@ -42,10 +42,35 @@ public partial class ConfigurationSlider : ConfigurationBase where T : struct [Parameter] public Action ValueUpdate { get; set; } = _ => { }; + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + await this.EnsureMinMax(); + await base.OnInitializedAsync(); + } + + protected override async Task OnParametersSetAsync() + { + await this.EnsureMinMax(); + await base.OnParametersSetAsync(); + } + + #endregion + private async Task OptionChanged(T updatedValue) { this.ValueUpdate(updatedValue); await this.SettingsManager.StoreSettings(); await this.InformAboutChange(); } + + private async Task EnsureMinMax() + { + if (this.Value() < this.Min) + await this.OptionChanged(this.Min); + + else if(this.Value() > this.Max) + await this.OptionChanged(this.Max); + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/EnumSelection.razor b/app/MindWork AI Studio/Components/Blocks/EnumSelection.razor new file mode 100644 index 0000000..144d0ea --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/EnumSelection.razor @@ -0,0 +1,17 @@ +@typeparam T +@inherits EnumSelectionBase + + + + @foreach (var value in Enum.GetValues()) + { + + @this.NameFunc(value) + + } + + @if (this.AllowOther && this.Value.Equals(this.OtherValue)) + { + + } + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/EnumSelection.razor.cs b/app/MindWork AI Studio/Components/Blocks/EnumSelection.razor.cs new file mode 100644 index 0000000..d87384f --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/EnumSelection.razor.cs @@ -0,0 +1,79 @@ +using AIStudio.Settings; + +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components.Blocks; + +public partial class EnumSelection : EnumSelectionBase where T : struct, Enum +{ + [Parameter] + public T Value { get; set; } + + [Parameter] + public EventCallback ValueChanged { get; set; } + + [Parameter] + public bool AllowOther { get; set; } + + [Parameter] + public T OtherValue { get; set; } + + [Parameter] + public string OtherInput { get; set; } = string.Empty; + + [Parameter] + public EventCallback OtherInputChanged { get; set; } + + [Parameter] + public string Label { get; set; } = string.Empty; + + [Parameter] + public string LabelOther { get; set; } = "Other"; + + [Parameter] + public Func ValidateSelection { get; set; } = _ => null; + + [Parameter] + public Func ValidateOther { get; set; } = _ => null; + + [Parameter] + public string Icon { get; set; } = Icons.Material.Filled.ArrowDropDown; + + /// + /// Gets or sets the custom name function for selecting the display name of an enum value. + /// + /// The enum type. + /// The enum value. + /// The display name of the enum value. + [Parameter] + public Func NameFunc { get; set; } = value => value.ToString(); + + [Parameter] + public Func SelectionUpdated { get; set; } = _ => Task.CompletedTask; + + [Inject] + private SettingsManager SettingsManager { get; set; } = null!; + + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + // Configure the spellchecking for the user input: + this.SettingsManager.InjectSpellchecking(USER_INPUT_ATTRIBUTES); + await base.OnInitializedAsync(); + } + + #endregion + + private async Task SelectionChanged(T value) + { + await this.ValueChanged.InvokeAsync(value); + await this.SelectionUpdated(value); + } + + private async Task OtherValueChanged(string value) + { + await this.OtherInputChanged.InvokeAsync(value); + await this.SelectionUpdated(this.Value); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/EnumSelectionBase.cs b/app/MindWork AI Studio/Components/Blocks/EnumSelectionBase.cs new file mode 100644 index 0000000..f84478d --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/EnumSelectionBase.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components.Blocks; + +public abstract class EnumSelectionBase : ComponentBase +{ + protected static readonly Dictionary USER_INPUT_ATTRIBUTES = new(); +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/MudTextSlider.razor b/app/MindWork AI Studio/Components/Blocks/MudTextSlider.razor new file mode 100644 index 0000000..3c95b8d --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/MudTextSlider.razor @@ -0,0 +1,7 @@ +@typeparam T + + + + @this.Value @this.Unit + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/MudTextSlider.razor.cs b/app/MindWork AI Studio/Components/Blocks/MudTextSlider.razor.cs new file mode 100644 index 0000000..c3e2411 --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/MudTextSlider.razor.cs @@ -0,0 +1,78 @@ +using System.Numerics; + +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components.Blocks; + +public partial class MudTextSlider : ComponentBase where T : struct, INumber +{ + /// + /// The minimum value for the slider. + /// + [Parameter] + public T Min { get; set; } = T.Zero; + + /// + /// The maximum value for the slider. + /// + [Parameter] + public T Max { get; set; } = T.One; + + /// + /// The step size for the slider. + /// + [Parameter] + public T Step { get; set; } = T.One; + + /// + /// The unit to display next to the slider's value. + /// + [Parameter] + public string Unit { get; set; } = string.Empty; + + [Parameter] + public T Value { get; set; } + + [Parameter] + public EventCallback ValueChanged { get; set; } + + /// + /// The label to display above the slider. + /// + [Parameter] + public string Label { get; set; } = string.Empty; + + [Parameter] + public Func Disabled { get; set; } = () => false; + + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + await this.EnsureMinMax(); + await base.OnInitializedAsync(); + } + + protected override async Task OnParametersSetAsync() + { + await this.EnsureMinMax(); + await base.OnParametersSetAsync(); + } + + #endregion + + private async Task EnsureMinMax() + { + if (this.Value < this.Min) + await this.ValueUpdated(this.Min); + + else if(this.Value > this.Max) + await this.ValueUpdated(this.Max); + } + + private async Task ValueUpdated(T value) + { + this.Value = value; + await this.ValueChanged.InvokeAsync(this.Value); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/MudTextSwitch.razor b/app/MindWork AI Studio/Components/Blocks/MudTextSwitch.razor new file mode 100644 index 0000000..353ac8b --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/MudTextSwitch.razor @@ -0,0 +1,5 @@ + + + @(this.Value ? this.LabelOn : this.LabelOff) + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/MudTextSwitch.razor.cs b/app/MindWork AI Studio/Components/Blocks/MudTextSwitch.razor.cs new file mode 100644 index 0000000..30492d3 --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/MudTextSwitch.razor.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components.Blocks; + +public partial class MudTextSwitch : ComponentBase +{ + [Parameter] + public string Label { get; set; } = string.Empty; + + [Parameter] + public bool Disabled { get; set; } + + [Parameter] + public bool Value { get; set; } + + [Parameter] + public EventCallback ValueChanged { get; set; } + + [Parameter] + public Color Color { get; set; } = Color.Primary; + + [Parameter] + public Func Validation { get; set; } = _ => null; + + [Parameter] + public string LabelOn { get; set; } = string.Empty; + + [Parameter] + public string LabelOff { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/ProcessComponent.razor b/app/MindWork AI Studio/Components/Blocks/ProcessComponent.razor new file mode 100644 index 0000000..54d61e9 --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/ProcessComponent.razor @@ -0,0 +1,11 @@ +@typeparam T + +@if (this.ShowProgressAnimation) +{ +
+ +
+} +
+ +
\ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/ProcessComponent.razor.cs b/app/MindWork AI Studio/Components/Blocks/ProcessComponent.razor.cs new file mode 100644 index 0000000..6d71132 --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/ProcessComponent.razor.cs @@ -0,0 +1,16 @@ +using AIStudio.Tools; + +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components.Blocks; + +public partial class ProcessComponent : ComponentBase where T : struct, Enum +{ + [Parameter] + public bool ShowProgressAnimation { get; set; } + + [Parameter] + public ProcessStepValue StepValue { get; set; } + + private readonly Process process = Process.INSTANCE; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/ProviderSelection.razor b/app/MindWork AI Studio/Components/Blocks/ProviderSelection.razor new file mode 100644 index 0000000..aebe6e5 --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/ProviderSelection.razor @@ -0,0 +1,8 @@ +@using AIStudio.Settings + + + @foreach (var provider in this.SettingsManager.ConfigurationData.Providers) + { + + } + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/ProviderSelection.razor.cs b/app/MindWork AI Studio/Components/Blocks/ProviderSelection.razor.cs new file mode 100644 index 0000000..96204d0 --- /dev/null +++ b/app/MindWork AI Studio/Components/Blocks/ProviderSelection.razor.cs @@ -0,0 +1,26 @@ +using AIStudio.Settings; + +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components.Blocks; + +public partial class ProviderSelection : ComponentBase +{ + [Parameter] + public Settings.Provider ProviderSettings { get; set; } + + [Parameter] + public EventCallback ProviderSettingsChanged { get; set; } + + [Parameter] + public Func ValidateProvider { get; set; } = _ => null; + + [Inject] + protected SettingsManager SettingsManager { get; set; } = null!; + + private async Task SelectionChanged(Settings.Provider provider) + { + this.ProviderSettings = provider; + await this.ProviderSettingsChanged.InvokeAsync(provider); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/ReadWebContent.razor b/app/MindWork AI Studio/Components/Blocks/ReadWebContent.razor index 8b33a12..1d83309 100644 --- a/app/MindWork AI Studio/Components/Blocks/ReadWebContent.razor +++ b/app/MindWork AI Studio/Components/Blocks/ReadWebContent.razor @@ -1,17 +1,8 @@ - - - @(this.showWebContentReader ? "Show web content options" : "Hide web content options") - - - + @if (this.showWebContentReader) { - - - @(this.useContentCleanerAgent ? "The content is cleaned using an LLM agent: the main content is extracted, advertisements and other irrelevant things are attempted to be removed; relative links are attempted to be converted into absolute links so that they can be used." : "No content cleaning") - - + @@ -20,12 +11,7 @@ @if (this.AgentIsRunning) { -
- -
-
- -
+ } }
\ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Blocks/ReadWebContent.razor.cs b/app/MindWork AI Studio/Components/Blocks/ReadWebContent.razor.cs index 56cbd60..c4a3497 100644 --- a/app/MindWork AI Studio/Components/Blocks/ReadWebContent.razor.cs +++ b/app/MindWork AI Studio/Components/Blocks/ReadWebContent.razor.cs @@ -17,10 +17,7 @@ public partial class ReadWebContent : ComponentBase [Inject] protected SettingsManager SettingsManager { get; set; } = null!; - - [Inject] - protected IJSRuntime JsRuntime { get; init; } = null!; - + [Parameter] public string Content { get; set; } = string.Empty; @@ -63,8 +60,8 @@ public partial class ReadWebContent : ComponentBase if(this.PreselectContentCleanerAgent) this.useContentCleanerAgent = true; - if (this.SettingsManager.ConfigurationData.PreselectAgentTextContentCleanerOptions) - this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.PreselectedAgentTextContentCleanerProvider); + if (this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions) + this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider); else this.providerSettings = this.ProviderSettings; @@ -73,7 +70,7 @@ public partial class ReadWebContent : ComponentBase protected override async Task OnParametersSetAsync() { - if (!this.SettingsManager.ConfigurationData.PreselectAgentTextContentCleanerOptions) + if (!this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions) this.providerSettings = this.ProviderSettings; await base.OnParametersSetAsync(); diff --git a/app/MindWork AI Studio/Components/Layout/MainLayout.razor b/app/MindWork AI Studio/Components/Layout/MainLayout.razor index c7044e7..63c4a46 100644 --- a/app/MindWork AI Studio/Components/Layout/MainLayout.razor +++ b/app/MindWork AI Studio/Components/Layout/MainLayout.razor @@ -6,11 +6,11 @@ @if (!this.performingUpdate) { - + @foreach (var navBarItem in NAV_ITEMS) { - if (this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.NEVER_EXPAND_USE_TOOLTIPS) + if (this.SettingsManager.ConfigurationData.App.NavigationBehavior is NavBehavior.NEVER_EXPAND_USE_TOOLTIPS) { @navBarItem.Name diff --git a/app/MindWork AI Studio/Components/Layout/MainLayout.razor.cs b/app/MindWork AI Studio/Components/Layout/MainLayout.razor.cs index 8bd60a9..abc206c 100644 --- a/app/MindWork AI Studio/Components/Layout/MainLayout.razor.cs +++ b/app/MindWork AI Studio/Components/Layout/MainLayout.razor.cs @@ -89,7 +89,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, IDis TemporaryChatService.Initialize(); // Should the navigation bar be open by default? - if(this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.ALWAYS_EXPAND) + if(this.SettingsManager.ConfigurationData.App.NavigationBehavior is NavBehavior.ALWAYS_EXPAND) this.navBarOpen = true; await base.OnInitializedAsync(); @@ -121,7 +121,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, IDis break; case Event.CONFIGURATION_CHANGED: - if(this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.ALWAYS_EXPAND) + if(this.SettingsManager.ConfigurationData.App.NavigationBehavior is NavBehavior.ALWAYS_EXPAND) this.navBarOpen = true; else this.navBarOpen = false; diff --git a/app/MindWork AI Studio/Components/Pages/Agenda/AssistantAgenda.razor b/app/MindWork AI Studio/Components/Pages/Agenda/AssistantAgenda.razor new file mode 100644 index 0000000..5674dbf --- /dev/null +++ b/app/MindWork AI Studio/Components/Pages/Agenda/AssistantAgenda.razor @@ -0,0 +1,56 @@ +@page "/assistant/agenda" +@using AIStudio.Tools +@inherits AssistantBaseCore + + + + + + @foreach (var contentLine in this.contentLines) + { + @if(!this.justBriefly.Contains(contentLine)) + { + @contentLine + } + } + + + + @foreach (var contentLine in this.contentLines) + { + @if(!this.selectedFoci.Contains(contentLine)) + { + @contentLine + } + } + + + + + + + + + + + +@if (!this.isMeetingVirtual) +{ + + + + + + + + + + +} + + + + + + Create agenda + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/Agenda/AssistantAgenda.razor.cs b/app/MindWork AI Studio/Components/Pages/Agenda/AssistantAgenda.razor.cs new file mode 100644 index 0000000..ba67907 --- /dev/null +++ b/app/MindWork AI Studio/Components/Pages/Agenda/AssistantAgenda.razor.cs @@ -0,0 +1,452 @@ +using System.Text; + +using AIStudio.Tools; + +namespace AIStudio.Components.Pages.Agenda; + +public partial class AssistantAgenda : AssistantBaseCore +{ + protected override string Title => "Agenda Planner"; + + protected override string Description => + """ + This agenda planner helps you create a structured agenda for your meeting or seminar. Just provide some basic + information about the event, and the assistant will generate an agenda for you. You can also specify the + duration, the start time, the location, the target language, and other details. + """; + + protected override string SystemPrompt => + $""" + You are a friendly assistant who supports the planning and consultation of events. You receive + metadata about an event and create an agenda from it. Additionally, you provide advice on what + the organizer and moderator should consider. When creating the agenda, you take into account that + time for questions and discussions needs to be scheduled. For large events, you take into account + the logistical challenges that come with an increasing number of participants. + + If the user is planning interactions with participants, you know various methods. For example: + + - **Townhall Meeting**: An open assembly where participants can ask questions and provide feedback directly to leaders or speakers. Good moderation is necessary to queue contributions and hand the floor to the respective person. Additionally, one person should take notes visible to all. Ideally, this should not be the moderator. + + - **Speed Dating**: Short, structured interaction rounds where participants get the chance to quickly introduce themselves and make initial connections. A long row of tables is needed so that two people can sit opposite each other. A moderator with a stopwatch must ensure that participants rotate and change seats every 3 to 5 minutes. + + - **World Café**: Participants discuss in small groups at tables and rotate after set intervals to exchange thoughts and develop ideas further. Each table needs a host. Notes should be taken on a flipchart or digitally at each table. At the end, the table hosts could present their insights to all participants in a plenary session. + + - **Fishbowl**: A group discusses in an inner circle while a larger group listens from the outside. Occasionally, listeners can move into the inner circle to actively participate. + + - **BarCamp (Unconference)**: Participants contribute to part of the agenda themselves and can act as both presenters and listeners. Anyone can propose and lead a session. However, there should be initial moderation to guide this meta-process. + + - **Open Space Technology**: A method for large groups where participants bring up their own topics and then work intensively in small groups. At the end, the groups can present their findings to all participants in a plenary session. + + - **Panel Discussion**: A group of experts discusses a specific topic in front of an audience, followed by a question-and-answer session. + + - **Breakout Sessions**: Larger groups are divided into smaller, topic-related groups to discuss specific issues more deeply and interactively. + + - **Interactive Polling**: Real-time surveys during the meeting or seminar using digital technology to collect immediate feedback from participants. With an increasing number of participants, technical requirements also become more complex: not every Wi-Fi router can handle several hundred or thousand devices. Additionally, the moderator or speaker must have a stable network connection to display the results. It would be problematic if the speaker depends on the same Wi-Fi as the participants: if the Wi-Fi crashes due to the high number of participants, the speaker cannot show the results. Therefore, a LAN for the speaker or the use of a mobile hotspot would be a better choice. + + - **Peer Learning Groups**: Small groups of participants work together to learn from each other and collaboratively develop solutions for specific challenges. + + - **Role Play/Simulation**: Participants take on roles to simulate certain scenarios, gaining practical experience and promoting dynamic discussions. + + - **Round Table Discussions**: Small group discussions on specific topics, often without formal moderation, to encourage open and equal dialogue. + + - **Mind Mapping**: A method for visualizing ideas and concepts, which can foster creative exchange within groups. + + - **Case Study Analysis**: Groups analyze real or hypothetical case studies and present their solutions or insights. + + - **Silent Meeting/Writing**: Participants write down their thoughts and questions, which are then collected and discussed to balance out loud or dominant voices. + + - **Debate**: Participants argue for or against a specific topic, often with a moderator who ensures that the discussion remains constructive. + + - **Workshops**: Interactive sessions where participants work together on specific tasks or challenges. + + - **Brainstorming**: A method for generating ideas in a group setting, often with a focus on quantity and creativity. + + - **Design Thinking**: A structured approach to innovation solutions. Design thinking is structured in six phases: understand, observe, point of view, ideate, prototype, and test. Depending on the number of participants, there are two moderates needed. One moderator leads the process, the other supports the participants in their work. Design thinking may takes up to two days. + + You output the agenda in the following Markdown format: + + # [Agenda Title] + - 09:00 - 09:05 (5 minutes): Welcome + - 09:05 - 09:15 (10 minutes): Introduction + - ... + {this.SystemPromptSocialActivity()} + {this.SystemPromptDinner()} + + # Organizational notes + [Your advice for the organizer goes here, like room setup, technical requirements, etc.] + + # Moderation notes + [Your advice for the moderator goes here] + + Output the agenda in the following language: {this.PromptLanguage()}. + """; + + private const string PLACEHOLDER_CONTENT = """ + - Project status + - We need to discuss how to proceed + - Problem solving in work package 3 possible? + - Concerns of the members + """; + + private const string PLACEHOLDER_WHO_IS_PRESENTING = """ + - John Doe: Project status + - Mary Jane: Work package 3 + """; + + private string inputTopic = string.Empty; + private string inputName = string.Empty; + private string inputContent = string.Empty; + private string inputDuration = string.Empty; + private string inputStartTime = string.Empty; + private IEnumerable selectedFoci = new HashSet(); + private IEnumerable justBriefly = new HashSet(); + private string inputObjective = string.Empty; + private string inputModerator = string.Empty; + private CommonLanguages selectedTargetLanguage; + private string customTargetLanguage = string.Empty; + private bool introduceParticipants; + private bool isMeetingVirtual = true; + private string inputLocation = string.Empty; + private bool goingToDinner; + private bool doingSocialActivity; + private bool needToArriveAndDepart; + private int durationLunchBreak; + private int durationBreaks; + private bool activeParticipation; + private NumberParticipants numberParticipants; + private string inputWhoIsPresenting = string.Empty; + + private readonly List contentLines = []; + + #region Overrides of ComponentBase + + protected override async Task OnInitializedAsync() + { + if (this.SettingsManager.ConfigurationData.Agenda.PreselectOptions) + { + this.inputTopic = this.SettingsManager.ConfigurationData.Agenda.PreselectTopic; + this.inputName = this.SettingsManager.ConfigurationData.Agenda.PreselectName; + this.inputDuration = this.SettingsManager.ConfigurationData.Agenda.PreselectDuration; + this.inputStartTime = this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime; + this.inputObjective = this.SettingsManager.ConfigurationData.Agenda.PreselectObjective; + this.inputModerator = this.SettingsManager.ConfigurationData.Agenda.PreselectModerator; + this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage; + this.customTargetLanguage = this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage; + this.introduceParticipants = this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants; + this.isMeetingVirtual = this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual; + this.inputLocation = this.SettingsManager.ConfigurationData.Agenda.PreselectLocation; + this.goingToDinner = this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner; + this.doingSocialActivity = this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity; + this.needToArriveAndDepart = this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart; + this.durationLunchBreak = this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime; + this.durationBreaks = this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime; + this.activeParticipation = this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation; + this.numberParticipants = this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants; + this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider); + } + + await base.OnInitializedAsync(); + } + + #endregion + + private void OnContentChanged(string content) + { + var previousSelectedFoci = new HashSet(); + var previousJustBriefly = new HashSet(); + + this.contentLines.Clear(); + foreach (var line in content.AsSpan().EnumerateLines()) + { + var trimmedLine = line.Trim(); + if (trimmedLine.StartsWith("-")) + trimmedLine = trimmedLine[1..].Trim(); + + if (trimmedLine.Length == 0) + continue; + + var finalLine = trimmedLine.ToString(); + if(this.selectedFoci.Any(x => x.StartsWith(finalLine, StringComparison.InvariantCultureIgnoreCase))) + previousSelectedFoci.Add(finalLine); + + if(this.justBriefly.Any(x => x.StartsWith(finalLine, StringComparison.InvariantCultureIgnoreCase))) + previousJustBriefly.Add(finalLine); + + this.contentLines.Add(finalLine); + } + + this.selectedFoci = previousSelectedFoci; + this.justBriefly = previousJustBriefly; + } + + private string? ValidateLocation(string location) + { + if(!this.isMeetingVirtual && string.IsNullOrWhiteSpace(location)) + return "Please provide a location for the meeting or the seminar."; + + return null; + } + + private string? ValidateNumberParticipants(NumberParticipants selectedSize) + { + if(selectedSize is NumberParticipants.NOT_SPECIFIED) + return "Please select the number of participants."; + + return null; + } + + private string? ValidateTargetLanguage(CommonLanguages language) + { + if(language is CommonLanguages.AS_IS) + return "Please select a target language for the agenda."; + + return null; + } + + private string? ValidateDuration(string duration) + { + if(string.IsNullOrWhiteSpace(duration)) + return "Please provide a duration for the meeting or the seminar, e.g. '2 hours', or '2 days (8 hours and 4 hours)', etc."; + + return null; + } + + private string? ValidateStartTime(string startTime) + { + if(string.IsNullOrWhiteSpace(startTime)) + return "Please provide a start time for the meeting or the seminar. When the meeting is a multi-day event, specify the start time for each day, e.g. '9:00 AM, 10:00 AM', etc."; + + 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? ValidateTopic(string topic) + { + if(string.IsNullOrWhiteSpace(topic)) + return "Please provide a topic for the agenda. What is the meeting or the seminar about?"; + + return null; + } + + private string? ValidateName(string name) + { + if(string.IsNullOrWhiteSpace(name)) + return "Please provide a name for the meeting or the seminar."; + + return null; + } + + private string? ValidateContent(string content) + { + if(string.IsNullOrWhiteSpace(content)) + return "Please provide some content for the agenda. What are the main points of the meeting or the seminar?"; + + var lines = content.Split('\n'); + foreach (var line in lines) + if(!line.TrimStart().StartsWith('-')) + return "Please start each line of your content list with a dash (-) to create a bullet point list."; + + return null; + } + + private string? ValidateObjective(string objective) + { + if(string.IsNullOrWhiteSpace(objective)) + return "Please provide an objective for the meeting or the seminar. What do you want to achieve?"; + + return null; + } + + private string? ValidateModerator(string moderator) + { + if(string.IsNullOrWhiteSpace(moderator)) + return "Please provide a moderator for the meeting or the seminar. Who will lead the discussion?"; + + return null; + } + + private async Task CreateAgenda() + { + await this.form!.Validate(); + if (!this.inputIsValid) + return; + + this.CreateChatThread(); + var time = this.AddUserRequest( + $""" + Create an agenda for the meeting or seminar wit the title '{this.inputName}' using the following details: + + - The overall topic is '{this.inputTopic}'. + - The objective of the meeting is '{this.inputObjective}'. + - The moderator is '{this.inputModerator}'. + - The planned duration is '{this.inputDuration}'. + - The planned start time is '{this.inputStartTime}'. + {this.PromptGettingToKnowEachOther()} + - The number of participants is '{this.numberParticipants.Name()}'. + {this.PromptActiveParticipation()} + {this.PromptVirtualMeeting()} + {this.PromptPhysicalMeeting()} + + Here is draft what was planned for the meeting: + {this.inputContent} + + Please do not follow this draft strictly. It is just a suggestion. + {this.PromptFoci()} + {this.PromptBriefly()} + {this.PromptWhoIsPresenting()} + """); + + await this.AddAIResponseAsync(time); + } + + private string PromptLanguage() + { + if(this.selectedTargetLanguage is CommonLanguages.OTHER) + return this.customTargetLanguage; + + return this.selectedTargetLanguage.Name(); + } + + private string PromptPhysicalMeeting() + { + if(this.isMeetingVirtual) + return string.Empty; + + return $""" + - The meeting takes place at the following location: '{this.inputLocation}'. + {this.PromptJoiningDinner()} + {this.PromptSocialActivity()} + {this.PromptArriveAndDepart()} + - In case a lunch break is necessary, the break should about {this.durationLunchBreak} minutes long. + - In case any breaks are necessary, the breaks should be about {this.durationBreaks} minutes long. + """; + } + + private string PromptArriveAndDepart() + { + if (this.needToArriveAndDepart) + return "- The participants should have time to arrive and depart."; + + return "- The participants do not need to arrive and depart."; + } + + private string PromptSocialActivity() + { + if (this.doingSocialActivity) + return "- The participants will engage in a social activity after the meeting or seminar. This can be a team-building exercise, a sightseeing tour, or a visit to a local attraction. Please make a recommendation for an activity at '{this.inputLocation}'."; + + return "- The participants will not engage in a social activity after the meeting or seminar."; + } + + private string SystemPromptSocialActivity() + { + if(this.doingSocialActivity) + return """ + - 16:00 Departure to the social event [Consider the time needed to get to the location]. + - 17:00 [Insert your advice for the social activity here]. + """; + + return string.Empty; + } + + private string SystemPromptDinner() + { + if(this.goingToDinner) + return """ + - 19:00 Departure to the restaurant [Consider the time needed to get to the restaurant]. + - 20:00 [Insert your advice for the dinner here.]. + """; + + return string.Empty; + } + + private string PromptJoiningDinner() + { + if (this.goingToDinner) + return $"- The participants will join for a dinner after the meeting or seminar. Please make a recommendation for a restaurant at '{this.inputLocation}'."; + + return "- The participants will not join for a dinner after the meeting or seminar."; + } + + private string PromptVirtualMeeting() + { + if (this.isMeetingVirtual) + return "- The meeting or seminar will be held virtually, e.g, a call or webinar. The participants will join online."; + + return "- The meeting or seminar will be held in person."; + } + + private string PromptActiveParticipation() + { + if (this.activeParticipation) + return "- The participants should actively participate in the meeting or seminar. This can be done through discussions, questions, and contributions to the content."; + + return "- The participants do not need to actively participate."; + } + + private string PromptGettingToKnowEachOther() + { + if (this.introduceParticipants) + return "- The participants should introduce themselves to get to know each other. This can be done in a round or in pairs. The moderator should ensure that everyone has the opportunity to speak."; + + return "- The participants do not need to introduce themselves."; + } + + private string PromptFoci() + { + if (this.selectedFoci.Any()) + { + return $""" + + Out of this content, the following points should be focused on: + {this.ConvertItemsToMarkdown(this.selectedFoci)} + """; + } + + return string.Empty; + } + + private string PromptBriefly() + { + if (this.justBriefly.Any()) + { + return $""" + + The following points should be just briefly mentioned: + {this.ConvertItemsToMarkdown(this.justBriefly)} + """; + } + + return string.Empty; + } + + private string PromptWhoIsPresenting() + { + if (!string.IsNullOrWhiteSpace(this.inputWhoIsPresenting)) + { + return $""" + + The following persons will present the content: + {this.inputWhoIsPresenting} + """; + } + + return string.Empty; + } + + private string ConvertItemsToMarkdown(IEnumerable items) + { + var markdown = new StringBuilder(); + foreach (var item in items) + markdown.AppendLine($"- {item}"); + + return markdown.ToString(); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/Agenda/NumberParticipants.cs b/app/MindWork AI Studio/Components/Pages/Agenda/NumberParticipants.cs new file mode 100644 index 0000000..7e0e99e --- /dev/null +++ b/app/MindWork AI Studio/Components/Pages/Agenda/NumberParticipants.cs @@ -0,0 +1,18 @@ +namespace AIStudio.Components.Pages.Agenda; + +public enum NumberParticipants +{ + NOT_SPECIFIED, + + PEER_TO_PEER, // 2 participants + + SMALL_GROUP, // 3 - 5 participants + LARGE_GROUP, // 6 - 12 participants + MULTIPLE_SMALL_GROUPS, // 13 - 20 participants + MULTIPLE_LARGE_GROUPS, // 21 - 30 participants + + SYMPOSIUM, // 31 - 100 participants + CONFERENCE, // 101 - 200 participants + CONGRESS, // 201 - 1000 participants + LARGE_EVENT, // 1000+ participants +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/Agenda/NumberParticipantsExtensions.cs b/app/MindWork AI Studio/Components/Pages/Agenda/NumberParticipantsExtensions.cs new file mode 100644 index 0000000..f0966a2 --- /dev/null +++ b/app/MindWork AI Studio/Components/Pages/Agenda/NumberParticipantsExtensions.cs @@ -0,0 +1,24 @@ +namespace AIStudio.Components.Pages.Agenda; + +public static class NumberParticipantsExtensions +{ + public static string Name(this NumberParticipants numberParticipants) => numberParticipants switch + { + NumberParticipants.NOT_SPECIFIED => "Please select how many participants are expected", + + NumberParticipants.PEER_TO_PEER => "2 (peer to peer)", + + NumberParticipants.SMALL_GROUP => "3 - 5 (small group)", + NumberParticipants.LARGE_GROUP => "6 - 12 (large group)", + NumberParticipants.MULTIPLE_SMALL_GROUPS => "13 - 20 (multiple small groups)", + NumberParticipants.MULTIPLE_LARGE_GROUPS => "21 - 30 (multiple large groups)", + + NumberParticipants.SYMPOSIUM => "31 - 100 (symposium)", + NumberParticipants.CONFERENCE => "101 - 200 (conference)", + NumberParticipants.CONGRESS => "201 - 1,000 (congress)", + + NumberParticipants.LARGE_EVENT => "1,000+ (large event)", + + _ => "Unknown" + }; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/Assistants.razor b/app/MindWork AI Studio/Components/Pages/Assistants.razor index 3c7087b..97ad484 100644 --- a/app/MindWork AI Studio/Components/Pages/Assistants.razor +++ b/app/MindWork AI Studio/Components/Pages/Assistants.razor @@ -18,6 +18,7 @@ Business + diff --git a/app/MindWork AI Studio/Components/Pages/Chat.razor b/app/MindWork AI Studio/Components/Pages/Chat.razor index a039e2c..7decaff 100644 --- a/app/MindWork AI Studio/Components/Pages/Chat.razor +++ b/app/MindWork AI Studio/Components/Pages/Chat.razor @@ -1,6 +1,5 @@ @page "/chat" @using AIStudio.Chat -@using AIStudio.Settings @using AIStudio.Settings.DataModel @inherits MSGComponentBase @@ -16,13 +15,7 @@ } - - @foreach (var provider in this.SettingsManager.ConfigurationData.Providers) - { - - } - - + @if (this.chatThread is not null) @@ -39,14 +32,14 @@ - @if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES) + @if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES) { } - @if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY) + @if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY) { @@ -64,14 +57,14 @@ } - @if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) + @if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) { } - @if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES) + @if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES) { @@ -82,7 +75,7 @@ -@if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior != WorkspaceStorageBehavior.DISABLE_WORKSPACES) +@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior != WorkspaceStorageBehavior.DISABLE_WORKSPACES) { diff --git a/app/MindWork AI Studio/Components/Pages/Chat.razor.cs b/app/MindWork AI Studio/Components/Pages/Chat.razor.cs index 05eae50..b040d9f 100644 --- a/app/MindWork AI Studio/Components/Pages/Chat.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/Chat.razor.cs @@ -57,9 +57,9 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable // Configure the spellchecking for the user input: this.SettingsManager.InjectSpellchecking(USER_INPUT_ATTRIBUTES); - if (this.SettingsManager.ConfigurationData.PreselectChatOptions) + if (this.SettingsManager.ConfigurationData.Chat.PreselectOptions) { - this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.PreselectedChatProvider); + this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Chat.PreselectedProvider); } await base.OnInitializedAsync(); @@ -120,7 +120,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable }); // Save the chat: - if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) + if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) { await this.SaveThread(); this.hasUnsavedChanges = false; @@ -160,7 +160,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(), this.JsRuntime, this.SettingsManager, this.providerSettings.Model, this.chatThread); // Save the chat: - if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) + if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) { await this.SaveThread(); this.hasUnsavedChanges = false; @@ -183,7 +183,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable var isModifier = keyEvent.AltKey || keyEvent.CtrlKey || keyEvent.MetaKey || keyEvent.ShiftKey; // Depending on the user's settings, might react to shortcuts: - switch (this.SettingsManager.ConfigurationData.ShortcutSendBehavior) + switch (this.SettingsManager.ConfigurationData.Chat.ShortcutSendBehavior) { case SendBehavior.ENTER_IS_SENDING: if (!isModifier && isEnter) @@ -232,7 +232,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable private async Task StartNewChat(bool useSameWorkspace = false, bool deletePreviousChat = false) { - if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges) + if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges) { var dialogParameters = new DialogParameters { @@ -294,7 +294,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable if(this.workspaces is null) return; - if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges) + if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges) { var confirmationDialogParameters = new DialogParameters { @@ -385,7 +385,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable switch (triggeredEvent) { case Event.HAS_CHAT_UNSAVED_CHANGES: - if(this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) + if(this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) return Task.FromResult((TResult?) (object) false); return Task.FromResult((TResult?)(object)this.hasUnsavedChanges); @@ -400,7 +400,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable public async ValueTask DisposeAsync() { - if(this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) + if(this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY) { await this.SaveThread(); this.hasUnsavedChanges = false; diff --git a/app/MindWork AI Studio/Components/Pages/Coding/AssistantCoding.razor b/app/MindWork AI Studio/Components/Pages/Coding/AssistantCoding.razor index 2f9af4b..9d11034 100644 --- a/app/MindWork AI Studio/Components/Pages/Coding/AssistantCoding.razor +++ b/app/MindWork AI Studio/Components/Pages/Coding/AssistantCoding.razor @@ -1,5 +1,4 @@ @page "/assistant/coding" -@using AIStudio.Settings @inherits AssistantBaseCore @@ -16,9 +15,7 @@ - - @(this.provideCompilerMessages ? "Provide compiler messages" : "Provide no compiler messages") - + @if (this.provideCompilerMessages) { @@ -26,13 +23,7 @@ - - - @foreach (var provider in this.SettingsManager.ConfigurationData.Providers) - { - - } - + Get support diff --git a/app/MindWork AI Studio/Components/Pages/Coding/AssistantCoding.razor.cs b/app/MindWork AI Studio/Components/Pages/Coding/AssistantCoding.razor.cs index b4e5057..f0e552e 100644 --- a/app/MindWork AI Studio/Components/Pages/Coding/AssistantCoding.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/Coding/AssistantCoding.razor.cs @@ -33,10 +33,10 @@ public partial class AssistantCoding : AssistantBaseCore protected override async Task OnInitializedAsync() { - if (this.SettingsManager.ConfigurationData.PreselectCodingOptions) + if (this.SettingsManager.ConfigurationData.Coding.PreselectOptions) { - this.provideCompilerMessages = this.SettingsManager.ConfigurationData.PreselectCodingCompilerMessages; - this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.PreselectedCodingProvider); + this.provideCompilerMessages = this.SettingsManager.ConfigurationData.Coding.PreselectCompilerMessages; + this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Coding.PreselectedProvider); } await base.OnInitializedAsync(); @@ -68,8 +68,8 @@ public partial class AssistantCoding : AssistantBaseCore this.codingContexts.Add(new() { Id = $"Context {this.codingContexts.Count + 1}", - Language = this.SettingsManager.ConfigurationData.PreselectCodingOptions ? this.SettingsManager.ConfigurationData.PreselectedCodingLanguage : default, - OtherLanguage = this.SettingsManager.ConfigurationData.PreselectCodingOptions ? this.SettingsManager.ConfigurationData.PreselectedCodingOtherLanguage : string.Empty, + Language = this.SettingsManager.ConfigurationData.Coding.PreselectOptions ? this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage : default, + OtherLanguage = this.SettingsManager.ConfigurationData.Coding.PreselectOptions ? this.SettingsManager.ConfigurationData.Coding.PreselectedOtherProgrammingLanguage : string.Empty, }); } diff --git a/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor index 02a5993..97dc5bc 100644 --- a/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor +++ b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor @@ -1,5 +1,4 @@ @page "/assistant/icons" -@using AIStudio.Settings @inherits AssistantBaseCore @@ -16,13 +15,7 @@ Open website } - - - @foreach (var provider in this.SettingsManager.ConfigurationData.Providers) - { - - } - + Find icon diff --git a/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs index a2cf367..d1f54e5 100644 --- a/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/IconFinder/AssistantIconFinder.razor.cs @@ -9,10 +9,10 @@ public partial class AssistantIconFinder : AssistantBaseCore protected override async Task OnInitializedAsync() { - if (this.SettingsManager.ConfigurationData.PreselectIconOptions) + if (this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions) { - this.selectedIconSource = this.SettingsManager.ConfigurationData.PreselectedIconSource; - this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.PreselectedIconProvider); + this.selectedIconSource = this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource; + this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider); } await base.OnInitializedAsync(); diff --git a/app/MindWork AI Studio/Components/Pages/Settings.razor b/app/MindWork AI Studio/Components/Pages/Settings.razor index 0f0e788..4a3be0b 100644 --- a/app/MindWork AI Studio/Components/Pages/Settings.razor +++ b/app/MindWork AI Studio/Components/Pages/Settings.razor @@ -8,146 +8,181 @@ Settings - - - Configured Providers - - - - - - - - - - # - Instance Name - Provider - Model - Actions - - - @context.Num - @context.InstanceName - @context.UsedProvider - - @if (context.UsedProvider is not Providers.SELF_HOSTED) - { - @this.GetProviderModelName(context) - } - else if (context.UsedProvider is Providers.SELF_HOSTED && context.Host is not Host.LLAMACPP) - { - @this.GetProviderModelName(context) - } - else - { - @("as selected by provider") - } - - - - Open Dashboard - - - Edit - - - Delete - - - - + + + + Configured Providers + + + + + + + + + + # + Instance Name + Provider + Model + Actions + + + @context.Num + @context.InstanceName + @context.UsedProvider + + @if (context.UsedProvider is not Providers.SELF_HOSTED) + { + @this.GetProviderModelName(context) + } + else if (context.UsedProvider is Providers.SELF_HOSTED && context.Host is not Host.LLAMACPP) + { + @this.GetProviderModelName(context) + } + else + { + @("as selected by provider") + } + + + + Open Dashboard + + + Edit + + + Delete + + + + - @if(this.SettingsManager.ConfigurationData.Providers.Count == 0) - { - No providers configured yet. - } - - - Add Provider - - - App Options - - - - - - Chat Options - - - - - Workspace Options - - - - Assistant Options - - Icon Finder Options - - - - - - - Translator Options - - - - - - - - - @if (this.SettingsManager.ConfigurationData.PreselectedTranslationTargetLanguage is CommonLanguages.OTHER) + @if(this.SettingsManager.ConfigurationData.Providers.Count == 0) { - + No providers configured yet. } - - - - Coding Options - - - - - @if (this.SettingsManager.ConfigurationData.PreselectedCodingLanguage is CommonCodingLanguages.OTHER) - { - - } - - - - Text Summarizer Options - - - - - - - @if (this.SettingsManager.ConfigurationData.PreselectedTextSummarizerTargetLanguage is CommonLanguages.OTHER) - { - - } - - @if(this.SettingsManager.ConfigurationData.PreselectedTextSummarizerComplexity is Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS) - { - - } - - - LLM Agent Options + + Add Provider + + + + + + + + + - Text Content Cleaner Agent - - - Use Case: this agent is used to clean up text content. It extracts the main content, removes advertisements and other irrelevant things, - and attempts to convert relative links into absolute links so that they can be used. - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @if (this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage is CommonLanguages.OTHER) + { + + } + + + + + + + + + + @if (this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage is CommonCodingLanguages.OTHER) + { + + } + + + + + + + + + + + + @if (this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage is CommonLanguages.OTHER) + { + + } + + @if(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity is Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS) + { + + } + + + + + + + + + + + + + + + + + + + + + + + + + + @if (this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage is CommonLanguages.OTHER) + { + + } + + + + + + + + Use Case: this agent is used to clean up text content. It extracts the main content, removes advertisements and other irrelevant things, + and attempts to convert relative links into absolute links so that they can be used. + + + + + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor b/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor index 82f138e..dc2b130 100644 --- a/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor +++ b/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor @@ -1,47 +1,16 @@ @page "/assistant/summarizer" -@using AIStudio.Settings @using AIStudio.Tools @inherits AssistantBaseCore -@if (!this.SettingsManager.ConfigurationData.HideWebContentReaderForTextSummarizer) +@if (!this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader) { - + } - - - - @foreach (var targetLanguage in Enum.GetValues()) - { - @targetLanguage.Name() - } - - @if (this.selectedTargetLanguage is CommonLanguages.OTHER) - { - - } - - - - - @foreach (var targetComplexity in Enum.GetValues()) - { - @targetComplexity.Name() - } - - @if (this.selectedComplexity is Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS) - { - - } - - - - @foreach (var provider in this.SettingsManager.ConfigurationData.Providers) - { - - } - + + + Summarize diff --git a/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor.cs b/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor.cs index 9a1b3f8..f0badef 100644 --- a/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/TextSummarizer/AssistantTextSummarizer.razor.cs @@ -34,13 +34,13 @@ public partial class AssistantTextSummarizer : AssistantBaseCore protected override async Task OnInitializedAsync() { - if(this.SettingsManager.ConfigurationData.PreselectTextSummarizerOptions) + if(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions) { - this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.PreselectedTextSummarizerTargetLanguage; - this.customTargetLanguage = this.SettingsManager.ConfigurationData.PreselectedTextSummarizerOtherLanguage; - this.selectedComplexity = this.SettingsManager.ConfigurationData.PreselectedTextSummarizerComplexity; - this.expertInField = this.SettingsManager.ConfigurationData.PreselectedTextSummarizerExpertInField; - this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.PreselectedTextSummarizerProvider); + this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage; + this.customTargetLanguage = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedOtherLanguage; + this.selectedComplexity = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity; + this.expertInField = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedExpertInField; + this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedProvider); } await base.OnInitializedAsync(); @@ -81,7 +81,7 @@ public partial class AssistantTextSummarizer : AssistantBaseCore this.CreateChatThread(); var time = this.AddUserRequest( $""" - {this.selectedTargetLanguage.Prompt(this.customTargetLanguage)} + {this.selectedTargetLanguage.PromptSummarizing(this.customTargetLanguage)} {this.selectedComplexity.Prompt(this.expertInField)} Please summarize the following text: diff --git a/app/MindWork AI Studio/Components/Pages/TextSummarizer/CommonLanguagePrompts.cs b/app/MindWork AI Studio/Components/Pages/TextSummarizer/CommonLanguagePrompts.cs deleted file mode 100644 index 73bd72c..0000000 --- a/app/MindWork AI Studio/Components/Pages/TextSummarizer/CommonLanguagePrompts.cs +++ /dev/null @@ -1,14 +0,0 @@ -using AIStudio.Tools; - -namespace AIStudio.Components.Pages.TextSummarizer; - -public static class CommonLanguagePrompts -{ - public static string Prompt(this CommonLanguages language, string customLanguage) => language switch - { - CommonLanguages.AS_IS => "Do not change the language of the text.", - CommonLanguages.OTHER => $"Output you summary in {customLanguage}.", - - _ => $"Output your summary in {language.Name()} ({language}).", - }; -} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor b/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor index 2b03eca..df54b13 100644 --- a/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor +++ b/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor @@ -1,54 +1,24 @@ @page "/assistant/translation" -@using AIStudio.Settings @using AIStudio.Tools @inherits AssistantBaseCore -@if (!this.SettingsManager.ConfigurationData.HideWebContentReaderForTranslation) +@if (!this.SettingsManager.ConfigurationData.Translation.HideWebContentReader) { - + } - - - @(this.liveTranslation ? "Live translation" : "No live translation") - - - + @if (this.liveTranslation) { - + } else { } - - - @foreach (var targetLanguage in Enum.GetValues()) - { - if (targetLanguage is CommonLanguages.AS_IS) - { - Please select the target language - } - else - { - @targetLanguage.Name() - } - } - - @if (this.selectedTargetLanguage is CommonLanguages.OTHER) - { - - } - - - - @foreach (var provider in this.SettingsManager.ConfigurationData.Providers) - { - - } - + + Translate diff --git a/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor.cs b/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor.cs index e21dcd3..20fe8fe 100644 --- a/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor.cs +++ b/app/MindWork AI Studio/Components/Pages/Translation/AssistantTranslation.razor.cs @@ -30,12 +30,12 @@ public partial class AssistantTranslation : AssistantBaseCore protected override async Task OnInitializedAsync() { - if (this.SettingsManager.ConfigurationData.PreselectTranslationOptions) + if (this.SettingsManager.ConfigurationData.Translation.PreselectOptions) { - this.liveTranslation = this.SettingsManager.ConfigurationData.PreselectLiveTranslation; - this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.PreselectedTranslationTargetLanguage; - this.customTargetLanguage = this.SettingsManager.ConfigurationData.PreselectTranslationOtherLanguage; - this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.PreselectedTranslationProvider); + this.liveTranslation = this.SettingsManager.ConfigurationData.Translation.PreselectLiveTranslation; + this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage; + this.customTargetLanguage = this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage; + this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Translation.PreselectedProvider); } await base.OnInitializedAsync(); @@ -66,7 +66,7 @@ public partial class AssistantTranslation : AssistantBaseCore return null; } - + private async Task TranslateText(bool force) { if (!this.inputIsValid) @@ -79,7 +79,7 @@ public partial class AssistantTranslation : AssistantBaseCore this.CreateChatThread(); var time = this.AddUserRequest( $""" - {this.selectedTargetLanguage.Prompt(this.customTargetLanguage)} + {this.selectedTargetLanguage.PromptTranslation(this.customTargetLanguage)} The given text is: diff --git a/app/MindWork AI Studio/Components/Pages/Translation/CommonLanguageExtension.cs b/app/MindWork AI Studio/Components/Pages/Translation/CommonLanguageExtension.cs deleted file mode 100644 index 97dcbbc..0000000 --- a/app/MindWork AI Studio/Components/Pages/Translation/CommonLanguageExtension.cs +++ /dev/null @@ -1,13 +0,0 @@ -using AIStudio.Tools; - -namespace AIStudio.Components.Pages.Translation; - -public static class CommonLanguageExtension -{ - public static string Prompt(this CommonLanguages language, string customLanguage) => language switch - { - CommonLanguages.OTHER => $"Translate the text in {customLanguage}.", - - _ => $"Translate the given text in {language.Name()} ({language}).", - }; -} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs b/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs index 95269f5..e802a7f 100644 --- a/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs +++ b/app/MindWork AI Studio/Settings/ConfigurationSelectData.cs @@ -1,3 +1,4 @@ +using AIStudio.Components.Pages.Agenda; using AIStudio.Components.Pages.Coding; using AIStudio.Components.Pages.IconFinder; using AIStudio.Components.Pages.TextSummarizer; @@ -72,6 +73,15 @@ public static class ConfigurationSelectDataFactory yield return new(language.Name(), language); } + public static IEnumerable> GetCommonLanguagesTranslationData() + { + foreach (var language in Enum.GetValues()) + if(language is CommonLanguages.AS_IS) + yield return new("Not yet specified", language); + else + yield return new(language.Name(), language); + } + public static IEnumerable> GetCommonCodingLanguagesData() { foreach (var language in Enum.GetValues()) @@ -83,4 +93,10 @@ public static class ConfigurationSelectDataFactory foreach (var complexity in Enum.GetValues()) yield return new(complexity.Name(), complexity); } + + public static IEnumerable> GetNumberParticipantsData() + { + foreach (var number in Enum.GetValues()) + yield return new(number.Name(), number); + } } \ 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 7ed6022..36c5c32 100644 --- a/app/MindWork AI Studio/Settings/DataModel/Data.cs +++ b/app/MindWork AI Studio/Settings/DataModel/Data.cs @@ -1,8 +1,3 @@ -using AIStudio.Components.Pages.Coding; -using AIStudio.Components.Pages.IconFinder; -using AIStudio.Components.Pages.TextSummarizer; -using AIStudio.Tools; - namespace AIStudio.Settings.DataModel; /// @@ -14,7 +9,7 @@ public sealed class Data /// The version of the settings file. Allows us to upgrade the settings /// when a new version is available. /// - public Version Version { get; init; } = Version.V3; + public Version Version { get; init; } = Version.V4; /// /// List of configured providers. @@ -26,222 +21,21 @@ public sealed class Data /// public uint NextProviderNum { get; set; } = 1; - #region App Settings + public DataApp App { get; init; } = new(); + + public DataChat Chat { get; init; } = new(); + + public DataWorkspace Workspace { get; init; } = new(); + + public DataIconFinder IconFinder { get; init; } = new(); + + public DataTranslation Translation { get; init; } = new(); + + public DataCoding Coding { get; init; } = new(); + + public DataTextSummarizer TextSummarizer { get; init; } = new(); + + public DataTextContentCleaner TextContentCleaner { get; init; } = new(); - /// - /// Should we save energy? When true, we will update content streamed - /// from the server, i.e., AI, less frequently. - /// - public bool IsSavingEnergy { get; set; } - - /// - /// Should we enable spellchecking for all input fields? - /// - public bool EnableSpellchecking { get; set; } - - /// - /// If and when we should look for updates. - /// - public UpdateBehavior UpdateBehavior { get; set; } = UpdateBehavior.ONCE_STARTUP; - - /// - /// The navigation behavior. - /// - public NavBehavior NavigationBehavior { get; set; } = NavBehavior.EXPAND_ON_HOVER; - - #endregion - - #region Chat Settings - - /// - /// Shortcuts to send the input to the AI. - /// - public SendBehavior ShortcutSendBehavior { get; set; } = SendBehavior.MODIFER_ENTER_IS_SENDING; - - /// - /// Preselect any chat options? - /// - public bool PreselectChatOptions { get; set; } - - /// - /// Should we preselect a provider for the chat? - /// - public string PreselectedChatProvider { get; set; } = string.Empty; - - #endregion - - #region Workspace Settings - - /// - /// The chat storage behavior. - /// - public WorkspaceStorageBehavior WorkspaceStorageBehavior { get; set; } = WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY; - - /// - /// The chat storage maintenance behavior. - /// - public WorkspaceStorageTemporaryMaintenancePolicy WorkspaceStorageTemporaryMaintenancePolicy { get; set; } = WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_90_DAYS; - - #endregion - - #region Assiatant: Icon Finder Settings - - /// - /// Do we want to preselect any icon options? - /// - public bool PreselectIconOptions { get; set; } - - /// - /// The preselected icon source. - /// - public IconSources PreselectedIconSource { get; set; } - - /// - /// The preselected icon provider. - /// - public string PreselectedIconProvider { get; set; } = string.Empty; - - #endregion - - #region Assistant: Translation Settings - - /// - /// The live translation interval for debouncing in milliseconds. - /// - public int LiveTranslationDebounceIntervalMilliseconds { get; set; } = 1_500; - - /// - /// Do we want to preselect any translator options? - /// - public bool PreselectTranslationOptions { get; set; } - - /// - /// Preselect the live translation? - /// - public bool PreselectLiveTranslation { get; set; } - - /// - /// Hide the web content reader? - /// - public bool HideWebContentReaderForTranslation { get; set; } - - /// - /// Preselect the web content reader? - /// - public bool PreselectWebContentReaderForTranslation { get; set; } - - /// - /// Preselect the content cleaner agent? - /// - public bool PreselectContentCleanerAgentForTranslation { get; set; } - - /// - /// Preselect the target language? - /// - public CommonLanguages PreselectedTranslationTargetLanguage { get; set; } = CommonLanguages.EN_US; - - /// - /// Preselect any other language? - /// - public string PreselectTranslationOtherLanguage { get; set; } = string.Empty; - - /// - /// The preselected translator provider. - /// - public string PreselectedTranslationProvider { get; set; } = string.Empty; - - #endregion - - #region Assistant: Coding Settings - - /// - /// Preselect any coding options? - /// - public bool PreselectCodingOptions { get; set; } - - /// - /// Preselect the compiler messages? - /// - public bool PreselectCodingCompilerMessages { get; set; } - - /// - /// Preselect the coding language for new contexts? - /// - public CommonCodingLanguages PreselectedCodingLanguage { get; set; } - - /// - /// Do you want to preselect any other language? - /// - public string PreselectedCodingOtherLanguage { get; set; } = string.Empty; - - /// - /// Which coding provider should be preselected? - /// - public string PreselectedCodingProvider { get; set; } = string.Empty; - - #endregion - - #region Assistant: Text Summarizer Settings - - /// - /// Preselect any text summarizer options? - /// - public bool PreselectTextSummarizerOptions { get; set; } - - - /// - /// Hide the web content reader? - /// - public bool HideWebContentReaderForTextSummarizer { get; set; } - - /// - /// Preselect the web content reader? - /// - public bool PreselectWebContentReaderForTextSummarizer { get; set; } - - /// - /// Preselect the content cleaner agent? - /// - public bool PreselectContentCleanerAgentForTextSummarizer { get; set; } - - /// - /// Preselect the target language? - /// - public CommonLanguages PreselectedTextSummarizerTargetLanguage { get; set; } - - /// - /// Preselect any other language? - /// - public string PreselectedTextSummarizerOtherLanguage { get; set; } = string.Empty; - - /// - /// Preselect the complexity? - /// - public Complexity PreselectedTextSummarizerComplexity { get; set; } - - /// - /// Preselect any expertise in a field? - /// - public string PreselectedTextSummarizerExpertInField { get; set; } = string.Empty; - - /// - /// Preselect a text summarizer provider? - /// - public string PreselectedTextSummarizerProvider { get; set; } = string.Empty; - - #endregion - - #region Agent: Text Content Cleaner Settings - - /// - /// Preselect any text content cleaner options? - /// - public bool PreselectAgentTextContentCleanerOptions { get; set; } - - /// - /// Preselect a text content cleaner provider? - /// - public string PreselectedAgentTextContentCleanerProvider { get; set; } = string.Empty; - - #endregion + public DataAgenda Agenda { get; init; } = new(); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataAgenda.cs b/app/MindWork AI Studio/Settings/DataModel/DataAgenda.cs new file mode 100644 index 0000000..4ab8ae7 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataAgenda.cs @@ -0,0 +1,59 @@ +using AIStudio.Components.Pages.Agenda; +using AIStudio.Tools; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataAgenda +{ + /// + /// Preselect any agenda options? + /// + public bool PreselectOptions { get; set; } + + public string PreselectName { get; set; } = string.Empty; + + public string PreselectTopic { get; set; } = string.Empty; + + public string PreselectObjective { get; set; } = string.Empty; + + public string PreselectModerator { get; set; } = string.Empty; + + public string PreselectDuration { get; set; } = string.Empty; + + public string PreselectStartTime { get; set; } = string.Empty; + + public bool PreselectIntroduceParticipants { get; set; } + + public NumberParticipants PreselectNumberParticipants { get; set; } = NumberParticipants.NOT_SPECIFIED; + + public bool PreselectActiveParticipation { get; set; } + + public bool PreselectIsMeetingVirtual { get; set; } = true; + + public string PreselectLocation { get; set; } = string.Empty; + + public bool PreselectJointDinner { get; set; } + + public bool PreselectSocialActivity { get; set; } + + public bool PreselectArriveAndDepart { get; set; } + + public int PreselectLunchTime { get; set; } + + public int PreselectBreakTime { get; set; } + + /// + /// Preselect the target language? + /// + public CommonLanguages PreselectedTargetLanguage { get; set; } + + /// + /// Preselect any other language? + /// + public string PreselectedOtherLanguage { get; set; } = string.Empty; + + /// + /// Preselect a agenda provider? + /// + public string PreselectedProvider { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataApp.cs b/app/MindWork AI Studio/Settings/DataModel/DataApp.cs new file mode 100644 index 0000000..885ab9a --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataApp.cs @@ -0,0 +1,25 @@ +namespace AIStudio.Settings.DataModel; + +public sealed class DataApp +{ + /// + /// Should we save energy? When true, we will update content streamed + /// from the server, i.e., AI, less frequently. + /// + public bool IsSavingEnergy { get; set; } + + /// + /// Should we enable spellchecking for all input fields? + /// + public bool EnableSpellchecking { get; set; } + + /// + /// If and when we should look for updates. + /// + public UpdateBehavior UpdateBehavior { get; set; } = UpdateBehavior.ONCE_STARTUP; + + /// + /// The navigation behavior. + /// + public NavBehavior NavigationBehavior { get; set; } = NavBehavior.EXPAND_ON_HOVER; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataChat.cs b/app/MindWork AI Studio/Settings/DataModel/DataChat.cs new file mode 100644 index 0000000..825bfc9 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataChat.cs @@ -0,0 +1,19 @@ +namespace AIStudio.Settings.DataModel; + +public sealed class DataChat +{ + /// + /// Shortcuts to send the input to the AI. + /// + public SendBehavior ShortcutSendBehavior { get; set; } = SendBehavior.MODIFER_ENTER_IS_SENDING; + + /// + /// Preselect any chat options? + /// + public bool PreselectOptions { get; set; } + + /// + /// Should we preselect a provider for the chat? + /// + public string PreselectedProvider { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataCoding.cs b/app/MindWork AI Studio/Settings/DataModel/DataCoding.cs new file mode 100644 index 0000000..052c319 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataCoding.cs @@ -0,0 +1,31 @@ +using AIStudio.Components.Pages.Coding; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataCoding +{ + /// + /// Preselect any coding options? + /// + public bool PreselectOptions { get; set; } + + /// + /// Preselect the compiler messages? + /// + public bool PreselectCompilerMessages { get; set; } + + /// + /// Preselect the coding language for new contexts? + /// + public CommonCodingLanguages PreselectedProgrammingLanguage { get; set; } + + /// + /// Do you want to preselect any other language? + /// + public string PreselectedOtherProgrammingLanguage { get; set; } = string.Empty; + + /// + /// Which coding provider should be preselected? + /// + public string PreselectedProvider { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataIconFinder.cs b/app/MindWork AI Studio/Settings/DataModel/DataIconFinder.cs new file mode 100644 index 0000000..d47c3df --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataIconFinder.cs @@ -0,0 +1,21 @@ +using AIStudio.Components.Pages.IconFinder; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataIconFinder +{ + /// + /// Do we want to preselect any icon options? + /// + public bool PreselectOptions { get; set; } + + /// + /// The preselected icon source. + /// + public IconSources PreselectedSource { get; set; } + + /// + /// The preselected icon provider. + /// + public string PreselectedProvider { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataTextContentCleaner.cs b/app/MindWork AI Studio/Settings/DataModel/DataTextContentCleaner.cs new file mode 100644 index 0000000..c1e7137 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataTextContentCleaner.cs @@ -0,0 +1,14 @@ +namespace AIStudio.Settings.DataModel; + +public sealed class DataTextContentCleaner +{ + /// + /// Preselect any text content cleaner options? + /// + public bool PreselectAgentOptions { get; set; } + + /// + /// Preselect a text content cleaner provider? + /// + public string PreselectedAgentProvider { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataTextSummarizer.cs b/app/MindWork AI Studio/Settings/DataModel/DataTextSummarizer.cs new file mode 100644 index 0000000..e6ee9ea --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataTextSummarizer.cs @@ -0,0 +1,53 @@ +using AIStudio.Components.Pages.TextSummarizer; +using AIStudio.Tools; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataTextSummarizer +{ + /// + /// Preselect any text summarizer options? + /// + public bool PreselectOptions { get; set; } + + + /// + /// Hide the web content reader? + /// + public bool HideWebContentReader { get; set; } + + /// + /// Preselect the web content reader? + /// + public bool PreselectWebContentReader { get; set; } + + /// + /// Preselect the content cleaner agent? + /// + public bool PreselectContentCleanerAgent { get; set; } + + /// + /// Preselect the target language? + /// + public CommonLanguages PreselectedTargetLanguage { get; set; } + + /// + /// Preselect any other language? + /// + public string PreselectedOtherLanguage { get; set; } = string.Empty; + + /// + /// Preselect the complexity? + /// + public Complexity PreselectedComplexity { get; set; } + + /// + /// Preselect any expertise in a field? + /// + public string PreselectedExpertInField { get; set; } = string.Empty; + + /// + /// Preselect a text summarizer provider? + /// + public string PreselectedProvider { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataTranslation.cs b/app/MindWork AI Studio/Settings/DataModel/DataTranslation.cs new file mode 100644 index 0000000..26c5aba --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataTranslation.cs @@ -0,0 +1,51 @@ +using AIStudio.Tools; + +namespace AIStudio.Settings.DataModel; + +public sealed class DataTranslation +{ + /// + /// The live translation interval for debouncing in milliseconds. + /// + public int DebounceIntervalMilliseconds { get; set; } = 1_500; + + /// + /// Do we want to preselect any translator options? + /// + public bool PreselectOptions { get; set; } + + /// + /// Preselect the live translation? + /// + public bool PreselectLiveTranslation { get; set; } + + /// + /// Hide the web content reader? + /// + public bool HideWebContentReader { get; set; } + + /// + /// Preselect the web content reader? + /// + public bool PreselectWebContentReader { get; set; } + + /// + /// Preselect the content cleaner agent? + /// + public bool PreselectContentCleanerAgent { get; set; } + + /// + /// Preselect the target language? + /// + public CommonLanguages PreselectedTargetLanguage { get; set; } = CommonLanguages.EN_US; + + /// + /// Preselect any other language? + /// + public string PreselectOtherLanguage { get; set; } = string.Empty; + + /// + /// The preselected translator provider. + /// + public string PreselectedProvider { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/DataWorkspace.cs b/app/MindWork AI Studio/Settings/DataModel/DataWorkspace.cs new file mode 100644 index 0000000..5041fc1 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/DataWorkspace.cs @@ -0,0 +1,14 @@ +namespace AIStudio.Settings.DataModel; + +public sealed class DataWorkspace +{ + /// + /// The chat storage behavior. + /// + public WorkspaceStorageBehavior StorageBehavior { get; set; } = WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY; + + /// + /// The chat storage maintenance behavior. + /// + public WorkspaceStorageTemporaryMaintenancePolicy StorageTemporaryMaintenancePolicy { get; set; } = WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_90_DAYS; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/DataModel/PreviousModels/DataV1V3.cs b/app/MindWork AI Studio/Settings/DataModel/PreviousModels/DataV1V3.cs new file mode 100644 index 0000000..b19c7b4 --- /dev/null +++ b/app/MindWork AI Studio/Settings/DataModel/PreviousModels/DataV1V3.cs @@ -0,0 +1,247 @@ +using AIStudio.Components.Pages.Coding; +using AIStudio.Components.Pages.IconFinder; +using AIStudio.Components.Pages.TextSummarizer; +using AIStudio.Tools; + +namespace AIStudio.Settings.DataModel.PreviousModels; + +/// +/// The data model for the settings file. +/// +public sealed class DataV1V3 +{ + /// + /// The version of the settings file. Allows us to upgrade the settings + /// when a new version is available. + /// + public Version Version { get; init; } = Version.V3; + + /// + /// List of configured providers. + /// + public List Providers { get; init; } = []; + + /// + /// The next provider number to use. + /// + public uint NextProviderNum { get; set; } = 1; + + #region App Settings + + /// + /// Should we save energy? When true, we will update content streamed + /// from the server, i.e., AI, less frequently. + /// + public bool IsSavingEnergy { get; set; } + + /// + /// Should we enable spellchecking for all input fields? + /// + public bool EnableSpellchecking { get; set; } + + /// + /// If and when we should look for updates. + /// + public UpdateBehavior UpdateBehavior { get; set; } = UpdateBehavior.ONCE_STARTUP; + + /// + /// The navigation behavior. + /// + public NavBehavior NavigationBehavior { get; set; } = NavBehavior.EXPAND_ON_HOVER; + + #endregion + + #region Chat Settings + + /// + /// Shortcuts to send the input to the AI. + /// + public SendBehavior ShortcutSendBehavior { get; set; } = SendBehavior.MODIFER_ENTER_IS_SENDING; + + /// + /// Preselect any chat options? + /// + public bool PreselectChatOptions { get; set; } + + /// + /// Should we preselect a provider for the chat? + /// + public string PreselectedChatProvider { get; set; } = string.Empty; + + #endregion + + #region Workspace Settings + + /// + /// The chat storage behavior. + /// + public WorkspaceStorageBehavior WorkspaceStorageBehavior { get; set; } = WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY; + + /// + /// The chat storage maintenance behavior. + /// + public WorkspaceStorageTemporaryMaintenancePolicy WorkspaceStorageTemporaryMaintenancePolicy { get; set; } = WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_90_DAYS; + + #endregion + + #region Assiatant: Icon Finder Settings + + /// + /// Do we want to preselect any icon options? + /// + public bool PreselectIconOptions { get; set; } + + /// + /// The preselected icon source. + /// + public IconSources PreselectedIconSource { get; set; } + + /// + /// The preselected icon provider. + /// + public string PreselectedIconProvider { get; set; } = string.Empty; + + #endregion + + #region Assistant: Translation Settings + + /// + /// The live translation interval for debouncing in milliseconds. + /// + public int LiveTranslationDebounceIntervalMilliseconds { get; set; } = 1_500; + + /// + /// Do we want to preselect any translator options? + /// + public bool PreselectTranslationOptions { get; set; } + + /// + /// Preselect the live translation? + /// + public bool PreselectLiveTranslation { get; set; } + + /// + /// Hide the web content reader? + /// + public bool HideWebContentReaderForTranslation { get; set; } + + /// + /// Preselect the web content reader? + /// + public bool PreselectWebContentReaderForTranslation { get; set; } + + /// + /// Preselect the content cleaner agent? + /// + public bool PreselectContentCleanerAgentForTranslation { get; set; } + + /// + /// Preselect the target language? + /// + public CommonLanguages PreselectedTranslationTargetLanguage { get; set; } = CommonLanguages.EN_US; + + /// + /// Preselect any other language? + /// + public string PreselectTranslationOtherLanguage { get; set; } = string.Empty; + + /// + /// The preselected translator provider. + /// + public string PreselectedTranslationProvider { get; set; } = string.Empty; + + #endregion + + #region Assistant: Coding Settings + + /// + /// Preselect any coding options? + /// + public bool PreselectCodingOptions { get; set; } + + /// + /// Preselect the compiler messages? + /// + public bool PreselectCodingCompilerMessages { get; set; } + + /// + /// Preselect the coding language for new contexts? + /// + public CommonCodingLanguages PreselectedCodingLanguage { get; set; } + + /// + /// Do you want to preselect any other language? + /// + public string PreselectedCodingOtherLanguage { get; set; } = string.Empty; + + /// + /// Which coding provider should be preselected? + /// + public string PreselectedCodingProvider { get; set; } = string.Empty; + + #endregion + + #region Assistant: Text Summarizer Settings + + /// + /// Preselect any text summarizer options? + /// + public bool PreselectTextSummarizerOptions { get; set; } + + + /// + /// Hide the web content reader? + /// + public bool HideWebContentReaderForTextSummarizer { get; set; } + + /// + /// Preselect the web content reader? + /// + public bool PreselectWebContentReaderForTextSummarizer { get; set; } + + /// + /// Preselect the content cleaner agent? + /// + public bool PreselectContentCleanerAgentForTextSummarizer { get; set; } + + /// + /// Preselect the target language? + /// + public CommonLanguages PreselectedTextSummarizerTargetLanguage { get; set; } + + /// + /// Preselect any other language? + /// + public string PreselectedTextSummarizerOtherLanguage { get; set; } = string.Empty; + + /// + /// Preselect the complexity? + /// + public Complexity PreselectedTextSummarizerComplexity { get; set; } + + /// + /// Preselect any expertise in a field? + /// + public string PreselectedTextSummarizerExpertInField { get; set; } = string.Empty; + + /// + /// Preselect a text summarizer provider? + /// + public string PreselectedTextSummarizerProvider { get; set; } = string.Empty; + + #endregion + + #region Agent: Text Content Cleaner Settings + + /// + /// Preselect any text content cleaner options? + /// + public bool PreselectAgentTextContentCleanerOptions { get; set; } + + /// + /// Preselect a text content cleaner provider? + /// + public string PreselectedAgentTextContentCleanerProvider { get; set; } = string.Empty; + + #endregion +} \ 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 26151a1..c4cbc44 100644 --- a/app/MindWork AI Studio/Settings/SettingsManager.cs +++ b/app/MindWork AI Studio/Settings/SettingsManager.cs @@ -107,13 +107,33 @@ public sealed class SettingsManager var settingsPath = Path.Combine(ConfigDirectory!, SETTINGS_FILENAME); if(!File.Exists(settingsPath)) return; - - var settingsJson = await File.ReadAllTextAsync(settingsPath); - var loadedConfiguration = JsonSerializer.Deserialize(settingsJson, JSON_OPTIONS); - if(loadedConfiguration is null) + + // We read the `"Version": "V3"` line to determine the version of the settings file: + await foreach (var line in File.ReadLinesAsync(settingsPath)) + { + if (!line.Contains(""" + "Version": + """)) + continue; + + // Extract the version from the line: + var settingsVersionText = line.Split('"')[3]; + + // Parse the version: + Enum.TryParse(settingsVersionText, out Version settingsVersion); + if(settingsVersion is Version.UNKNOWN) + { + Console.WriteLine("Error: Unknown version of the settings file."); + this.ConfigurationData = new(); + return; + } + + this.ConfigurationData = SettingsMigrations.Migrate(settingsVersion, await File.ReadAllTextAsync(settingsPath), JSON_OPTIONS); return; + } - this.ConfigurationData = SettingsMigrations.Migrate(loadedConfiguration); + Console.WriteLine("Error: Failed to read the version of the settings file."); + this.ConfigurationData = new(); } /// @@ -132,5 +152,5 @@ public sealed class SettingsManager await File.WriteAllTextAsync(settingsPath, settingsJson); } - public void InjectSpellchecking(Dictionary attributes) => attributes["spellcheck"] = this.ConfigurationData.EnableSpellchecking ? "true" : "false"; + public void InjectSpellchecking(Dictionary attributes) => attributes["spellcheck"] = this.ConfigurationData.App.EnableSpellchecking ? "true" : "false"; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/SettingsMigrations.cs b/app/MindWork AI Studio/Settings/SettingsMigrations.cs index 6e1669d..121d96c 100644 --- a/app/MindWork AI Studio/Settings/SettingsMigrations.cs +++ b/app/MindWork AI Studio/Settings/SettingsMigrations.cs @@ -1,4 +1,7 @@ +using System.Text.Json; + using AIStudio.Settings.DataModel; +using AIStudio.Settings.DataModel.PreviousModels; using Host = AIStudio.Provider.SelfHosted.Host; @@ -6,24 +9,57 @@ namespace AIStudio.Settings; public static class SettingsMigrations { - public static Data Migrate(Data previousData) + public static Data Migrate(Version previousVersion, string configData, JsonSerializerOptions jsonOptions) { - switch (previousData.Version) + switch (previousVersion) { case Version.V1: - previousData = MigrateV1ToV2(previousData); - return MigrateV2ToV3(previousData); + var configV1 = JsonSerializer.Deserialize(configData, jsonOptions); + if (configV1 is null) + { + Console.WriteLine("Error: failed to parse the configuration. Using default values."); + return new(); + } + + configV1 = MigrateV1ToV2(configV1); + configV1 = MigrateV2ToV3(configV1); + return MigrateV3ToV4(configV1); case Version.V2: - return MigrateV2ToV3(previousData); - + var configV2 = JsonSerializer.Deserialize(configData, jsonOptions); + if (configV2 is null) + { + Console.WriteLine("Error: failed to parse the configuration. Using default values."); + return new(); + } + + configV2 = MigrateV2ToV3(configV2); + return MigrateV3ToV4(configV2); + + case Version.V3: + var configV3 = JsonSerializer.Deserialize(configData, jsonOptions); + if (configV3 is null) + { + Console.WriteLine("Error: failed to parse the configuration. Using default values."); + return new(); + } + + return MigrateV3ToV4(configV3); + default: - Console.WriteLine("No migration needed."); - return previousData; + Console.WriteLine("No configuration migration needed."); + var configV4 = JsonSerializer.Deserialize(configData, jsonOptions); + if (configV4 is null) + { + Console.WriteLine("Error: failed to parse the configuration. Using default values."); + return new(); + } + + return configV4; } } - private static Data MigrateV1ToV2(Data previousData) + private static DataV1V3 MigrateV1ToV2(DataV1V3 previousData) { // // Summary: @@ -45,7 +81,7 @@ public static class SettingsMigrations }; } - private static Data MigrateV2ToV3(Data previousData) + private static DataV1V3 MigrateV2ToV3(DataV1V3 previousData) { // // Summary: @@ -73,4 +109,89 @@ public static class SettingsMigrations WorkspaceStorageTemporaryMaintenancePolicy = previousData.WorkspaceStorageTemporaryMaintenancePolicy, }; } + + private static Data MigrateV3ToV4(DataV1V3 previousConfig) + { + // + // Summary: + // We grouped the settings into different categories. + // + + Console.WriteLine("Migrating from v3 to v4..."); + return new() + { + Version = Version.V4, + Providers = previousConfig.Providers, + NextProviderNum = previousConfig.NextProviderNum, + + App = new() + { + EnableSpellchecking = previousConfig.EnableSpellchecking, + IsSavingEnergy = previousConfig.IsSavingEnergy, + UpdateBehavior = previousConfig.UpdateBehavior, + NavigationBehavior = previousConfig.NavigationBehavior, + }, + + Chat = new() + { + ShortcutSendBehavior = previousConfig.ShortcutSendBehavior, + PreselectOptions = previousConfig.PreselectChatOptions, + PreselectedProvider = previousConfig.PreselectedChatProvider, + }, + + Workspace = new() + { + StorageBehavior = previousConfig.WorkspaceStorageBehavior, + StorageTemporaryMaintenancePolicy = previousConfig.WorkspaceStorageTemporaryMaintenancePolicy, + }, + + IconFinder = new() + { + PreselectOptions = previousConfig.PreselectIconOptions, + PreselectedProvider = previousConfig.PreselectedIconProvider, + PreselectedSource = previousConfig.PreselectedIconSource, + }, + + Translation = new() + { + PreselectLiveTranslation = previousConfig.PreselectLiveTranslation, + DebounceIntervalMilliseconds = previousConfig.LiveTranslationDebounceIntervalMilliseconds, + PreselectOptions = previousConfig.PreselectTranslationOptions, + PreselectedProvider = previousConfig.PreselectedTranslationProvider, + PreselectedTargetLanguage = previousConfig.PreselectedTranslationTargetLanguage, + PreselectOtherLanguage = previousConfig.PreselectTranslationOtherLanguage, + HideWebContentReader = previousConfig.HideWebContentReaderForTranslation, + PreselectContentCleanerAgent = previousConfig.PreselectContentCleanerAgentForTranslation, + PreselectWebContentReader = previousConfig.PreselectWebContentReaderForTranslation, + }, + + Coding = new() + { + PreselectOptions = previousConfig.PreselectCodingOptions, + PreselectedProvider = previousConfig.PreselectedCodingProvider, + PreselectedProgrammingLanguage = previousConfig.PreselectedCodingLanguage, + PreselectedOtherProgrammingLanguage = previousConfig.PreselectedCodingOtherLanguage, + PreselectCompilerMessages = previousConfig.PreselectCodingCompilerMessages, + }, + + TextSummarizer = new() + { + PreselectOptions = previousConfig.PreselectTextSummarizerOptions, + PreselectedComplexity = previousConfig.PreselectedTextSummarizerComplexity, + PreselectedProvider = previousConfig.PreselectedTextSummarizerProvider, + PreselectedTargetLanguage = previousConfig.PreselectedTextSummarizerTargetLanguage, + PreselectedOtherLanguage = previousConfig.PreselectedTextSummarizerOtherLanguage, + PreselectedExpertInField = previousConfig.PreselectedTextSummarizerExpertInField, + HideWebContentReader = previousConfig.HideWebContentReaderForTextSummarizer, + PreselectContentCleanerAgent = previousConfig.PreselectContentCleanerAgentForTextSummarizer, + PreselectWebContentReader = previousConfig.PreselectWebContentReaderForTextSummarizer, + }, + + TextContentCleaner = new() + { + PreselectAgentOptions = previousConfig.PreselectAgentTextContentCleanerOptions, + PreselectedAgentProvider = previousConfig.PreselectedAgentTextContentCleanerProvider, + }, + }; + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Settings/Version.cs b/app/MindWork AI Studio/Settings/Version.cs index cb30052..2b38b8f 100644 --- a/app/MindWork AI Studio/Settings/Version.cs +++ b/app/MindWork AI Studio/Settings/Version.cs @@ -11,4 +11,5 @@ public enum Version V1, V2, V3, + V4, } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/CommonLanguageExtensions.cs b/app/MindWork AI Studio/Tools/CommonLanguageExtensions.cs index 5d932a2..57618b6 100644 --- a/app/MindWork AI Studio/Tools/CommonLanguageExtensions.cs +++ b/app/MindWork AI Studio/Tools/CommonLanguageExtensions.cs @@ -19,4 +19,27 @@ public static class CommonLanguageExtensions _ => "Other", }; + + public static string PromptSummarizing(this CommonLanguages language, string customLanguage) => language switch + { + CommonLanguages.AS_IS => "Do not change the language of the text.", + CommonLanguages.OTHER => $"Output your summary in {customLanguage}.", + + _ => $"Output your summary in {language.Name()} ({language}).", + }; + + public static string PromptTranslation(this CommonLanguages language, string customLanguage) => language switch + { + CommonLanguages.OTHER => $"Translate the text in {customLanguage}.", + + _ => $"Translate the given text in {language.Name()} ({language}).", + }; + + public static string NameSelecting(this CommonLanguages language) + { + if(language is CommonLanguages.AS_IS) + return "Please select the target language"; + + return language.Name(); + } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/TemporaryChatService.cs b/app/MindWork AI Studio/Tools/TemporaryChatService.cs index f820716..0e76279 100644 --- a/app/MindWork AI Studio/Tools/TemporaryChatService.cs +++ b/app/MindWork AI Studio/Tools/TemporaryChatService.cs @@ -16,7 +16,7 @@ public class TemporaryChatService(SettingsManager settingsManager) : BackgroundS await Task.Delay(TimeSpan.FromSeconds(3), stoppingToken); await settingsManager.LoadSettings(); - if(settingsManager.ConfigurationData.WorkspaceStorageTemporaryMaintenancePolicy is WorkspaceStorageTemporaryMaintenancePolicy.NO_AUTOMATIC_MAINTENANCE) + if(settingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy is WorkspaceStorageTemporaryMaintenancePolicy.NO_AUTOMATIC_MAINTENANCE) { Console.WriteLine("Automatic maintenance of temporary chat storage is disabled. Exiting maintenance service."); return; @@ -46,7 +46,7 @@ public class TemporaryChatService(SettingsManager settingsManager) : BackgroundS continue; var lastWriteTime = chatMetadata.LastWriteTimeUtc; - var deleteChat = settingsManager.ConfigurationData.WorkspaceStorageTemporaryMaintenancePolicy switch + var deleteChat = settingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy switch { WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_7_DAYS => DateTime.UtcNow - lastWriteTime > TimeSpan.FromDays(7), WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_30_DAYS => DateTime.UtcNow - lastWriteTime > TimeSpan.FromDays(30), diff --git a/app/MindWork AI Studio/Tools/UpdateService.cs b/app/MindWork AI Studio/Tools/UpdateService.cs index 71fcb9b..6f6c07d 100644 --- a/app/MindWork AI Studio/Tools/UpdateService.cs +++ b/app/MindWork AI Studio/Tools/UpdateService.cs @@ -37,7 +37,7 @@ public sealed class UpdateService : BackgroundService, IMessageBusReceiver while (!stoppingToken.IsCancellationRequested && !IS_INITIALIZED) await Task.Delay(TimeSpan.FromSeconds(3), stoppingToken); - this.updateInterval = this.settingsManager.ConfigurationData.UpdateBehavior switch + this.updateInterval = this.settingsManager.ConfigurationData.App.UpdateBehavior switch { UpdateBehavior.NO_CHECK => Timeout.InfiniteTimeSpan, UpdateBehavior.ONCE_STARTUP => Timeout.InfiniteTimeSpan, @@ -49,7 +49,7 @@ public sealed class UpdateService : BackgroundService, IMessageBusReceiver _ => TimeSpan.FromHours(1) }; - if(this.settingsManager.ConfigurationData.UpdateBehavior is UpdateBehavior.NO_CHECK) + if(this.settingsManager.ConfigurationData.App.UpdateBehavior is UpdateBehavior.NO_CHECK) return; await this.CheckForUpdate(); diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.8.6.md b/app/MindWork AI Studio/wwwroot/changelog/v0.8.6.md index b6cedaa..399c229 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.8.6.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.8.6.md @@ -6,4 +6,5 @@ - Improved the readability of the settings.json file by using indentation and enum names instead of numbers - Improved assistant overview; assistants will now wrap to the next line if there are too many to fit on the row - Increased the default value for the live translation delay from 1,000 to 3_000 ms -- Fixed random number generator usage to be thread-safe \ No newline at end of file +- Fixed random number generator usage to be thread-safe +- Upgraded MudBlazor dependency \ No newline at end of file diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.8.7.md b/app/MindWork AI Studio/wwwroot/changelog/v0.8.7.md index 9127ada..01c3284 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.8.7.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.8.7.md @@ -1,2 +1,14 @@ -# v0.8.7, build 169 -- Restructuring of the assistant overview: the assistants are now displayed in different categories. \ No newline at end of file +# v0.8.7, build 169 (2024-08-01 19:08 UTC) +- Added an agenda planning assistant. +- Added the possibility to preselect most agenda planning options. +- Added a slider component to adjust values. +- Added a process visualization component. +- Restructuring of the assistant overview: the assistants are now displayed in different categories. +- Restructuring of the settings page: the settings are now displayed in different categories. +- Refactored switch component to unify the behavior. +- Refactored the language extensions into one extension class. +- Refactored the provider selection into a separate component. +- Refactored the configuration data model: the configuration is now stored in separate classes for each section. +- Fixed a bug where the configured live translation intervall was not applied. +- Fixed a bug where the option slider component was not handling min/max constraints correctly. +- Upgraded MudBlazor dependency \ No newline at end of file diff --git a/metadata.txt b/metadata.txt index 51f9c8e..00cca42 100644 --- a/metadata.txt +++ b/metadata.txt @@ -1,9 +1,9 @@ -0.8.6 -2024-08-01 19:50:02 UTC -168 +0.8.7 +2024-08-05 19:08:00 UTC +169 8.0.107 (commit 1bdaef7265) 8.0.7 (commit 2aade6beb0) 1.80.0 (commit 051478957) -7.4.0 +7.5.0 1.7.1 -199be1e863f, release +bf0a75677d8, release diff --git a/runtime/Cargo.lock b/runtime/Cargo.lock index a7bc970..5355577 100644 --- a/runtime/Cargo.lock +++ b/runtime/Cargo.lock @@ -2308,7 +2308,7 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mindwork-ai-studio" -version = "0.8.6" +version = "0.8.7" dependencies = [ "arboard", "flexi_logger", diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8f64fca..d8e1013 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindwork-ai-studio" -version = "0.8.6" +version = "0.8.7" edition = "2021" description = "MindWork AI Studio" authors = ["Thorsten Sommer"] diff --git a/runtime/tauri.conf.json b/runtime/tauri.conf.json index 315a8a3..97e526f 100644 --- a/runtime/tauri.conf.json +++ b/runtime/tauri.conf.json @@ -6,7 +6,7 @@ }, "package": { "productName": "MindWork AI Studio", - "version": "0.8.6" + "version": "0.8.7" }, "tauri": { "allowlist": {