diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
index 039f0e8b..232abd1e 100644
--- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
+++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
@@ -46,6 +46,15 @@ LANG_NAME = "English (United States)"
UI_TEXT_CONTENT = {}
+-- Self-hosted
+UI_TEXT_CONTENT["::LLMPROVIDERSEXTENSIONS::T146444217"] = "Self-hosted"
+
+-- No provider selected
+UI_TEXT_CONTENT["::LLMPROVIDERSEXTENSIONS::T2897045472"] = "No provider selected"
+
+-- Unknown
+UI_TEXT_CONTENT["::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Unknown"
+
-- No audit provider is configured.
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2034826200"] = "No audit provider is configured."
@@ -3514,6 +3523,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3227981830"] = "Using s
-- Add a message
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3372872324"] = "Add a message"
+-- Close
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3448155331"] = "Close"
+
-- Unsupported content type
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3570316759"] = "Unsupported content type"
@@ -4294,6 +4306,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3243902394"] = "The profile
-- Profile Name
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3392578705"] = "Profile Name"
+-- Close
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3448155331"] = "Close"
+
-- Please enter what the LLM should know about you and/or what actions it should take.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3708405102"] = "Please enter what the LLM should know about you and/or what actions it should take."
@@ -4813,6 +4828,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T14695
-- Add Chat Template
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T1548314416"] = "Add Chat Template"
+-- View
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T1582017048"] = "View"
+
-- Note: This advanced feature is designed for users familiar with prompt engineering concepts. Furthermore, you have to make sure yourself that your chosen provider supports the use of assistant prompts.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T1909110760"] = "Note: This advanced feature is designed for users familiar with prompt engineering concepts. Furthermore, you have to make sure yourself that your chosen provider supports the use of assistant prompts."
@@ -4852,6 +4870,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T38650
-- Delete Chat Template
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T4025180906"] = "Delete Chat Template"
+-- View Chat Template
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T4042112076"] = "View Chat Template"
+
-- Export Chat Template
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T491504763"] = "Export Chat Template"
@@ -5260,6 +5281,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T143353473
-- Delete
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T1469573738"] = "Delete"
+-- View
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T1582017048"] = "View"
+
-- Your Profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T2378610256"] = "Your Profiles"
@@ -5284,6 +5308,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T405841465
-- Store personal data about yourself in various profiles so that the AIs know your personal context. This saves you from having to explain your context each time, for example, in every chat. When you have different roles, you can create a profile for each role.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T4125557797"] = "Store personal data about yourself in various profiles so that the AIs know your personal context. This saves you from having to explain your context each time, for example, in every chat. When you have different roles, you can create a profile for each role."
+-- View Profile
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T4219233997"] = "View Profile"
+
-- Add Profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T4248067241"] = "Add Profile"
@@ -6721,15 +6748,6 @@ UI_TEXT_CONTENT["AISTUDIO::PROVIDER::CONFIDENCELEVELEXTENSIONS::T3188327965"] =
-- Very Low
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::CONFIDENCELEVELEXTENSIONS::T786675843"] = "Very Low"
--- Self-hosted
-UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T146444217"] = "Self-hosted"
-
--- No provider selected
-UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T2897045472"] = "No provider selected"
-
--- Unknown
-UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Unknown"
-
-- no model selected
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODEL::T2234274832"] = "no model selected"
@@ -7870,6 +7888,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::PANDOCAVAILABILITYSERVICE::T25964655
-- Failed to store the secret data due to an API issue.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T1110203516"] = "Failed to store the secret data due to an API issue."
+-- Failed to store the API key due to an API issue.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T1704298921"] = "Failed to store the API key due to an API issue."
+
-- Failed to delete the secret data due to an API issue.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T2303057928"] = "Failed to delete the secret data due to an API issue."
diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor b/app/MindWork AI Studio/Components/AttachDocuments.razor
index bc66f9c2..e96825c3 100644
--- a/app/MindWork AI Studio/Components/AttachDocuments.razor
+++ b/app/MindWork AI Studio/Components/AttachDocuments.razor
@@ -52,29 +52,42 @@
}
else
{
-
-
- @T("Drag and drop files into the marked area or click here to attach documents: ")
-
-
- @T("Add file")
-
-
+ @if (!this.Disabled)
+ {
+
+
+ @T("Drag and drop files into the marked area or click here to attach documents: ")
+
+
+ @T("Add file")
+
+
+ }
@foreach (var fileAttachment in this.DocumentPaths)
{
-
+ @if (this.Disabled)
+ {
+
+ }
+ else
+ {
+
+ }
}
-
- @T("Clear file list")
-
+ @if (!this.Disabled)
+ {
+
+ @T("Clear file list")
+
+ }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs
index acfc0dd2..dc72d2e9 100644
--- a/app/MindWork AI Studio/Components/AttachDocuments.razor.cs
+++ b/app/MindWork AI Studio/Components/AttachDocuments.razor.cs
@@ -14,16 +14,16 @@ using DialogOptions = Dialogs.DialogOptions;
public partial class AttachDocuments : MSGComponentBase
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(AttachDocuments).Namespace, nameof(AttachDocuments));
-
+
[Parameter]
public string Name { get; set; } = string.Empty;
-
+
///
/// On which layer to register the drop area. Higher layers have priority over lower layers.
///
[Parameter]
public int Layer { get; set; }
-
+
///
/// When true, pause catching dropped files. Default is false.
///
@@ -38,16 +38,19 @@ public partial class AttachDocuments : MSGComponentBase
[Parameter]
public Func, Task> OnChange { get; set; } = _ => Task.CompletedTask;
-
+
///
- /// Catch all documents that are hovered over the AI Studio window and not only over the drop zone.
+ /// Catch all documents that are hovered over the AI Studio window and not only over the drop zone.
///
- [Parameter]
+ [Parameter]
public bool CatchAllDocuments { get; set; }
-
+
[Parameter]
public bool UseSmallForm { get; set; }
-
+
+ [Parameter]
+ public bool Disabled { get; set; }
+
///
/// When true, validate media file types before attaching. Default is true. That means that
/// the user cannot attach unsupported media file types when the provider or model does not
@@ -56,16 +59,16 @@ public partial class AttachDocuments : MSGComponentBase
///
[Parameter]
public bool ValidateMediaFileTypes { get; set; } = true;
-
+
[Parameter]
public AIStudio.Settings.Provider? Provider { get; set; }
-
+
[Inject]
private ILogger Logger { get; set; } = null!;
-
+
[Inject]
private RustService RustService { get; init; } = null!;
-
+
[Inject]
private IDialogService DialogService { get; init; } = null!;
@@ -74,17 +77,17 @@ public partial class AttachDocuments : MSGComponentBase
private const Placement TOOLBAR_TOOLTIP_PLACEMENT = Placement.Top;
private static readonly string DROP_FILES_HERE_TEXT = TB("Drop files here to attach them.");
-
+
private uint numDropAreasAboveThis;
private bool isComponentHovered;
private bool isDraggingOver;
-
+
#region Overrides of MSGComponentBase
protected override async Task OnInitializedAsync()
{
this.ApplyFilters([], [ Event.TAURI_EVENT_RECEIVED, Event.REGISTER_FILE_DROP_AREA, Event.UNREGISTER_FILE_DROP_AREA ]);
-
+
// Register this drop area:
await this.MessageBus.SendMessage(this, Event.REGISTER_FILE_DROP_AREA, this.Layer);
await base.OnInitializedAsync();
@@ -92,6 +95,9 @@ public partial class AttachDocuments : MSGComponentBase
protected override async Task ProcessIncomingMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
{
+ if (this.Disabled && triggeredEvent == Event.TAURI_EVENT_RECEIVED)
+ return;
+
switch (triggeredEvent)
{
case Event.REGISTER_FILE_DROP_AREA when sendingComponent != this:
@@ -111,7 +117,7 @@ public partial class AttachDocuments : MSGComponentBase
{
if(this.numDropAreasAboveThis > 0)
this.numDropAreasAboveThis--;
-
+
if(this.numDropAreasAboveThis is 0)
this.PauseCatchingDrops = false;
}
@@ -122,40 +128,40 @@ public partial class AttachDocuments : MSGComponentBase
case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_HOVERED }:
if(this.PauseCatchingDrops)
return;
-
+
if(!this.isComponentHovered && !this.CatchAllDocuments)
{
this.Logger.LogDebug("Attach documents component '{Name}' is not hovered, ignoring file drop hovered event.", this.Name);
return;
}
-
+
this.isDraggingOver = true;
this.SetDragClass();
this.StateHasChanged();
break;
-
+
case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_CANCELED }:
if(this.PauseCatchingDrops)
return;
-
+
this.isDraggingOver = false;
this.StateHasChanged();
break;
-
+
case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.WINDOW_NOT_FOCUSED }:
if(this.PauseCatchingDrops)
return;
-
+
this.isDraggingOver = false;
this.isComponentHovered = false;
this.ClearDragClass();
this.StateHasChanged();
break;
-
+
case Event.TAURI_EVENT_RECEIVED when data is TauriEvent { EventType: TauriEventType.FILE_DROP_DROPPED, Payload: var paths }:
if(this.PauseCatchingDrops)
return;
-
+
if(!this.isComponentHovered && !this.CatchAllDocuments)
{
this.Logger.LogDebug("Attach documents component '{Name}' is not hovered, ignoring file drop dropped event.", this.Name);
@@ -197,11 +203,14 @@ public partial class AttachDocuments : MSGComponentBase
#endregion
private const string DEFAULT_DRAG_CLASS = "relative rounded-lg border-2 border-dashed pa-4 mt-4 mud-width-full mud-height-full";
-
+
private string dragClass = DEFAULT_DRAG_CLASS;
-
+
private async Task AddFilesManually()
{
+ if (this.Disabled)
+ return;
+
// Ensure that Pandoc is installed and ready:
var pandocState = await this.PandocAvailabilityService.EnsureAvailabilityAsync(
showSuccessMessage: false,
@@ -228,43 +237,49 @@ public partial class AttachDocuments : MSGComponentBase
this.DocumentPaths.Add(FileAttachment.FromPath(selectedFilePath));
}
-
+
await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths);
await this.OnChange(this.DocumentPaths);
}
-
+
private async Task OpenAttachmentsDialog()
{
+ if (this.Disabled)
+ return;
+
this.DocumentPaths = await ReviewAttachmentsDialog.OpenDialogAsync(this.DialogService, this.DocumentPaths);
}
private async Task ClearAllFiles()
{
+ if (this.Disabled)
+ return;
+
this.DocumentPaths.Clear();
await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths);
await this.OnChange(this.DocumentPaths);
}
private void SetDragClass() => this.dragClass = $"{DEFAULT_DRAG_CLASS} mud-border-primary border-4";
-
+
private void ClearDragClass() => this.dragClass = DEFAULT_DRAG_CLASS;
-
+
private void OnMouseEnter(EventArgs _)
{
- if(this.PauseCatchingDrops)
+ if(this.Disabled || this.PauseCatchingDrops)
return;
-
+
this.Logger.LogDebug("Attach documents component '{Name}' is hovered.", this.Name);
this.isComponentHovered = true;
this.SetDragClass();
this.StateHasChanged();
}
-
+
private void OnMouseLeave(EventArgs _)
{
- if(this.PauseCatchingDrops)
+ if(this.Disabled || this.PauseCatchingDrops)
return;
-
+
this.Logger.LogDebug("Attach documents component '{Name}' is no longer hovered.", this.Name);
this.isComponentHovered = false;
this.ClearDragClass();
@@ -273,6 +288,9 @@ public partial class AttachDocuments : MSGComponentBase
private async Task RemoveDocument(FileAttachment fileAttachment)
{
+ if (this.Disabled)
+ return;
+
this.DocumentPaths.Remove(fileAttachment);
await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths);
diff --git a/app/MindWork AI Studio/Components/ChatTemplateSelection.razor b/app/MindWork AI Studio/Components/ChatTemplateSelection.razor
index edfb9b41..6fea9a4d 100644
--- a/app/MindWork AI Studio/Components/ChatTemplateSelection.razor
+++ b/app/MindWork AI Studio/Components/ChatTemplateSelection.razor
@@ -6,7 +6,7 @@
@if (this.CurrentChatTemplate != ChatTemplate.NO_CHAT_TEMPLATE)
{
-
+
@this.CurrentChatTemplate.GetSafeName()
}
@@ -22,7 +22,7 @@
@foreach (var chatTemplate in this.SettingsManager.ConfigurationData.ChatTemplates.GetAllChatTemplates())
{
-
+
@chatTemplate.GetSafeName()
}
diff --git a/app/MindWork AI Studio/Components/ChatTemplateSelection.razor.cs b/app/MindWork AI Studio/Components/ChatTemplateSelection.razor.cs
index 25b72e11..bf3eaa99 100644
--- a/app/MindWork AI Studio/Components/ChatTemplateSelection.razor.cs
+++ b/app/MindWork AI Studio/Components/ChatTemplateSelection.razor.cs
@@ -11,13 +11,13 @@ public partial class ChatTemplateSelection : MSGComponentBase
{
[Parameter]
public ChatTemplate CurrentChatTemplate { get; set; } = ChatTemplate.NO_CHAT_TEMPLATE;
-
+
[Parameter]
public bool CanChatThreadBeUsedForTemplate { get; set; }
-
+
[Parameter]
public ChatThread? CurrentChatThread { get; set; }
-
+
[Parameter]
public EventCallback CurrentChatTemplateChanged { get; set; }
@@ -26,24 +26,32 @@ public partial class ChatTemplateSelection : MSGComponentBase
[Parameter]
public string MarginRight { get; set; } = string.Empty;
-
+
[Inject]
private IDialogService DialogService { get; init; } = null!;
-
+
private string MarginClass => $"{this.MarginLeft} {this.MarginRight}";
-
+
+ private string ChatTemplateIcon(ChatTemplate chatTemplate)
+ {
+ if (chatTemplate.IsEnterpriseConfiguration)
+ return Icons.Material.Filled.Business;
+
+ return Icons.Material.Filled.RateReview;
+ }
+
private async Task SelectionChanged(ChatTemplate chatTemplate)
{
this.CurrentChatTemplate = chatTemplate;
await this.CurrentChatTemplateChanged.InvokeAsync(chatTemplate);
}
-
+
private async Task OpenSettingsDialog()
{
var dialogParameters = new DialogParameters();
await this.DialogService.ShowAsync(T("Open Chat Template Options"), dialogParameters, DialogOptions.FULLSCREEN);
}
-
+
private async Task CreateNewChatTemplateFromChat()
{
var dialogParameters = new DialogParameters
diff --git a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor
index d13a44bb..8080114e 100644
--- a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor
@@ -10,7 +10,7 @@
@T("The name of the chat template is mandatory. Each chat template must have a unique name.")
-
+
@* ReSharper disable once CSharpWarnings::CS8974 *@
-
+
@T("System Prompt")
@@ -47,16 +48,17 @@
Class="mb-3"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
HelperText="@T("Tell the AI your system prompt.")"
+ ReadOnly="@this.IsReadOnly"
/>
-
+
@T("Are you unsure which system prompt to use? You might start with the default system prompt that AI Studio uses for all chats.")
-
+
@T("Use the default system prompt")
-
-
+
+
@T("Predefined User Input")
@@ -77,6 +79,7 @@
Class="mb-3"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
HelperText="@T("Tell the AI your predefined user input.")"
+ ReadOnly="@this.IsReadOnly"
/>
@@ -92,6 +95,7 @@
UseSmallForm="false"
CatchAllDocuments="true"
ValidateMediaFileTypes="false"
+ Disabled="@this.IsReadOnly"
/>
@@ -100,8 +104,8 @@
@T("Using some chat templates in tandem with profiles might cause issues. Therefore, you might prohibit the usage of profiles here.")
-
-
+
+
@T("Example Conversation")
@@ -129,18 +133,18 @@
case ContentText textContent:
break;
-
+
case ContentImage { SourceType: ContentImageSource.URL or ContentImageSource.LOCAL_PATH } imageContent:
break;
-
+
default:
@T("Unsupported content type")
break;
}
- @if (!this.isInlineEditOnGoing)
+ @if (!this.isInlineEditOnGoing && !this.IsReadOnly)
{
@@ -153,22 +157,29 @@
-
- @foreach (var role in ChatRoles.ChatTemplateRoles())
- {
-
- @role.ToChatTemplateName()
-
- }
-
+ @if (this.IsReadOnly)
+ {
+ @context.Role.ToChatTemplateName()
+ }
+ else
+ {
+
+ @foreach (var role in ChatRoles.ChatTemplateRoles())
+ {
+
+ @role.ToChatTemplateName()
+
+ }
+
+ }
@switch(context.Content)
{
case ContentText textContent:
-
+
break;
-
+
default:
@T("Only text content is supported in the editing mode yet.")
@@ -182,8 +193,8 @@
-
- @if (!this.isInlineEditOnGoing)
+
+ @if (!this.isInlineEditOnGoing && !this.IsReadOnly)
{
@T("Add a message")
@@ -193,22 +204,31 @@
-
- @T("Cancel")
-
-
- @if (!this.isInlineEditOnGoing)
+ @if (this.IsReadOnly)
{
-
- @if (this.IsEditing)
- {
- @T("Update")
- }
- else
- {
- @T("Add")
- }
+
+ @T("Close")
}
+ else
+ {
+
+ @T("Cancel")
+
+
+ @if (!this.isInlineEditOnGoing)
+ {
+
+ @if (this.IsEditing)
+ {
+ @T("Update")
+ }
+ else
+ {
+ @T("Add")
+ }
+
+ }
+ }
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs
index cbc438cf..24d0b0e7 100644
--- a/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/ChatTemplateDialog.razor.cs
@@ -16,37 +16,40 @@ public partial class ChatTemplateDialog : MSGComponentBase
///
[Parameter]
public uint DataNum { get; set; }
-
+
///
/// The chat template's ID.
///
[Parameter]
public string DataId { get; set; } = Guid.NewGuid().ToString();
-
+
///
/// The chat template name chosen by the user.
///
[Parameter]
public string DataName { get; set; } = string.Empty;
-
+
///
/// What is the system prompt?
///
[Parameter]
public string DataSystemPrompt { get; set; } = string.Empty;
-
+
///
/// What is the predefined user prompt?
///
[Parameter]
public string PredefinedUserPrompt { get; set; } = string.Empty;
-
+
///
/// Should the dialog be in editing mode?
///
[Parameter]
public bool IsEditing { get; init; }
-
+
+ [Parameter]
+ public bool IsReadOnly { get; init; }
+
[Parameter]
public IReadOnlyCollection ExampleConversation { get; init; } = [];
@@ -55,23 +58,23 @@ public partial class ChatTemplateDialog : MSGComponentBase
[Parameter]
public bool AllowProfileUsage { get; set; } = true;
-
- [Parameter]
+
+ [Parameter]
public bool CreateFromExistingChatThread { get; set; }
-
- [Parameter]
+
+ [Parameter]
public ChatThread? ExistingChatThread { get; set; }
-
+
[Inject]
private ILogger Logger { get; init; } = null!;
-
+
private static readonly Dictionary SPELLCHECK_ATTRIBUTES = new();
-
+
///
/// The list of used chat template names. We need this to check for uniqueness.
///
private List UsedNames { get; set; } = [];
-
+
private bool dataIsValid;
private List dataExampleConversation = [];
private HashSet fileAttachments = [];
@@ -80,20 +83,20 @@ public partial class ChatTemplateDialog : MSGComponentBase
private bool isInlineEditOnGoing;
private ContentBlock? messageEntryBeforeEdit;
-
+
// We get the form reference from Blazor code to validate it manually:
private MudForm form = null!;
-
+
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
// Configure the spellchecking for the instance name input:
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
-
+
// Load the used instance names:
this.UsedNames = this.SettingsManager.ConfigurationData.ChatTemplates.Select(x => x.Name.ToLowerInvariant()).ToList();
-
+
// When editing, we need to load the data:
if(this.IsEditing)
{
@@ -108,7 +111,7 @@ public partial class ChatTemplateDialog : MSGComponentBase
this.dataExampleConversation = this.ExistingChatThread.Blocks.Select(n => n.DeepClone(true)).ToList();
this.DataName = this.ExistingChatThread.Name;
}
-
+
await base.OnInitializedAsync();
}
@@ -118,7 +121,7 @@ public partial class ChatTemplateDialog : MSGComponentBase
// We don't want to show validation errors when the user opens the dialog.
if(!this.IsEditing && firstRender)
this.form.ResetValidation();
-
+
await base.OnAfterRenderAsync(firstRender);
}
@@ -128,28 +131,34 @@ public partial class ChatTemplateDialog : MSGComponentBase
{
Num = this.DataNum,
Id = this.DataId,
-
+
Name = this.DataName,
SystemPrompt = this.DataSystemPrompt,
PredefinedUserPrompt = this.PredefinedUserPrompt,
ExampleConversation = this.dataExampleConversation,
FileAttachments = this.fileAttachments.Select(attachment => attachment.Normalize()).ToList(),
AllowProfileUsage = this.AllowProfileUsage,
-
+
EnterpriseConfigurationPluginId = Guid.Empty,
IsEnterpriseConfiguration = false,
};
private void RemoveMessage(ContentBlock item)
{
+ if (this.IsReadOnly)
+ return;
+
this.dataExampleConversation.Remove(item);
}
private void AddMessageToEnd()
{
+ if (this.IsReadOnly)
+ return;
+
var newEntry = new ContentBlock
{
- Role = this.dataExampleConversation.Count is 0 ? ChatRole.USER : this.dataExampleConversation.Last().Role.SelectNextRoleForTemplate(),
+ Role = this.dataExampleConversation.Count is 0 ? ChatRole.USER : this.dataExampleConversation.Last().Role.SelectNextRoleForTemplate(),
Content = new ContentText(),
ContentType = ContentType.TEXT,
HideFromUser = true,
@@ -161,6 +170,9 @@ public partial class ChatTemplateDialog : MSGComponentBase
private void AddMessageBelow(ContentBlock currentItem)
{
+ if (this.IsReadOnly)
+ return;
+
var insertedEntry = new ContentBlock
{
Role = this.dataExampleConversation.Count is 0 ? ChatRole.USER : this.dataExampleConversation.Last().Role.SelectNextRoleForTemplate(),
@@ -169,7 +181,7 @@ public partial class ChatTemplateDialog : MSGComponentBase
HideFromUser = true,
Time = DateTimeOffset.Now,
};
-
+
// The rest of the method remains the same:
var index = this.dataExampleConversation.IndexOf(currentItem);
if (index >= 0)
@@ -177,71 +189,83 @@ public partial class ChatTemplateDialog : MSGComponentBase
else
this.dataExampleConversation.Add(insertedEntry);
}
-
+
private void BackupItem(object? element)
{
+ if (this.IsReadOnly)
+ return;
+
this.isInlineEditOnGoing = true;
this.messageEntryBeforeEdit = element switch
{
ContentBlock block => block.DeepClone(),
_ => null,
};
-
+
this.StateHasChanged();
}
private void ResetItem(object? element)
{
+ if (this.IsReadOnly)
+ return;
+
this.isInlineEditOnGoing = false;
switch (element)
{
case ContentBlock block:
if (this.messageEntryBeforeEdit is null)
return; // No backup to restore from
-
+
block.Content = this.messageEntryBeforeEdit.Content?.DeepClone();
block.Role = this.messageEntryBeforeEdit.Role;
break;
}
-
+
this.StateHasChanged();
}
private void CommitInlineEdit(object? element)
{
+ if (this.IsReadOnly)
+ return;
+
this.isInlineEditOnGoing = false;
this.StateHasChanged();
}
-
+
private async Task Store()
{
+ if (this.IsReadOnly)
+ return;
+
await this.form.Validate();
-
+
// When the data is not valid, we don't store it:
if (!this.dataIsValid)
return;
-
+
// When an inline edit is ongoing, we cannot store the data:
if (this.isInlineEditOnGoing)
return;
-
+
// Use the data model to store the chat template.
// We just return this data to the parent component:
var addedChatTemplateSettings = this.CreateChatTemplateSettings();
-
+
if(this.IsEditing)
this.Logger.LogInformation($"Edited chat template '{addedChatTemplateSettings.Name}'.");
else
this.Logger.LogInformation($"Created chat template '{addedChatTemplateSettings.Name}'.");
-
+
this.MudDialog.Close(DialogResult.Ok(addedChatTemplateSettings));
}
-
+
private string? ValidateExampleTextMessage(string message)
{
if (string.IsNullOrWhiteSpace(message))
return T("Please enter a message for the example conversation.");
-
+
return null;
}
@@ -249,20 +273,23 @@ public partial class ChatTemplateDialog : MSGComponentBase
{
if (string.IsNullOrWhiteSpace(name))
return T("Please enter a name for the chat template.");
-
+
if (name.Length > 40)
return T("The chat template name must not exceed 40 characters.");
-
+
// The instance name must be unique:
var lowerName = name.ToLowerInvariant();
if (lowerName != this.dataEditingPreviousName && this.UsedNames.Contains(lowerName))
return T("The chat template name must be unique; the chosen name is already in use.");
-
+
return null;
}
private void UseDefaultSystemPrompt()
{
+ if (this.IsReadOnly)
+ return;
+
this.DataSystemPrompt = SystemPrompts.DEFAULT;
}
diff --git a/app/MindWork AI Studio/Dialogs/ProfileDialog.razor b/app/MindWork AI Studio/Dialogs/ProfileDialog.razor
index b9e4e1e3..a711e084 100644
--- a/app/MindWork AI Studio/Dialogs/ProfileDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/ProfileDialog.razor
@@ -27,6 +27,7 @@
AdornmentColor="Color.Info"
Validation="@this.ValidateName"
Variant="Variant.Outlined"
+ ReadOnly="@this.IsReadOnly"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
/>
@@ -44,8 +45,9 @@
MaxLines="12"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
HelperText="@T("Tell the AI something about yourself. What is your profession? How experienced are you in this profession? Which technologies do you like?")"
+ ReadOnly="@this.IsReadOnly"
/>
-
+
-
+
@T("Please be aware that your profile info becomes part of the system prompt. This means it uses up context space — the “memory” the LLM uses to understand and respond to your request. If your profile is extremely long, the LLM may struggle to focus on your actual task.")
@@ -73,18 +76,27 @@
-
- @T("Cancel")
-
-
- @if(this.IsEditing)
- {
- @T("Update")
- }
- else
- {
- @T("Add")
- }
-
+ @if (this.IsReadOnly)
+ {
+
+ @T("Close")
+
+ }
+ else
+ {
+
+ @T("Cancel")
+
+
+ @if(this.IsEditing)
+ {
+ @T("Update")
+ }
+ else
+ {
+ @T("Add")
+ }
+
+ }
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Dialogs/ProfileDialog.razor.cs b/app/MindWork AI Studio/Dialogs/ProfileDialog.razor.cs
index 54fbb2b8..ba2dfff8 100644
--- a/app/MindWork AI Studio/Dialogs/ProfileDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/ProfileDialog.razor.cs
@@ -15,19 +15,19 @@ public partial class ProfileDialog : MSGComponentBase
///
[Parameter]
public uint DataNum { get; set; }
-
+
///
/// The profile's ID.
///
[Parameter]
public string DataId { get; set; } = Guid.NewGuid().ToString();
-
+
///
/// The profile name chosen by the user.
///
[Parameter]
public string DataName { get; set; } = string.Empty;
-
+
///
/// What should the LLM know about you?
///
@@ -39,27 +39,30 @@ public partial class ProfileDialog : MSGComponentBase
///
[Parameter]
public string DataActions { get; set; } = string.Empty;
-
+
///
/// Should the dialog be in editing mode?
///
[Parameter]
public bool IsEditing { get; init; }
-
+
+ [Parameter]
+ public bool IsReadOnly { get; init; }
+
[Inject]
private ILogger Logger { get; init; } = null!;
-
+
private static readonly Dictionary SPELLCHECK_ATTRIBUTES = new();
-
+
///
/// The list of used profile names. We need this to check for uniqueness.
///
private List UsedNames { get; set; } = [];
-
+
private bool dataIsValid;
private string[] dataIssues = [];
private string dataEditingPreviousName = string.Empty;
-
+
// We get the form reference from Blazor code to validate it manually:
private MudForm form = null!;
@@ -70,7 +73,7 @@ public partial class ProfileDialog : MSGComponentBase
Name = this.DataName,
NeedToKnow = this.DataNeedToKnow,
Actions = this.DataActions,
-
+
EnterpriseConfigurationPluginId = Guid.Empty,
IsEnterpriseConfiguration = false,
};
@@ -81,16 +84,16 @@ public partial class ProfileDialog : MSGComponentBase
{
// Configure the spellchecking for the instance name input:
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
-
+
// Load the used instance names:
this.UsedNames = this.SettingsManager.ConfigurationData.Profiles.Select(x => x.Name.ToLowerInvariant()).ToList();
-
+
// When editing, we need to load the data:
if(this.IsEditing)
{
this.dataEditingPreviousName = this.DataName.ToLowerInvariant();
}
-
+
await base.OnInitializedAsync();
}
@@ -100,37 +103,40 @@ public partial class ProfileDialog : MSGComponentBase
// We don't want to show validation errors when the user opens the dialog.
if(!this.IsEditing && firstRender)
this.form.ResetValidation();
-
+
await base.OnAfterRenderAsync(firstRender);
}
#endregion
-
+
private async Task Store()
{
+ if (this.IsReadOnly)
+ return;
+
await this.form.Validate();
-
+
// When the data is not valid, we don't store it:
if (!this.dataIsValid)
return;
-
+
// Use the data model to store the profile.
// We just return this data to the parent component:
var addedProfileSettings = this.CreateProfileSettings();
-
+
if(this.IsEditing)
this.Logger.LogInformation($"Edited profile '{addedProfileSettings.Name}'.");
else
this.Logger.LogInformation($"Created profile '{addedProfileSettings.Name}'.");
-
+
this.MudDialog.Close(DialogResult.Ok(addedProfileSettings));
}
-
+
private string? ValidateNeedToKnow(string text)
{
if (string.IsNullOrWhiteSpace(this.DataNeedToKnow) && string.IsNullOrWhiteSpace(this.DataActions))
return T("Please enter what the LLM should know about you and/or what actions it should take.");
-
+
return null;
}
@@ -138,7 +144,7 @@ public partial class ProfileDialog : MSGComponentBase
{
if (string.IsNullOrWhiteSpace(this.DataNeedToKnow) && string.IsNullOrWhiteSpace(this.DataActions))
return T("Please enter what the LLM should know about you and/or what actions it should take.");
-
+
return null;
}
@@ -146,15 +152,15 @@ public partial class ProfileDialog : MSGComponentBase
{
if (string.IsNullOrWhiteSpace(name))
return T("Please enter a profile name.");
-
+
if (name.Length > 40)
return T("The profile name must not exceed 40 characters.");
-
+
// The instance name must be unique:
var lowerName = name.ToLowerInvariant();
if (lowerName != this.dataEditingPreviousName && this.UsedNames.Contains(lowerName))
return T("The profile name must be unique; the chosen name is already in use.");
-
+
return null;
}
diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor
index 2f8600a8..19680575 100644
--- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor
+++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor
@@ -33,9 +33,14 @@
@if (context.IsEnterpriseConfiguration)
{
-
-
-
+
+
+
+
+
+
+
+
}
else
{
diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs
index 89473518..54a2f631 100644
--- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs
@@ -6,24 +6,24 @@ namespace AIStudio.Dialogs.Settings;
public partial class SettingsDialogChatTemplate : SettingsDialogBase
{
- [Parameter]
+ [Parameter]
public bool CreateTemplateFromExistingChatThread { get; set; }
-
+
[Parameter]
public ChatThread? ExistingChatThread { get; set; }
-
+
#region Overrides of ComponentBase
-
+
///
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
- if (this.CreateTemplateFromExistingChatThread)
+ if (this.CreateTemplateFromExistingChatThread)
await this.AddChatTemplate();
}
#endregion
-
+
private async Task AddChatTemplate()
{
var dialogParameters = new DialogParameters
@@ -41,21 +41,21 @@ public partial class SettingsDialogChatTemplate : SettingsDialogBase
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
-
+
var addedChatTemplate = (ChatTemplate)dialogResult.Data!;
addedChatTemplate = addedChatTemplate with { Num = this.SettingsManager.ConfigurationData.NextChatTemplateNum++ };
-
+
this.SettingsManager.ConfigurationData.ChatTemplates.Add(addedChatTemplate);
-
+
await this.SettingsManager.StoreSettings();
await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED);
}
-
+
private async Task EditChatTemplate(ChatTemplate chatTemplate)
{
if (chatTemplate == ChatTemplate.NO_CHAT_TEMPLATE || chatTemplate.IsEnterpriseConfiguration)
return;
-
+
var dialogParameters = new DialogParameters
{
{ x => x.DataNum, chatTemplate.Num },
@@ -68,34 +68,53 @@ public partial class SettingsDialogChatTemplate : SettingsDialogBase
{ x => x.FileAttachments, chatTemplate.FileAttachments },
{ x => x.AllowProfileUsage, chatTemplate.AllowProfileUsage },
};
-
+
var dialogReference = await this.DialogService.ShowAsync(T("Edit Chat Template"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
-
+
var editedChatTemplate = (ChatTemplate)dialogResult.Data!;
this.SettingsManager.ConfigurationData.ChatTemplates[this.SettingsManager.ConfigurationData.ChatTemplates.IndexOf(chatTemplate)] = editedChatTemplate;
-
+
await this.SettingsManager.StoreSettings();
await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED);
}
+ private async Task ViewChatTemplate(ChatTemplate chatTemplate)
+ {
+ var dialogParameters = new DialogParameters
+ {
+ { x => x.DataNum, chatTemplate.Num },
+ { x => x.DataId, chatTemplate.Id },
+ { x => x.DataName, chatTemplate.Name },
+ { x => x.DataSystemPrompt, chatTemplate.SystemPrompt },
+ { x => x.PredefinedUserPrompt, chatTemplate.PredefinedUserPrompt },
+ { x => x.IsEditing, true },
+ { x => x.IsReadOnly, true },
+ { x => x.ExampleConversation, chatTemplate.ExampleConversation },
+ { x => x.FileAttachments, chatTemplate.FileAttachments },
+ { x => x.AllowProfileUsage, chatTemplate.AllowProfileUsage },
+ };
+
+ await this.DialogService.ShowAsync(T("View Chat Template"), dialogParameters, DialogOptions.FULLSCREEN);
+ }
+
private async Task DeleteChatTemplate(ChatTemplate chatTemplate)
{
var dialogParameters = new DialogParameters
{
{ x => x.Message, string.Format(T("Are you sure you want to delete the chat template '{0}'?"), chatTemplate.Name) },
};
-
+
var dialogReference = await this.DialogService.ShowAsync(T("Delete Chat Template"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
-
+
this.SettingsManager.ConfigurationData.ChatTemplates.Remove(chatTemplate);
await this.SettingsManager.StoreSettings();
-
+
await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED);
}
diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor
index 784bfffc..1af4253c 100644
--- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor
+++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor
@@ -32,9 +32,14 @@
@if (context.IsEnterpriseConfiguration)
{
-
-
-
+
+
+
+
+
+
+
+
}
else
{
diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor.cs
index 4fb6c67a..d5387dc0 100644
--- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor.cs
@@ -10,21 +10,21 @@ public partial class SettingsDialogProfiles : SettingsDialogBase
{
{ x => x.IsEditing, false },
};
-
+
var dialogReference = await this.DialogService.ShowAsync(T("Add Profile"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
-
+
var addedProfile = (Profile)dialogResult.Data!;
addedProfile = addedProfile with { Num = this.SettingsManager.ConfigurationData.NextProfileNum++ };
-
+
this.SettingsManager.ConfigurationData.Profiles.Add(addedProfile);
-
+
await this.SettingsManager.StoreSettings();
await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED);
}
-
+
private async Task EditProfile(Profile profile)
{
var dialogParameters = new DialogParameters
@@ -36,19 +36,35 @@ public partial class SettingsDialogProfiles : SettingsDialogBase
{ x => x.DataActions, profile.Actions },
{ x => x.IsEditing, true },
};
-
+
var dialogReference = await this.DialogService.ShowAsync(T("Edit Profile"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
-
+
var editedProfile = (Profile)dialogResult.Data!;
this.SettingsManager.ConfigurationData.Profiles[this.SettingsManager.ConfigurationData.Profiles.IndexOf(profile)] = editedProfile;
-
+
await this.SettingsManager.StoreSettings();
await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED);
}
+ private async Task ViewProfile(Profile profile)
+ {
+ var dialogParameters = new DialogParameters
+ {
+ { x => x.DataNum, profile.Num },
+ { x => x.DataId, profile.Id },
+ { x => x.DataName, profile.Name },
+ { x => x.DataNeedToKnow, profile.NeedToKnow },
+ { x => x.DataActions, profile.Actions },
+ { x => x.IsEditing, true },
+ { x => x.IsReadOnly, true },
+ };
+
+ await this.DialogService.ShowAsync(T("View Profile"), dialogParameters, DialogOptions.FULLSCREEN);
+ }
+
private async Task ExportProfile(Profile profile)
{
if (!this.SettingsManager.ConfigurationData.App.ShowAdminSettings)
@@ -68,15 +84,15 @@ public partial class SettingsDialogProfiles : SettingsDialogBase
{
{ x => x.Message, string.Format(T("Are you sure you want to delete the profile '{0}'?"), profile.Name) },
};
-
+
var dialogReference = await this.DialogService.ShowAsync(T("Delete Profile"), dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
-
+
this.SettingsManager.ConfigurationData.Profiles.Remove(profile);
await this.SettingsManager.StoreSettings();
-
+
await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED);
}
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua
index eabbcfd9..bd075701 100644
--- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua
+++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua
@@ -48,6 +48,15 @@ LANG_NAME = "Deutsch (Deutschland)"
UI_TEXT_CONTENT = {}
+-- Self-hosted
+UI_TEXT_CONTENT["::LLMPROVIDERSEXTENSIONS::T146444217"] = "Selbst gehostet"
+
+-- No provider selected
+UI_TEXT_CONTENT["::LLMPROVIDERSEXTENSIONS::T2897045472"] = "Kein Anbieter ausgewählt"
+
+-- Unknown
+UI_TEXT_CONTENT["::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Unbekannt"
+
-- No audit provider is configured.
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2034826200"] = "Es ist kein Audit-Anbieter konfiguriert."
@@ -3516,6 +3525,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3227981830"] = "Die gle
-- Add a message
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3372872324"] = "Nachricht hinzufügen"
+-- Close
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3448155331"] = "Schließen"
+
-- Unsupported content type
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3570316759"] = "Nicht unterstützter Inhaltstyp"
@@ -4296,6 +4308,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3243902394"] = "Der Profilna
-- Profile Name
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3392578705"] = "Profilname"
+-- Close
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3448155331"] = "Schließen"
+
-- Please enter what the LLM should know about you and/or what actions it should take.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3708405102"] = "Bitte geben Sie ein, was das LLM über Sie wissen sollte und/oder welche Aktionen es ausführen soll."
@@ -4815,6 +4830,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T14695
-- Add Chat Template
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T1548314416"] = "Chat-Vorlage hinzufügen"
+-- View
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T1582017048"] = "Anzeigen"
+
-- Note: This advanced feature is designed for users familiar with prompt engineering concepts. Furthermore, you have to make sure yourself that your chosen provider supports the use of assistant prompts.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T1909110760"] = "Hinweis: Diese fortgeschrittene Funktion richtet sich an Nutzer, die mit den Grundlagen des Prompt Engineerings vertraut sind. Außerdem müssen Sie selbst sicherstellen, dass Ihr gewählter Anbieter die Verwendung von Assistenten-Prompts unterstützt."
@@ -4854,6 +4872,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T38650
-- Delete Chat Template
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T4025180906"] = "Chat-Vorlage löschen"
+-- View Chat Template
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T4042112076"] = "Chat-Vorlage anzeigen"
+
-- Export Chat Template
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T491504763"] = "Chat-Vorlage exportieren"
@@ -5262,6 +5283,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T143353473
-- Delete
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T1469573738"] = "Löschen"
+-- View
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T1582017048"] = "Anzeigen"
+
-- Your Profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T2378610256"] = "Ihre Profile"
@@ -5286,6 +5310,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T405841465
-- Store personal data about yourself in various profiles so that the AIs know your personal context. This saves you from having to explain your context each time, for example, in every chat. When you have different roles, you can create a profile for each role.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T4125557797"] = "Speichern Sie persönliche Daten über sich in verschiedenen Profilen, damit die KIs ihren persönlichen Kontext kennen. So müssen Sie den Kontext nicht jedes Mal erneut erklären, zum Beispiel in jedem Chat. Wenn Sie verschiedene Rollen haben, können Sie für jede Rolle ein eigenes Profil anlegen."
+-- View Profile
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T4219233997"] = "Profil anzeigen"
+
-- Add Profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T4248067241"] = "Profil hinzufügen"
@@ -6723,15 +6750,6 @@ UI_TEXT_CONTENT["AISTUDIO::PROVIDER::CONFIDENCELEVELEXTENSIONS::T3188327965"] =
-- Very Low
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::CONFIDENCELEVELEXTENSIONS::T786675843"] = "Sehr niedrig"
--- Self-hosted
-UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T146444217"] = "Selbst gehostet"
-
--- No provider selected
-UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T2897045472"] = "Kein Anbieter ausgewählt"
-
--- Unknown
-UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Unbekannt"
-
-- no model selected
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODEL::T2234274832"] = "Kein Modell ausgewählt"
@@ -7872,6 +7890,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::PANDOCAVAILABILITYSERVICE::T25964655
-- Failed to store the secret data due to an API issue.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T1110203516"] = "Fehler beim Speichern der geheimen Daten aufgrund eines API-Problems."
+-- Failed to store the API key due to an API issue.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T1704298921"] = "Fehler beim Speichern des API-Schlüssels aufgrund eines API-Problems."
+
-- Failed to delete the secret data due to an API issue.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T2303057928"] = "Das Löschen der geheimen Daten ist aufgrund eines API-Problems fehlgeschlagen."
diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua
index 6b1fd6f4..df545001 100644
--- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua
+++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua
@@ -48,6 +48,15 @@ LANG_NAME = "English (United States)"
UI_TEXT_CONTENT = {}
+-- Self-hosted
+UI_TEXT_CONTENT["::LLMPROVIDERSEXTENSIONS::T146444217"] = "Self-hosted"
+
+-- No provider selected
+UI_TEXT_CONTENT["::LLMPROVIDERSEXTENSIONS::T2897045472"] = "No provider selected"
+
+-- Unknown
+UI_TEXT_CONTENT["::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Unknown"
+
-- No audit provider is configured.
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2034826200"] = "No audit provider is configured."
@@ -3516,6 +3525,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3227981830"] = "Using s
-- Add a message
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3372872324"] = "Add a message"
+-- Close
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3448155331"] = "Close"
+
-- Unsupported content type
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::CHATTEMPLATEDIALOG::T3570316759"] = "Unsupported content type"
@@ -4296,6 +4308,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3243902394"] = "The profile
-- Profile Name
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3392578705"] = "Profile Name"
+-- Close
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3448155331"] = "Close"
+
-- Please enter what the LLM should know about you and/or what actions it should take.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::PROFILEDIALOG::T3708405102"] = "Please enter what the LLM should know about you and/or what actions it should take."
@@ -4815,6 +4830,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T14695
-- Add Chat Template
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T1548314416"] = "Add Chat Template"
+-- View
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T1582017048"] = "View"
+
-- Note: This advanced feature is designed for users familiar with prompt engineering concepts. Furthermore, you have to make sure yourself that your chosen provider supports the use of assistant prompts.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T1909110760"] = "Note: This advanced feature is designed for users familiar with prompt engineering concepts. Furthermore, you have to make sure yourself that your chosen provider supports the use of assistant prompts."
@@ -4854,6 +4872,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T38650
-- Delete Chat Template
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T4025180906"] = "Delete Chat Template"
+-- View Chat Template
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T4042112076"] = "View Chat Template"
+
-- Export Chat Template
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T491504763"] = "Export Chat Template"
@@ -5262,6 +5283,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T143353473
-- Delete
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T1469573738"] = "Delete"
+-- View
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T1582017048"] = "View"
+
-- Your Profiles
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T2378610256"] = "Your Profiles"
@@ -5286,6 +5310,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T405841465
-- Store personal data about yourself in various profiles so that the AIs know your personal context. This saves you from having to explain your context each time, for example, in every chat. When you have different roles, you can create a profile for each role.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T4125557797"] = "Store personal data about yourself in various profiles so that the AIs know your personal context. This saves you from having to explain your context each time, for example, in every chat. When you have different roles, you can create a profile for each role."
+-- View Profile
+UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T4219233997"] = "View Profile"
+
-- Add Profile
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T4248067241"] = "Add Profile"
@@ -6723,15 +6750,6 @@ UI_TEXT_CONTENT["AISTUDIO::PROVIDER::CONFIDENCELEVELEXTENSIONS::T3188327965"] =
-- Very Low
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::CONFIDENCELEVELEXTENSIONS::T786675843"] = "Very Low"
--- Self-hosted
-UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T146444217"] = "Self-hosted"
-
--- No provider selected
-UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T2897045472"] = "No provider selected"
-
--- Unknown
-UI_TEXT_CONTENT["AISTUDIO::PROVIDER::LLMPROVIDERSEXTENSIONS::T3424652889"] = "Unknown"
-
-- no model selected
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::MODEL::T2234274832"] = "no model selected"
@@ -7872,6 +7890,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::PANDOCAVAILABILITYSERVICE::T25964655
-- Failed to store the secret data due to an API issue.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T1110203516"] = "Failed to store the secret data due to an API issue."
+-- Failed to store the API key due to an API issue.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T1704298921"] = "Failed to store the API key due to an API issue."
+
-- Failed to delete the secret data due to an API issue.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::RUSTSERVICE::T2303057928"] = "Failed to delete the secret data due to an API issue."
diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.6.2.md b/app/MindWork AI Studio/wwwroot/changelog/v26.6.2.md
index 911dfa54..a93e1895 100644
--- a/app/MindWork AI Studio/wwwroot/changelog/v26.6.2.md
+++ b/app/MindWork AI Studio/wwwroot/changelog/v26.6.2.md
@@ -1,2 +1,4 @@
# v26.6.2, build 242 (2026-06-xx xx:xx UTC)
+- Added a read-only view for organization-managed profiles and chat templates, so users can inspect the content while the organization remains in control of changes.
+- Fixed organization-managed chat templates not showing the correct icon in the chat template selection menu.
- Fixed self-hosted provider API keys sometimes being stored under a localized name. AI Studio now uses a stable key name, keeps correct entries working, and automatically migrates known localized entries for LLM, transcription, and embedding providers. Organizations using configuration plugins do not need to change their plugins; affected users who still see an invalid API key warning should open the provider, transcription, or embedding settings and update the API key once.
\ No newline at end of file