Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
protected override string SubmitText => this.submitText;
protected override Func<Task> 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;

/// <summary>
/// Gets the plugin ID as the assistant session instance ID.
Expand Down
3 changes: 2 additions & 1 deletion app/MindWork AI Studio/Pages/Assistants.razor
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
var launchLink = assistantPlugin.StartsChatDirectly ? string.Empty : $"{Routes.ASSISTANT_DYNAMIC}?assistantId={assistantPlugin.Id}";
var availablePlugin = PluginFactory.AvailablePlugins.OfType<IAvailablePlugin>().FirstOrDefault(plugin => plugin.Id == assistantPlugin.Id);
<AssistantBlock TSettings="NoSettingsPanel"
Component="Components.DYNAMIC_ASSISTANT"
Name="@T(assistantPlugin.AssistantTitle)"
Description="@T(assistantPlugin.Description)"
Icon="@Icons.Material.Filled.FindInPage"
Expand Down Expand Up @@ -79,4 +80,4 @@
</AssistantCategoryBlock>

</InnerScrolling>
</div>
</div>
6 changes: 6 additions & 0 deletions app/MindWork AI Studio/Tools/AssistantVisibilityExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ public static bool IsAssistantVisible(this SettingsManager settingsManager, Comp
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
{
Expand Down
6 changes: 5 additions & 1 deletion app/MindWork AI Studio/Tools/Components.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand All @@ -37,4 +41,4 @@ public enum Components
AGENT_ASSISTANT_PLUGIN_AUDIT,
LOG_VIEWER_ASSISTANT,
VISUAL_BRIEFING_ASSISTANT,
}
}
15 changes: 10 additions & 5 deletions app/MindWork AI Studio/Tools/ComponentsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,17 @@ public static class ComponentsExtensions
/// blocks starting another one and inactive sessions can be cleared as a group.
/// </summary>
/// <remarks>
/// Components return <c>false</c> 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 <c>false</c> 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.
/// </remarks>
/// <param name="component">The component to look up.</param>
/// <returns><c>true</c> when the component owns exactly one session slot.</returns>
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,
Expand All @@ -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,
Expand Down Expand Up @@ -186,6 +188,7 @@ public static AIStudio.Settings.Provider PreselectedProvider(this Components com
// 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,
Expand All @@ -212,6 +215,7 @@ public static ProfilePreselection GetProfilePreselection(this Components compone
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.
Expand All @@ -226,6 +230,7 @@ public static ProfilePreselection GetProfilePreselection(this Components compone

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,
Expand Down