diff --git a/app/MindWork AI Studio/Components/DataSourceSelection.razor b/app/MindWork AI Studio/Components/DataSourceSelection.razor
index 11001174..3388b710 100644
--- a/app/MindWork AI Studio/Components/DataSourceSelection.razor
+++ b/app/MindWork AI Studio/Components/DataSourceSelection.razor
@@ -179,13 +179,13 @@ else if (this.SelectionMode is DataSourceSelectionMode.CONFIGURATION_MODE)
}
-
+
@if (this.areDataSourcesEnabled)
{
-
-
-
- this.SelectionChanged(x))" ReadOnly="@this.IsPreselectedDataSourceIdsLocked()">
+
+
+
+ this.SelectionChanged(x))" ReadOnly="@(this.ReadOnly || this.IsPreselectedDataSourceIdsLocked())">
@*
The configuration mode lists what was configured, without filtering it, so no
row here is ever waiting for an index.
diff --git a/app/MindWork AI Studio/Components/DataSourceSelection.razor.cs b/app/MindWork AI Studio/Components/DataSourceSelection.razor.cs
index f1e619c0..170d6a0b 100644
--- a/app/MindWork AI Studio/Components/DataSourceSelection.razor.cs
+++ b/app/MindWork AI Studio/Components/DataSourceSelection.razor.cs
@@ -38,7 +38,28 @@ public partial class DataSourceSelection : MSGComponentBase
[Parameter]
public bool AutoSaveAppSettings { get; set; }
-
+
+ ///
+ /// Shows the options without letting the user change them.
+ ///
+ ///
+ /// For options somebody else decided on, such as those of a chat template an organization
+ /// rolled out. Seeing which data such a chat will search is the point; changing it here is not.
+ ///
+ [Parameter]
+ public bool ReadOnly { get; set; }
+
+ ///
+ /// Whether the options edited here are the data source defaults of the chat.
+ ///
+ ///
+ /// Those defaults can be locked by a configuration plugin, and this component reads the locks
+ /// from the chat settings. Wherever the same options belong to something else — to a chat
+ /// template, say — the locks of the chat defaults have nothing to say about them.
+ ///
+ [Parameter]
+ public bool ConfiguresChatDefaults { get; set; } = true;
+
[Inject]
private DataSourceService DataSourceService { get; init; } = null!;
@@ -334,6 +355,7 @@ public partial class DataSourceSelection : MSGComponentBase
private bool IsPreselectedDataSourcesDisabledLocked()
{
return this.SelectionMode is DataSourceSelectionMode.CONFIGURATION_MODE
+ && this.ConfiguresChatDefaults
&& ManagedConfiguration.TryGet(x => x.Chat, x => x.PreselectedDataSourcesDisabled, out var meta)
&& meta.IsLocked;
}
@@ -341,6 +363,7 @@ public partial class DataSourceSelection : MSGComponentBase
private bool IsPreselectedDataSourcesAutomaticSelectionLocked()
{
return this.SelectionMode is DataSourceSelectionMode.CONFIGURATION_MODE
+ && this.ConfiguresChatDefaults
&& ManagedConfiguration.TryGet(x => x.Chat, x => x.PreselectedDataSourcesAutomaticSelection, out var meta)
&& meta.IsLocked;
}
@@ -348,6 +371,7 @@ public partial class DataSourceSelection : MSGComponentBase
private bool IsPreselectedDataSourcesAutomaticValidationLocked()
{
return this.SelectionMode is DataSourceSelectionMode.CONFIGURATION_MODE
+ && this.ConfiguresChatDefaults
&& ManagedConfiguration.TryGet(x => x.Chat, x => x.PreselectedDataSourcesAutomaticValidation, out var meta)
&& meta.IsLocked;
}
@@ -355,6 +379,7 @@ public partial class DataSourceSelection : MSGComponentBase
private bool IsPreselectedDataSourceIdsLocked()
{
return this.SelectionMode is DataSourceSelectionMode.CONFIGURATION_MODE
+ && this.ConfiguresChatDefaults
&& ManagedConfiguration.TryGet(x => x.Chat, x => x.PreselectedDataSourceIds, out var meta)
&& meta.IsLocked;
}
diff --git a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor
index 638e9b9c..c26d4872 100644
--- a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor
@@ -1,4 +1,5 @@
@using AIStudio.Chat
+@using AIStudio.Settings.DataModel
@inherits MSGComponentBase
@@ -109,6 +110,35 @@
+
+ @T("Tools")
+
+
+ @T("A chat template may decide which tools a chat starts with. Without such a decision, those chats start with the tools you chose as your default in the chat options. Deciding and then picking nothing is a different statement: such chats start with no tool at all, no matter what your default says.")
+
+
+ @if (this.preselectTools)
+ {
+
+
+
+ }
+
+ @if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
+ {
+
+ @T("Data Sources")
+
+
+ @T("The same goes for your data. A chat template may bring its own data source options, which includes leaving the choice of sources to the AI. Without them, those chats start with the data source options from your chat options.")
+
+
+ @if (this.preselectDataSources)
+ {
+
+ }
+ }
+
@T("Example Conversation")
diff --git a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs
index 24d0b0e7..942d2727 100644
--- a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs
@@ -1,6 +1,7 @@
using AIStudio.Chat;
using AIStudio.Components;
using AIStudio.Settings;
+using AIStudio.Settings.DataModel;
using Microsoft.AspNetCore.Components;
@@ -59,6 +60,18 @@ public partial class ChatTemplateDialog : MSGComponentBase
[Parameter]
public bool AllowProfileUsage { get; set; } = true;
+ ///
+ /// The tools this template preselects, or null when it says nothing about tools.
+ ///
+ [Parameter]
+ public HashSet? ToolIds { get; set; }
+
+ ///
+ /// The data source options this template preselects, or null when it says nothing about them.
+ ///
+ [Parameter]
+ public DataSourceOptions? DataSourceOptions { get; set; }
+
[Parameter]
public bool CreateFromExistingChatThread { get; set; }
@@ -78,6 +91,10 @@ public partial class ChatTemplateDialog : MSGComponentBase
private bool dataIsValid;
private List dataExampleConversation = [];
private HashSet fileAttachments = [];
+ private bool preselectTools;
+ private HashSet selectedToolIds = new(StringComparer.Ordinal);
+ private bool preselectDataSources;
+ private DataSourceOptions templateDataSourceOptions = new();
private string[] dataIssues = [];
private string dataEditingPreviousName = string.Empty;
private bool isInlineEditOnGoing;
@@ -97,6 +114,20 @@ public partial class ChatTemplateDialog : MSGComponentBase
// Load the used instance names:
this.UsedNames = this.SettingsManager.ConfigurationData.ChatTemplates.Select(x => x.Name.ToLowerInvariant()).ToList();
+ //
+ // The two switches below carry the third state of the preselection: switched off, this
+ // template says nothing, and a chat started with it uses the defaults from the chat
+ // options. Their working copies live apart from the parameters, so switching a
+ // preselection off and on again does not throw away what was picked.
+ //
+ this.preselectTools = this.ToolIds is not null;
+ this.selectedToolIds = this.ToolIds is null ? new(StringComparer.Ordinal) : new(this.ToolIds, StringComparer.Ordinal);
+ this.preselectDataSources = this.DataSourceOptions is not null;
+
+ // Saying that this template preselects data sources is already the statement that it wants
+ // them, so the switch inside the selection starts on instead of at its usual default:
+ this.templateDataSourceOptions = this.DataSourceOptions?.CreateCopy() ?? new DataSourceOptions { DisableDataSources = false };
+
// When editing, we need to load the data:
if(this.IsEditing)
{
@@ -138,11 +169,15 @@ public partial class ChatTemplateDialog : MSGComponentBase
ExampleConversation = this.dataExampleConversation,
FileAttachments = this.fileAttachments.Select(attachment => attachment.Normalize()).ToList(),
AllowProfileUsage = this.AllowProfileUsage,
+ ToolIds = this.preselectTools ? new HashSet(this.selectedToolIds, StringComparer.Ordinal) : null,
+ DataSourceOptions = this.preselectDataSources ? this.templateDataSourceOptions.CreateCopy() : null,
EnterpriseConfigurationPluginId = Guid.Empty,
IsEnterpriseConfiguration = false,
};
+ private void SetSelectedToolIds(HashSet toolIds) => this.selectedToolIds = toolIds;
+
private void RemoveMessage(ContentBlock item)
{
if (this.IsReadOnly)
diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs
index becd4645..f88d5bf7 100644
--- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs
@@ -69,6 +69,8 @@ public partial class SettingsDialogChatTemplate : SettingsDialogBase
{ x => x.ExampleConversation, chatTemplate.ExampleConversation },
{ x => x.FileAttachments, chatTemplate.FileAttachments },
{ x => x.AllowProfileUsage, chatTemplate.AllowProfileUsage },
+ { x => x.ToolIds, chatTemplate.ToolIds },
+ { x => x.DataSourceOptions, chatTemplate.DataSourceOptions },
};
var dialogReference = await this.DialogService.ShowAsync(T("Edit Chat Template"), dialogParameters, DialogOptions.FULLSCREEN);
@@ -97,6 +99,8 @@ public partial class SettingsDialogChatTemplate : SettingsDialogBase
{ x => x.ExampleConversation, chatTemplate.ExampleConversation },
{ x => x.FileAttachments, chatTemplate.FileAttachments },
{ x => x.AllowProfileUsage, chatTemplate.AllowProfileUsage },
+ { x => x.ToolIds, chatTemplate.ToolIds },
+ { x => x.DataSourceOptions, chatTemplate.DataSourceOptions },
};
await this.DialogService.ShowAsync(T("View Chat Template"), dialogParameters, DialogOptions.FULLSCREEN);