diff --git a/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs b/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs index 19cd7183..1f4255c3 100644 --- a/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs +++ b/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs @@ -31,9 +31,9 @@ public partial class AssistantDynamic : AssistantBaseCore protected override string SubmitText => this.submitText; protected override Func SubmitAction => this.Submit; protected override bool SubmitDisabled => this.isSecurityBlocked; - // Dynamic assistants do not have dedicated settings yet. - // Reuse chat-level provider filtering/preselection instead of NONE. - protected override Tools.Components Component => Tools.Components.CHAT; + // Dynamic assistants do not have dedicated settings yet. Their internal identity keeps their + // session and media state separate while ComponentsExtensions derives their defaults from chat. + protected override Tools.Components Component => Tools.Components.DYNAMIC_ASSISTANT; /// /// Gets the plugin ID as the assistant session instance ID. diff --git a/app/MindWork AI Studio/Pages/Assistants.razor b/app/MindWork AI Studio/Pages/Assistants.razor index 26acd14d..7e622c37 100644 --- a/app/MindWork AI Studio/Pages/Assistants.razor +++ b/app/MindWork AI Studio/Pages/Assistants.razor @@ -31,6 +31,7 @@ var launchLink = assistantPlugin.StartsChatDirectly ? string.Empty : $"{Routes.ASSISTANT_DYNAMIC}?assistantId={assistantPlugin.Id}"; var availablePlugin = PluginFactory.AvailablePlugins.OfType().FirstOrDefault(plugin => plugin.Id == assistantPlugin.Id); - \ No newline at end of file + diff --git a/app/MindWork AI Studio/Tools/AssistantVisibilityExtensions.cs b/app/MindWork AI Studio/Tools/AssistantVisibilityExtensions.cs index 51066283..0c2c0acc 100644 --- a/app/MindWork AI Studio/Tools/AssistantVisibilityExtensions.cs +++ b/app/MindWork AI Studio/Tools/AssistantVisibilityExtensions.cs @@ -41,6 +41,12 @@ public static class AssistantVisibilityExtensions return true; } + // Dynamic assistants are controlled through plugin activation and their security state. + // The Assistant Builder is controlled through its preview feature. Neither belongs to the + // built-in assistant visibility list, so both are expected to be visible at this point. + if (component is Components.DYNAMIC_ASSISTANT or Components.META_ASSISTANT) + return true; + // Map Components enum to ConfigurableAssistant enum: var configurableAssistant = component switch { diff --git a/app/MindWork AI Studio/Tools/Components.cs b/app/MindWork AI Studio/Tools/Components.cs index 2b5299c1..9a2d05a3 100644 --- a/app/MindWork AI Studio/Tools/Components.cs +++ b/app/MindWork AI Studio/Tools/Components.cs @@ -28,6 +28,10 @@ public enum Components // ReSharper restore InconsistentNaming CHAT, + + // Internal identity for plugin-provided assistants. Its defaults are derived from CHAT, + // but it remains separate from the built-in chat component and its session state. + DYNAMIC_ASSISTANT, WRITER, APP_SETTINGS, @@ -37,4 +41,4 @@ public enum Components AGENT_ASSISTANT_PLUGIN_AUDIT, LOG_VIEWER_ASSISTANT, VISUAL_BRIEFING_ASSISTANT, -} \ No newline at end of file +} diff --git a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs index 8e1501aa..d9477fc4 100644 --- a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs +++ b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs @@ -30,16 +30,17 @@ public static class ComponentsExtensions /// blocks starting another one and inactive sessions can be cleared as a group. /// /// - /// Components return false for two different reasons. The chat has no assistant sessions - /// at all. The visual briefing assistant keys its sessions per briefing, so it owns one slot per - /// stored briefing rather than one per component. Both must be excluded from the single-slot - /// checks, which is why this is a capability and not a component comparison. + /// Components return false for three different reasons. The chat has no assistant sessions + /// at all. Dynamic assistants key their sessions per plugin. The visual briefing assistant keys + /// its sessions per briefing, so it owns one slot per stored briefing rather than one per + /// component. All must be excluded from the single-slot checks, which is why this is a + /// capability and not a component comparison. /// /// The component to look up. /// true when the component owns exactly one session slot. public static bool HasSingleSessionSlot(this Components component) => component switch { - Components.CHAT => false, + Components.CHAT or Components.DYNAMIC_ASSISTANT => false, Components.VISUAL_BRIEFING_ASSISTANT => false, _ => true, @@ -60,6 +61,7 @@ public static class ComponentsExtensions public static bool AllowSendTo(this Components component) => component switch { Components.NONE => false, + Components.DYNAMIC_ASSISTANT => false, Components.ERI_ASSISTANT => false, Components.BIAS_DAY_ASSISTANT => false, @@ -186,6 +188,7 @@ public static class ComponentsExtensions // The provider is selected per policy instead. We do this inside the Document Analysis Assistant component. Components.DOCUMENT_ANALYSIS_ASSISTANT => Settings.Provider.NONE, + Components.DYNAMIC_ASSISTANT => Components.CHAT.PreselectedProvider(settingsManager), Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Chat.PreselectedProvider) : null, Components.AGENT_TEXT_CONTENT_CLEANER => settingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider) : null, @@ -212,6 +215,7 @@ public static class ComponentsExtensions Components.ERI_ASSISTANT => settingsManager.ConfigurationData.ERI.PreselectOptions ? settingsManager.ConfigurationData.ERI.PreselectedProfile : string.Empty, Components.SLIDE_BUILDER_ASSISTANT => settingsManager.ConfigurationData.SlideBuilder.PreselectOptions ? settingsManager.ConfigurationData.SlideBuilder.PreselectedProfile : string.Empty, Components.VISUAL_BRIEFING_ASSISTANT => settingsManager.ConfigurationData.VisualBriefing.PreselectedProfile, + Components.DYNAMIC_ASSISTANT => (string)Components.CHAT.GetProfilePreselection(settingsManager), Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.Chat.PreselectedProfile : string.Empty, // The Document Analysis Assistant does not have a preselected profile at the component level. @@ -226,6 +230,7 @@ public static class ComponentsExtensions public static ChatTemplate PreselectedChatTemplate(this Components component, SettingsManager settingsManager) => component switch { + Components.DYNAMIC_ASSISTANT => Components.CHAT.PreselectedChatTemplate(settingsManager), Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.GetChatTemplateById(settingsManager.ConfigurationData.Chat.PreselectedChatTemplate) : ChatTemplate.NO_CHAT_TEMPLATE, _ => ChatTemplate.NO_CHAT_TEMPLATE,