diff --git a/README.md b/README.md
index 6a5f850d..81914d68 100644
--- a/README.md
+++ b/README.md
@@ -214,3 +214,20 @@ MindWork AI Studio is licensed under the `FSL-1.1-MIT` license (functional sourc
For more details, refer to the [LICENSE](LICENSE.md) file. This license structure ensures you have plenty of freedom to use and enjoy the software while protecting our work.
+
+
+
+
+ Trademarks
+
+
+
+The license above covers our own software. It says nothing about the trademarks of other companies, so here is where AI Studio stands on those.
+
+AI Studio ships the logos of the AI providers it supports and shows them next to the matching provider entry, so you can see at a glance which service a provider connects to. All product names, logos, and trademarks are the property of their respective owners. Their use here identifies compatible services and implies no endorsement, sponsorship, or business relationship between MindWork AI Studio and these companies.
+
+Some of these logos come from the [Simple Icons](https://github.com/simple-icons/simple-icons) project, which publishes them under [CC0-1.0](https://github.com/simple-icons/simple-icons/blob/16.21.0/LICENSE.md); the trademarks themselves are not part of that release. The remaining ones were taken from the official brand resources of the respective provider. The source of every single file is documented in [the provider icon notes](app/MindWork%20AI%20Studio/wwwroot/images/provider-icons/README.md). All logos ship with AI Studio and are loaded from your device, so showing one never sends a request to the provider.
+
+Organizations can replace these logos with their own icons through a configuration plugin. When an organization does so, it is responsible for holding the rights to the icons it provides.
+
+
diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
index a989292f..1ffeda02 100644
--- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
+++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
@@ -8320,6 +8320,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1402243995"] = "Updates are mana
-- This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1421513382"] = "This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library."
+-- Trademarks & Brand Assets
+UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1421823619"] = "Trademarks & Brand Assets"
+
-- Copies the allowed host pattern to the clipboard
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1513592659"] = "Copies the allowed host pattern to the clipboard"
@@ -8329,6 +8332,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1533382393"] = "Waiting for the
-- Encryption secret: is not configured
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1560776885"] = "Encryption secret: is not configured"
+-- Organizations can replace these logos with their own icons through a configuration plugin. When your organization does so, it is responsible for holding the rights to the icons it provides.
+UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T158845920"] = "Organizations can replace these logos with their own icons through a configuration plugin. When your organization does so, it is responsible for holding the rights to the icons it provides."
+
-- AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are active.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1596483935"] = "AI Studio runs with an enterprise configuration and configuration servers. The configuration plugins are active."
@@ -8344,6 +8350,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1630237140"] = "AI Studio create
-- Plugin directory:
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1698127325"] = "Plugin directory:"
+-- Several of the provider logos in AI Studio use the icon paths and brand colors published by the Simple Icons project, which releases them into the public domain under CC0. The trademarks themselves are not part of that release and remain the property of their respective owners.
+UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1699089284"] = "Several of the provider logos in AI Studio use the icon paths and brand colors published by the Simple Icons project, which releases them into the public domain under CC0. The trademarks themselves are not part of that release and remain the property of their respective owners."
+
-- Consent:
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T171952677"] = "Consent:"
@@ -8386,6 +8395,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2029659664"] = "Copies the follo
-- Copies the server URL to the clipboard
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2037899437"] = "Copies the server URL to the clipboard"
+-- AI Studio shows the logo of an AI provider next to its entry, so you can see at a glance which service a provider connects to. All product names, logos, and trademarks are the property of their respective owners. Their use here identifies compatible services and implies no endorsement, sponsorship, or business relationship between MindWork AI Studio and these companies.
+UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2124655767"] = "AI Studio shows the logo of an AI provider next to its entry, so you can see at a glance which service a provider connects to. All product names, logos, and trademarks are the property of their respective owners. Their use here identifies compatible services and implies no endorsement, sponsorship, or business relationship between MindWork AI Studio and these companies."
+
-- The windows-rs project provides access to Windows APIs from Rust. We use several libraries from this project: windows-registry is used to read the desired configuration in Windows enterprise environments. The windows and windows-collections libraries are used to open the native Windows share dialog, e.g., when you share a plugin with others.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T2146481269"] = "The windows-rs project provides access to Windows APIs from Rust. We use several libraries from this project: windows-registry is used to read the desired configuration in Windows enterprise environments. The windows and windows-collections libraries are used to open the native Windows share dialog, e.g., when you share a plugin with others."
@@ -8650,6 +8662,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3764549776"] = "Username provide
-- Allowed host:
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3774270763"] = "Allowed host:"
+-- Some of these logos come from the Simple Icons project, which publishes them under CC0. The remaining ones were taken from the official brand resources of the respective provider. Every logo ships with AI Studio and is loaded from your device, so showing it never sends a request to the provider.
+UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3775183188"] = "Some of these logos come from the Simple Icons project, which publishes them under CC0. The remaining ones were taken from the official brand resources of the respective provider. Every logo ships with AI Studio and is loaded from your device, so showing it never sends a request to the provider."
+
-- Configuration source:
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T3801531724"] = "Configuration source:"
diff --git a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor
index be6a93cd..1b1c8e47 100644
--- a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor
+++ b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor
@@ -1,2 +1,13 @@
@inherits MSGComponentBase
-
\ No newline at end of file
+
+
+ @if (this.GetProvider(providerData.Value) is { } provider)
+ {
+
+ }
+ else
+ {
+ @providerData.Name
+ }
+
+
diff --git a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs
index 722ad15f..9018afcb 100644
--- a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs
+++ b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs
@@ -32,7 +32,7 @@ public partial class ConfigurationProviderSelection : MSGComponentBase
[Parameter]
public Func IsLocked { get; set; } = () => false;
-
+
private IEnumerable> FilteredData()
{
if(this.Component is not Tools.Components.NONE and not Tools.Components.APP_SETTINGS)
@@ -51,6 +51,15 @@ public partial class ConfigurationProviderSelection : MSGComponentBase
}
}
+ private AIStudio.Settings.Provider? GetProvider(string providerId)
+ {
+ if (string.IsNullOrWhiteSpace(providerId))
+ return null;
+
+ var provider = this.SettingsManager.GetProviderById(providerId);
+ return provider == AIStudio.Settings.Provider.NONE ? null : provider;
+ }
+
#region Overrides of MSGComponentBase
protected override async Task ProcessIncomingMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
diff --git a/app/MindWork AI Studio/Components/ConfigurationSelect.razor b/app/MindWork AI Studio/Components/ConfigurationSelect.razor
index c3459101..4d708899 100644
--- a/app/MindWork AI Studio/Components/ConfigurationSelect.razor
+++ b/app/MindWork AI Studio/Components/ConfigurationSelect.razor
@@ -5,7 +5,14 @@
@foreach (var data in this.Data)
{
- @data.Name
+ @if (this.ItemTemplate is null)
+ {
+ @data.Name
+ }
+ else
+ {
+ @this.ItemTemplate(data)
+ }
}
-
\ No newline at end of file
+
diff --git a/app/MindWork AI Studio/Components/ConfigurationSelect.razor.cs b/app/MindWork AI Studio/Components/ConfigurationSelect.razor.cs
index 820a4ee0..fa0a51ab 100644
--- a/app/MindWork AI Studio/Components/ConfigurationSelect.razor.cs
+++ b/app/MindWork AI Studio/Components/ConfigurationSelect.razor.cs
@@ -33,7 +33,13 @@ public partial class ConfigurationSelect : ConfigurationBaseCore
///
[Parameter]
public Func SelectionUpdateAsync { get; set; } = _ => Task.CompletedTask;
-
+
+ ///
+ /// Optional template used to render an item in the list.
+ ///
+ [Parameter]
+ public RenderFragment>? ItemTemplate { get; set; }
+
#region Overrides of ConfigurationBase
///
@@ -54,4 +60,4 @@ public partial class ConfigurationSelect : ConfigurationBaseCore
await this.SettingsManager.StoreSettings();
await this.InformAboutChange();
}
-}
\ No newline at end of file
+}
diff --git a/app/MindWork AI Studio/Components/ProviderIcon.razor b/app/MindWork AI Studio/Components/ProviderIcon.razor
new file mode 100644
index 00000000..3f91cd81
--- /dev/null
+++ b/app/MindWork AI Studio/Components/ProviderIcon.razor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/ProviderIcon.razor.cs b/app/MindWork AI Studio/Components/ProviderIcon.razor.cs
new file mode 100644
index 00000000..3931fe17
--- /dev/null
+++ b/app/MindWork AI Studio/Components/ProviderIcon.razor.cs
@@ -0,0 +1,59 @@
+using AIStudio.Provider;
+using AIStudio.Settings;
+
+using Microsoft.AspNetCore.Components;
+
+namespace AIStudio.Components;
+
+///
+/// Shows the icon of a provider.
+///
+///
+/// The icon is rendered as an image instead of inline SVG. That way the browser treats the icon as
+/// a standalone, script-less document, which matters for the custom icons a configuration plugin
+/// may supply.
+///
+public partial class ProviderIcon : ComponentBase
+{
+ ///
+ /// The configured provider whose icon should be shown. Takes precedence over ProviderType.
+ ///
+ [Parameter]
+ public AIStudio.Settings.Provider? ProviderSettings { get; set; }
+
+ ///
+ /// The LLM provider whose icon should be shown when no ProviderSettings was given.
+ ///
+ [Parameter]
+ public LLMProviders ProviderType { get; set; } = LLMProviders.NONE;
+
+ ///
+ /// The validated custom icon supplied by a configuration plugin.
+ ///
+ [Parameter]
+ public string CustomIconDataUrl { get; set; } = string.Empty;
+
+ ///
+ /// Additional CSS class for the icon.
+ ///
+ [Parameter]
+ public string Class { get; set; } = string.Empty;
+
+ ///
+ /// Additional inline style for the icon.
+ ///
+ [Parameter]
+ public string Style { get; set; } = string.Empty;
+
+ [Inject]
+ private SettingsManager SettingsManager { get; init; } = null!;
+
+ ///
+ /// The provider-icon class carries the sizing from app.css. Callers add to it instead of
+ /// replacing it, so an icon cannot lose its size by setting a class of its own.
+ ///
+ private string CssClass => $"provider-icon {this.Class}".TrimEnd();
+
+ private string IconUrl => this.ProviderSettings?.GetIconUrl(this.SettingsManager.IsDarkMode)
+ ?? this.ProviderType.GetIconUrl(this.SettingsManager.IsDarkMode, this.CustomIconDataUrl);
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/ProviderLabel.razor b/app/MindWork AI Studio/Components/ProviderLabel.razor
new file mode 100644
index 00000000..94ea0208
--- /dev/null
+++ b/app/MindWork AI Studio/Components/ProviderLabel.razor
@@ -0,0 +1,4 @@
+
+
+ @this.Text
+
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/ProviderLabel.razor.cs b/app/MindWork AI Studio/Components/ProviderLabel.razor.cs
new file mode 100644
index 00000000..f78668cb
--- /dev/null
+++ b/app/MindWork AI Studio/Components/ProviderLabel.razor.cs
@@ -0,0 +1,46 @@
+using AIStudio.Provider;
+
+using Microsoft.AspNetCore.Components;
+
+namespace AIStudio.Components;
+
+///
+/// Shows a provider icon next to its name.
+///
+///
+/// Providers appear in select items, in table cells, and in group headers. All of them need the
+/// same icon and text pairing, so this component owns that layout once instead of repeating it at
+/// every call site.
+///
+public partial class ProviderLabel : ComponentBase
+{
+ ///
+ /// The configured provider whose icon should be shown. Takes precedence over ProviderType.
+ ///
+ [Parameter]
+ public AIStudio.Settings.Provider? ProviderSettings { get; set; }
+
+ ///
+ /// The LLM provider whose icon should be shown when no ProviderSettings was given.
+ ///
+ [Parameter]
+ public LLMProviders ProviderType { get; set; } = LLMProviders.NONE;
+
+ ///
+ /// The validated custom icon supplied by a configuration plugin.
+ ///
+ [Parameter]
+ public string CustomIconDataUrl { get; set; } = string.Empty;
+
+ ///
+ /// The text shown next to the icon.
+ ///
+ [Parameter]
+ public string Text { get; set; } = string.Empty;
+
+ ///
+ /// Additional CSS class for the text.
+ ///
+ [Parameter]
+ public string TextClass { get; set; } = string.Empty;
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/ProviderSelection.razor b/app/MindWork AI Studio/Components/ProviderSelection.razor
index 4d5b0887..e4ca191a 100644
--- a/app/MindWork AI Studio/Components/ProviderSelection.razor
+++ b/app/MindWork AI Studio/Components/ProviderSelection.razor
@@ -1,11 +1,11 @@
@using AIStudio.Settings
@inherits MSGComponentBase
-
+
@foreach (var providerItem in this.GetAvailableProviderSelectionItems())
{
- @providerItem.Provider
+
@if (providerItem.CapabilityIcons.Count > 0)
{
diff --git a/app/MindWork AI Studio/Components/ProviderSelection.razor.cs b/app/MindWork AI Studio/Components/ProviderSelection.razor.cs
index 20313116..90b4f460 100644
--- a/app/MindWork AI Studio/Components/ProviderSelection.razor.cs
+++ b/app/MindWork AI Studio/Components/ProviderSelection.razor.cs
@@ -105,12 +105,24 @@ public partial class ProviderSelection : MSGComponentBase
#region Overrides of MSGComponentBase
- protected override Task ProcessIncomingMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
+ protected override async Task ProcessIncomingMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
{
if (triggeredEvent is Event.CONFIGURATION_CHANGED or Event.PLUGINS_RELOADED)
- this.StateHasChanged();
+ {
+ //
+ // We hold a copy of the provider record, which is a snapshot taken when it was selected.
+ // Once the user edits that provider, our copy is stale and would keep showing the old
+ // name and the old icon, so we resolve it again and hand the fresh one to our parent:
+ //
+ var updatedProvider = this.SettingsManager.GetProviderById(this.ProviderSettings.Id);
+ if (updatedProvider != AIStudio.Settings.Provider.NONE && updatedProvider != this.ProviderSettings)
+ {
+ this.ProviderSettings = updatedProvider;
+ await this.ProviderSettingsChanged.InvokeAsync(updatedProvider);
+ }
- return Task.CompletedTask;
+ this.StateHasChanged();
+ }
}
#endregion
@@ -118,4 +130,4 @@ public partial class ProviderSelection : MSGComponentBase
private readonly record struct CapabilityIcon(string Icon, string Tooltip);
private readonly record struct ProviderSelectionItem(AIStudio.Settings.Provider Provider, IReadOnlyList CapabilityIcons);
-}
\ No newline at end of file
+}
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor
index 3b7a4ce4..071b9cbc 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor
@@ -37,7 +37,18 @@
@if (PreviewFeatures.PRE_SPEECH_TO_TEXT_2026.IsEnabled(this.SettingsManager))
{
-
+
+
+ @if (this.GetTranscriptionProvider(providerData.Value) is { } provider)
+ {
+
+ }
+ else
+ {
+ @providerData.Name
+ }
+
+
}
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor.cs
index ac5d07a0..d0a5a368 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor.cs
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor.cs
@@ -106,6 +106,12 @@ public partial class SettingsPanelApp : SettingsPanelBase
}
}
+ private TranscriptionProvider? GetTranscriptionProvider(string providerId)
+ {
+ var provider = this.SettingsManager.GetTranscriptionProviderById(providerId);
+ return provider == TranscriptionProvider.NONE ? null : provider;
+ }
+
private void UpdatePreviewFeatures(PreviewVisibility previewVisibility)
{
this.SettingsManager.ConfigurationData.App.PreviewVisibility = previewVisibility;
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor
index a4ad15f7..1de2dd17 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor
@@ -30,11 +30,16 @@
- @context.Key
+ @if (context.Key is LLMProviders llmProvider)
+ {
+
+ }
- @context.Name
+
+
+ @this.GetEmbeddingProviderModelName(context)
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs
index dd74f949..ba0f4587 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor.cs
@@ -19,7 +19,7 @@ public partial class SettingsPanelEmbeddings : SettingsPanelProviderBase
{
Expandable = true,
IsInitiallyExpanded = false,
- Selector = provider => provider.UsedLLMProvider.ToName(),
+ Selector = provider => provider.UsedLLMProvider,
};
[Parameter]
@@ -82,6 +82,7 @@ public partial class SettingsPanelEmbeddings : SettingsPanelProviderBase
{ x => x.DataId, embeddingProvider.Id },
{ x => x.DataName, embeddingProvider.Name },
{ x => x.DataLLMProvider, embeddingProvider.UsedLLMProvider },
+ { x => x.DataCustomIconDataUrl, embeddingProvider.CustomIconDataUrl },
{ x => x.DataModel, embeddingProvider.Model },
{ x => x.DataHostname, embeddingProvider.Hostname },
{ x => x.IsSelfHosted, embeddingProvider.IsSelfHosted },
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor
index c7dea430..59504730 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor
@@ -22,11 +22,16 @@
- @context.Key
+ @if (context.Key is LLMProviders llmProvider)
+ {
+
+ }
- @context.InstanceName
+
+
+ @this.GetLLMProviderModelName(context)
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs
index eef516da..d7096a8f 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs
@@ -1,7 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using AIStudio.Dialogs;
-using AIStudio.Provider;
using AIStudio.Settings;
using Microsoft.AspNetCore.Components;
@@ -20,7 +19,7 @@ public partial class SettingsPanelProviders : SettingsPanelProviderBase
{
Expandable = true,
IsInitiallyExpanded = false,
- Selector = provider => provider.UsedLLMProvider.ToName(),
+ Selector = provider => provider.UsedLLMProvider,
};
[Parameter]
@@ -77,6 +76,7 @@ public partial class SettingsPanelProviders : SettingsPanelProviderBase
{ x => x.DataId, provider.Id },
{ x => x.DataInstanceName, provider.InstanceName },
{ x => x.DataLLMProvider, provider.UsedLLMProvider },
+ { x => x.DataCustomIconDataUrl, provider.CustomIconDataUrl },
{ x => x.DataModel, provider.Model },
{ x => x.DataHostname, provider.Hostname },
{ x => x.IsSelfHosted, provider.IsSelfHosted },
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor
index 40ec1a82..b0d51e9a 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor
@@ -26,11 +26,16 @@
- @context.Key
+ @if (context.Key is LLMProviders llmProvider)
+ {
+
+ }
- @context.Name
+
+
+ @this.GetTranscriptionProviderModelName(context)
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor.cs
index 4d8daa15..252a95a4 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor.cs
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor.cs
@@ -1,5 +1,4 @@
using AIStudio.Dialogs;
-using AIStudio.Provider;
using AIStudio.Settings;
using Microsoft.AspNetCore.Components;
@@ -18,7 +17,7 @@ public partial class SettingsPanelTranscription : SettingsPanelProviderBase
{
Expandable = true,
IsInitiallyExpanded = false,
- Selector = provider => provider.UsedLLMProvider.ToName(),
+ Selector = provider => provider.UsedLLMProvider,
};
[Parameter]
@@ -81,6 +80,7 @@ public partial class SettingsPanelTranscription : SettingsPanelProviderBase
{ x => x.DataId, transcriptionProvider.Id },
{ x => x.DataName, transcriptionProvider.Name },
{ x => x.DataLLMProvider, transcriptionProvider.UsedLLMProvider },
+ { x => x.DataCustomIconDataUrl, transcriptionProvider.CustomIconDataUrl },
{ x => x.DataModel, transcriptionProvider.Model },
{ x => x.DataHostname, transcriptionProvider.Hostname },
{ x => x.IsSelfHosted, transcriptionProvider.IsSelfHosted },
diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor
index 7cdae497..1c7c39a3 100644
--- a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor
@@ -50,7 +50,14 @@
@foreach (var embedding in this.AvailableEmbeddings)
{
- @embedding.Name
+ @if (this.GetEmbeddingProvider(embedding.Value) is { } provider)
+ {
+
+ }
+ else
+ {
+ @embedding.Name
+ }
}
@@ -109,4 +116,4 @@
}
-
\ No newline at end of file
+
diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor.cs b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor.cs
index 42463e38..d103336e 100644
--- a/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalDirectoryDialog.razor.cs
@@ -95,6 +95,12 @@ public partial class DataSourceLocalDirectoryDialog : MSGComponentBase
}
#endregion
+
+ private EmbeddingProvider? GetEmbeddingProvider(string providerId)
+ {
+ var provider = this.SettingsManager.GetEmbeddingProviderById(providerId);
+ return provider == EmbeddingProvider.NONE ? null : provider;
+ }
private bool SelectedCloudEmbedding => !(this.SettingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(x => x.Id == this.dataEmbeddingId)?.IsTrustedForDataSourceSecurityChecks(this.SettingsManager) ?? false);
@@ -124,4 +130,4 @@ public partial class DataSourceLocalDirectoryDialog : MSGComponentBase
}
private void Cancel() => this.MudDialog.Cancel();
-}
\ No newline at end of file
+}
diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor
index d360b0de..b9cba6b5 100644
--- a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor
@@ -50,7 +50,14 @@
@foreach (var embedding in this.AvailableEmbeddings)
{
- @embedding.Name
+ @if (this.GetEmbeddingProvider(embedding.Value) is { } provider)
+ {
+
+ }
+ else
+ {
+ @embedding.Name
+ }
}
@@ -109,4 +116,4 @@
}
-
\ No newline at end of file
+
diff --git a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor.cs b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor.cs
index 13b8df1e..df794cca 100644
--- a/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/DataSourceLocalFileDialog.razor.cs
@@ -95,6 +95,12 @@ public partial class DataSourceLocalFileDialog : MSGComponentBase
}
#endregion
+
+ private EmbeddingProvider? GetEmbeddingProvider(string providerId)
+ {
+ var provider = this.SettingsManager.GetEmbeddingProviderById(providerId);
+ return provider == EmbeddingProvider.NONE ? null : provider;
+ }
private bool SelectedCloudEmbedding => !(this.SettingsManager.ConfigurationData.EmbeddingProviders.FirstOrDefault(x => x.Id == this.dataEmbeddingId)?.IsTrustedForDataSourceSecurityChecks(this.SettingsManager) ?? false);
@@ -124,4 +130,4 @@ public partial class DataSourceLocalFileDialog : MSGComponentBase
}
private void Cancel() => this.MudDialog.Cancel();
-}
\ No newline at end of file
+}
diff --git a/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor b/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor
index 1abb680e..5bcead75 100644
--- a/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor
@@ -13,13 +13,13 @@
@* ReSharper disable once CSharpWarnings::CS8974 *@
-
+
@foreach (LLMProviders provider in Enum.GetValues(typeof(LLMProviders)))
{
if (provider.ProvideEmbeddingAPI() || provider is LLMProviders.NONE)
{
- @provider.ToName()
+
}
}
@@ -152,4 +152,4 @@
}
-
\ No newline at end of file
+
diff --git a/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor.cs b/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor.cs
index f2fb87f6..4bb3c189 100644
--- a/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/EmbeddingProviderDialog.razor.cs
@@ -56,6 +56,12 @@ public partial class EmbeddingProviderDialog : MSGComponentBase, ISecretId
///
[Parameter]
public LLMProviders DataLLMProvider { get; set; } = LLMProviders.NONE;
+
+ ///
+ /// The validated custom icon supplied by a configuration plugin.
+ ///
+ [Parameter]
+ public string DataCustomIconDataUrl { get; set; } = string.Empty;
///
/// The embedding model to use.
@@ -144,6 +150,7 @@ public partial class EmbeddingProviderDialog : MSGComponentBase, ISecretId
Host = this.DataHost,
IsEnterpriseConfiguration = this.IsEnterpriseConfiguration,
EnterpriseConfigurationPluginId = Guid.Empty,
+ CustomIconDataUrl = this.DataCustomIconDataUrl,
};
}
@@ -343,4 +350,4 @@ public partial class EmbeddingProviderDialog : MSGComponentBase, ISecretId
};
private bool IsNoneProvider => this.DataLLMProvider is LLMProviders.NONE;
-}
\ No newline at end of file
+}
diff --git a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor
index b896837e..eb97b251 100644
--- a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor
@@ -18,15 +18,12 @@
ValueChanged="@this.OnProviderChanged"
Label="@T("Provider")"
Class="mb-3"
- OpenIcon="@Icons.Material.Filled.AccountBalance"
- AdornmentColor="Color.Info"
- Adornment="Adornment.Start"
Disabled="@this.IsEnterpriseConfiguration"
Validation="@this.providerValidation.ValidatingProvider">
@foreach (LLMProviders provider in Enum.GetValues(typeof(LLMProviders)))
{
- @provider.ToName()
+
}
diff --git a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs
index ef14b7bb..ae8362c3 100644
--- a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs
@@ -78,6 +78,12 @@ public partial class ProviderDialog : MSGComponentBase, ISecretId
///
[Parameter]
public LLMProviders DataLLMProvider { get; set; } = LLMProviders.NONE;
+
+ ///
+ /// The validated custom icon supplied by a configuration plugin.
+ ///
+ [Parameter]
+ public string DataCustomIconDataUrl { get; set; } = string.Empty;
///
/// The LLM model to use, e.g., GPT-4o.
@@ -184,6 +190,7 @@ public partial class ProviderDialog : MSGComponentBase, ISecretId
HFInferenceProvider = this.HFInferenceProviderId,
AdditionalJsonApiParameters = this.AdditionalJsonApiParameters,
CapabilityOverrides = this.capabilityOverrides.HasOverrides ? this.capabilityOverrides : null,
+ CustomIconDataUrl = this.DataCustomIconDataUrl,
};
}
diff --git a/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor b/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor
index dd7fb33a..e92889a4 100644
--- a/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor
+++ b/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor
@@ -13,13 +13,13 @@
@* ReSharper disable once CSharpWarnings::CS8974 *@
-
+
@foreach (LLMProviders provider in Enum.GetValues(typeof(LLMProviders)))
{
if (provider.ProvideTranscriptionAPI() || provider is LLMProviders.NONE)
{
- @provider.ToName()
+
}
}
@@ -163,4 +163,4 @@
}
-
\ No newline at end of file
+
diff --git a/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor.cs b/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor.cs
index 9132c9e6..1e1081f3 100644
--- a/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/TranscriptionProviderDialog.razor.cs
@@ -56,6 +56,12 @@ public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId
///
[Parameter]
public LLMProviders DataLLMProvider { get; set; } = LLMProviders.NONE;
+
+ ///
+ /// The validated custom icon supplied by a configuration plugin.
+ ///
+ [Parameter]
+ public string DataCustomIconDataUrl { get; set; } = string.Empty;
///
/// The transcription model to use.
@@ -159,6 +165,7 @@ public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId
Host = this.DataHost,
IsEnterpriseConfiguration = this.IsEnterpriseConfiguration,
EnterpriseConfigurationPluginId = Guid.Empty,
+ CustomIconDataUrl = this.DataCustomIconDataUrl,
};
}
@@ -358,4 +365,4 @@ public partial class TranscriptionProviderDialog : MSGComponentBase, ISecretId
};
private bool IsNoneProvider => this.DataLLMProvider is LLMProviders.NONE;
-}
\ No newline at end of file
+}
diff --git a/app/MindWork AI Studio/Pages/Information.razor b/app/MindWork AI Studio/Pages/Information.razor
index 272265c8..34714d92 100644
--- a/app/MindWork AI Studio/Pages/Information.razor
+++ b/app/MindWork AI Studio/Pages/Information.razor
@@ -393,8 +393,20 @@
+
+
+
+ @T("AI Studio shows the logo of an AI provider next to its entry, so you can see at a glance which service a provider connects to. All product names, logos, and trademarks are the property of their respective owners. Their use here identifies compatible services and implies no endorsement, sponsorship, or business relationship between MindWork AI Studio and these companies.")
+
+
+ @T("Some of these logos come from the Simple Icons project, which publishes them under CC0. The remaining ones were taken from the official brand resources of the respective provider. Every logo ships with AI Studio and is loaded from your device, so showing it never sends a request to the provider.")
+
+
+ @T("Organizations can replace these logos with their own icons through a configuration plugin. When your organization does so, it is responsible for holding the rights to the icons it provides.")
+
+
diff --git a/app/MindWork AI Studio/Pages/Plugins.razor b/app/MindWork AI Studio/Pages/Plugins.razor
index 4ceaa044..e99f7c4e 100644
--- a/app/MindWork AI Studio/Pages/Plugins.razor
+++ b/app/MindWork AI Studio/Pages/Plugins.razor
@@ -63,7 +63,10 @@