diff --git a/app/MindWork AI Studio/Chat/ChatThread.cs b/app/MindWork AI Studio/Chat/ChatThread.cs index e8277cb5..2c9bb720 100644 --- a/app/MindWork AI Studio/Chat/ChatThread.cs +++ b/app/MindWork AI Studio/Chat/ChatThread.cs @@ -94,6 +94,8 @@ public sealed record ChatThread /// The prepared system prompt. public string PrepareSystemPrompt(SettingsManager settingsManager) { + this.allowProfile = true; + // // Use the information from the chat template, if provided. Otherwise, use the default system prompt // @@ -111,8 +113,8 @@ public sealed record ChatThread systemPromptTextWithChatTemplate = this.SystemPrompt; else { - var chatTemplate = settingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == this.SelectedChatTemplate); - if(chatTemplate == null) + var chatTemplate = settingsManager.GetChatTemplateById(this.SelectedChatTemplate); + if(chatTemplate == ChatTemplate.NO_CHAT_TEMPLATE) systemPromptTextWithChatTemplate = this.SystemPrompt; else { @@ -168,8 +170,8 @@ public sealed record ChatThread systemPromptText = systemPromptWithAugmentedData; else { - var profile = settingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.SelectedProfile); - if(profile is null) + var profile = settingsManager.GetProfileById(this.SelectedProfile); + if(profile == Profile.NO_PROFILE) systemPromptText = systemPromptWithAugmentedData; else { diff --git a/app/MindWork AI Studio/Components/ChatComponent.razor.cs b/app/MindWork AI Studio/Components/ChatComponent.razor.cs index 62caf008..aa2b099d 100644 --- a/app/MindWork AI Studio/Components/ChatComponent.razor.cs +++ b/app/MindWork AI Studio/Components/ChatComponent.razor.cs @@ -101,7 +101,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable protected override async Task OnInitializedAsync() { // Apply the filters for the message bus: - this.ApplyFilters([], [ Event.HAS_CHAT_UNSAVED_CHANGES, Event.RESET_CHAT_STATE, Event.CHAT_STREAMING_DONE, Event.AI_JOB_CHANGED, Event.AI_JOB_FINISHED, Event.CHAT_GENERATION_CHANGED, Event.WORKSPACE_RENAMED ]); + this.ApplyFilters([], [ Event.HAS_CHAT_UNSAVED_CHANGES, Event.RESET_CHAT_STATE, Event.CHAT_STREAMING_DONE, Event.AI_JOB_CHANGED, Event.AI_JOB_FINISHED, Event.CHAT_GENERATION_CHANGED, Event.WORKSPACE_RENAMED, Event.CONFIGURATION_CHANGED ]); // Configure the spellchecking for the user input: this.SettingsManager.InjectSpellchecking(USER_INPUT_ATTRIBUTES); @@ -470,7 +470,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable private async Task ProfileWasChanged(Profile profile) { - this.currentProfile = profile; + this.currentProfile = this.SettingsManager.GetProfileById(profile.Id); if(this.ChatThread is null) return; @@ -484,7 +484,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable private async Task ChatTemplateWasChanged(ChatTemplate chatTemplate) { - this.currentChatTemplate = chatTemplate; + this.currentChatTemplate = this.SettingsManager.GetChatTemplateById(chatTemplate.Id); if(!string.IsNullOrWhiteSpace(this.currentChatTemplate.PredefinedUserPrompt)) this.ComposerState.SetSystemInput(this.currentChatTemplate.PredefinedUserPrompt); @@ -497,6 +497,12 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable await this.StartNewChat(true); } + private void RefreshCurrentProfileAndChatTemplate() + { + this.currentProfile = this.SettingsManager.GetProfileById(this.currentProfile.Id); + this.currentChatTemplate = this.SettingsManager.GetChatTemplateById(this.currentChatTemplate.Id); + } + private IReadOnlyList GetAgentSelectedDataSources() { if (this.ChatThread is null) @@ -601,7 +607,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable if(!this.ChatThread.IsLLMProviderAllowed(this.Provider)) return; - + + this.RefreshCurrentProfileAndChatTemplate(); + // Blur the focus away from the input field to be able to clear it: await this.inputField.BlurAsync(); @@ -795,6 +803,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable // this.hasUnsavedChanges = false; this.ComposerState.Clear(); + this.RefreshCurrentProfileAndChatTemplate(); // // Reset the LLM provider considering the user's settings: @@ -967,14 +976,11 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable // Try to select the profile: if (!string.IsNullOrWhiteSpace(chatProfile)) - this.currentProfile = this.SettingsManager.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == chatProfile) ?? Profile.NO_PROFILE; + this.currentProfile = this.SettingsManager.GetProfileById(chatProfile); // Try to select the chat template: if (!string.IsNullOrWhiteSpace(chatChatTemplate)) - { - var selectedTemplate = this.SettingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == chatChatTemplate); - this.currentChatTemplate = selectedTemplate ?? ChatTemplate.NO_CHAT_TEMPLATE; - } + this.currentChatTemplate = this.SettingsManager.GetChatTemplateById(chatChatTemplate); } private async Task ToggleWorkspaceOverlay() @@ -1074,6 +1080,15 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable if (data is Guid workspaceId) await this.RefreshRenamedWorkspaceHeaderAsync(workspaceId); break; + + case Event.CONFIGURATION_CHANGED: + var previousChatTemplate = this.currentChatTemplate; + this.RefreshCurrentProfileAndChatTemplate(); + if (!this.ComposerState.HasUserDraft && previousChatTemplate != this.currentChatTemplate) + this.ComposerState.ApplyTemplate(this.currentChatTemplate); + + this.StateHasChanged(); + break; case Event.AI_JOB_CHANGED: case Event.AI_JOB_FINISHED: diff --git a/app/MindWork AI Studio/Settings/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs index 3ec8906c..76be18d2 100644 --- a/app/MindWork AI Studio/Settings/SettingsManager.cs +++ b/app/MindWork AI Studio/Settings/SettingsManager.cs @@ -348,17 +348,13 @@ public sealed class SettingsManager return Profile.NO_PROFILE; if (preselection.UseSpecificProfile) - { - var componentProfile = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id.Equals(preselection.SpecificProfileId, StringComparison.OrdinalIgnoreCase)); - return componentProfile ?? Profile.NO_PROFILE; - } + return this.GetProfileById(preselection.SpecificProfileId); var appPreselection = ProfilePreselection.FromStoredValue(this.ConfigurationData.App.PreselectedProfile); if (appPreselection.DoNotPreselectProfile || !appPreselection.UseSpecificProfile) return Profile.NO_PROFILE; - var appProfile = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id.Equals(appPreselection.SpecificProfileId, StringComparison.OrdinalIgnoreCase)); - return appProfile ?? Profile.NO_PROFILE; + return this.GetProfileById(appPreselection.SpecificProfileId); } public Profile GetAppPreselectedProfile() @@ -367,8 +363,7 @@ public sealed class SettingsManager if (appPreselection.DoNotPreselectProfile || !appPreselection.UseSpecificProfile) return Profile.NO_PROFILE; - var appProfile = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id.Equals(appPreselection.SpecificProfileId, StringComparison.OrdinalIgnoreCase)); - return appProfile ?? Profile.NO_PROFILE; + return this.GetProfileById(appPreselection.SpecificProfileId); } public ChatTemplate GetPreselectedChatTemplate(Tools.Components component) @@ -377,8 +372,29 @@ public sealed class SettingsManager if (preselection != ChatTemplate.NO_CHAT_TEMPLATE) return preselection; - preselection = this.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id.Equals(this.ConfigurationData.App.PreselectedChatTemplate, StringComparison.OrdinalIgnoreCase)); - return preselection ?? ChatTemplate.NO_CHAT_TEMPLATE; + return this.GetChatTemplateById(this.ConfigurationData.App.PreselectedChatTemplate); + } + + public Profile GetProfileById(string? profileId) + { + if (string.IsNullOrWhiteSpace(profileId)) + return Profile.NO_PROFILE; + + if (string.Equals(profileId, Profile.NO_PROFILE.Id, StringComparison.OrdinalIgnoreCase)) + return Profile.NO_PROFILE; + + return this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id.Equals(profileId, StringComparison.OrdinalIgnoreCase)) ?? Profile.NO_PROFILE; + } + + public ChatTemplate GetChatTemplateById(string? chatTemplateId) + { + if (string.IsNullOrWhiteSpace(chatTemplateId)) + return ChatTemplate.NO_CHAT_TEMPLATE; + + if (string.Equals(chatTemplateId, ChatTemplate.NO_CHAT_TEMPLATE.Id, StringComparison.OrdinalIgnoreCase)) + return ChatTemplate.NO_CHAT_TEMPLATE; + + return this.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id.Equals(chatTemplateId, StringComparison.OrdinalIgnoreCase)) ?? ChatTemplate.NO_CHAT_TEMPLATE; } public ConfidenceLevel GetConfiguredConfidenceLevel(LLMProviders llmProvider) diff --git a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs index bd48dbc5..b95ab1cb 100644 --- a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs +++ b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs @@ -169,7 +169,7 @@ public static class ComponentsExtensions public static ChatTemplate PreselectedChatTemplate(this Components component, SettingsManager settingsManager) => component switch { - Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Chat.PreselectedChatTemplate) ?? ChatTemplate.NO_CHAT_TEMPLATE : ChatTemplate.NO_CHAT_TEMPLATE, + Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.GetChatTemplateById(settingsManager.ConfigurationData.Chat.PreselectedChatTemplate) : ChatTemplate.NO_CHAT_TEMPLATE, _ => ChatTemplate.NO_CHAT_TEMPLATE, };