mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-04 15:52:30 +00:00
Added provider icons (#934)
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
1 parent
afdcc0455d
commit
e78a0e61b9
74 files changed
+1018
-74
No files matched your search
@@ -3,9 +3,14 @@ namespace AIStudio.Tools.PluginSystem;
|
||||
public interface IPluginMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// The icon of this plugin.
|
||||
/// The icon of this plugin, as a data URL ready for the src attribute of an image element.
|
||||
/// </summary>
|
||||
public string IconSVG { get; }
|
||||
/// <remarks>
|
||||
/// Deliberately a data URL and not the raw markup: the icon comes from the plugin, so it must
|
||||
/// never be rendered inline into the DOM. Inside an image element the browser treats it as a
|
||||
/// standalone document which runs no script and loads nothing from the network.
|
||||
/// </remarks>
|
||||
public string IconDataUrl { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of this plugin.
|
||||
|
||||
@@ -7,39 +7,62 @@ public abstract partial class PluginBase
|
||||
<svg height="1.5em" width="1.5em" viewBox="0 0 24 24" fill="#1f1f1f"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 13h-2V7h-6V5c0-.28-.22-.5-.5-.5s-.5.22-.5.5v2H4l.01 2.12C5.76 9.8 7 11.51 7 13.5c0 1.99-1.25 3.7-3 4.38V20h2.12c.68-1.75 2.39-3 4.38-3 1.99 0 3.7 1.25 4.38 3H17v-6h2c.28 0 .5-.22.5-.5s-.22-.5-.5-.5z" opacity=".3"/><path d="M19 11V7c0-1.1-.9-2-2-2h-4c0-1.38-1.12-2.5-2.5-2.5S8 3.62 8 5H4c-1.1 0-1.99.9-1.99 2v3.8h.29c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-.3c0-1.49 1.21-2.7 2.7-2.7s2.7 1.21 2.7 2.7v.3H17c1.1 0 2-.9 2-2v-4c1.38 0 2.5-1.12 2.5-2.5S20.38 11 19 11zm0 3h-2v6h-2.12c-.68-1.75-2.39-3-4.38-3-1.99 0-3.7 1.25-4.38 3H4v-2.12c1.75-.68 3-2.39 3-4.38 0-1.99-1.24-3.7-2.99-4.38L4 7h6V5c0-.28.22-.5.5-.5s.5.22.5.5v2h6v6h2c.28 0 .5.22.5.5s-.22.5-.5.5z"/></svg>
|
||||
""";
|
||||
|
||||
private static readonly string DEFAULT_ICON_DATA_URL = CreateDefaultIconDataUrl();
|
||||
|
||||
#region Initialization-related methods
|
||||
|
||||
/// <summary>
|
||||
/// Tries to initialize the icon of the plugin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When no icon is specified, the default icon will be used.
|
||||
/// <para>
|
||||
/// When no icon is specified, or when the specified icon is unusable, the default icon will be
|
||||
/// used. A plugin never fails to load over its icon.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The icon is handed out as a data URL, not as markup: plugins are shown through an image
|
||||
/// element so the browser treats their icon as a standalone, script-less document. Rendering
|
||||
/// plugin-supplied markup inline would hand every plugin author a way to run code in the app.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="message">The error message, when the icon could not be read.</param>
|
||||
/// <param name="iconSVG">The read icon as SVG.</param>
|
||||
/// <param name="iconDataUrl">The read icon as a data URL.</param>
|
||||
/// <returns>True, when the icon could be read successfully.</returns>
|
||||
|
||||
// ReSharper disable once OutParameterValueIsAlwaysDiscarded.Local
|
||||
// ReSharper disable once UnusedMethodReturnValue.Local
|
||||
private bool TryInitIconSVG(out string message, out string iconSVG)
|
||||
private bool TryInitIconDataUrl(out string message, out string iconDataUrl)
|
||||
{
|
||||
if (!this.State.Environment["ICON_SVG"].TryRead(out iconSVG))
|
||||
if (!this.State.Environment["ICON_SVG"].TryRead<string>(out var iconSVG))
|
||||
{
|
||||
iconSVG = DEFAULT_ICON_SVG;
|
||||
iconDataUrl = DEFAULT_ICON_DATA_URL;
|
||||
message = "The field ICON_SVG does not exist or is not a valid string.";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(iconSVG))
|
||||
{
|
||||
iconSVG = DEFAULT_ICON_SVG;
|
||||
iconDataUrl = DEFAULT_ICON_DATA_URL;
|
||||
message = "The field ICON_SVG is empty. The icon must be a non-empty string.";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!SvgIcon.TryCreateDataUrl(iconSVG, out iconDataUrl, out var issue))
|
||||
{
|
||||
iconDataUrl = DEFAULT_ICON_DATA_URL;
|
||||
message = $"The field ICON_SVG is not a usable icon: {issue}";
|
||||
return true;
|
||||
}
|
||||
|
||||
message = string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string CreateDefaultIconDataUrl()
|
||||
{
|
||||
SvgIcon.TryCreateDataUrl(DEFAULT_ICON_SVG, out var dataUrl, out _);
|
||||
return dataUrl;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -16,8 +16,8 @@ public abstract partial class PluginBase : IPluginMetadata, IDisposable
|
||||
protected readonly List<string> PluginIssues = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public string IconSVG { get; }
|
||||
|
||||
public string IconDataUrl { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public PluginType Type { get; }
|
||||
|
||||
@@ -88,14 +88,14 @@ public abstract partial class PluginBase : IPluginMetadata, IDisposable
|
||||
if (this is NoPlugin or NoPluginLanguage)
|
||||
{
|
||||
this.IsInternal = isInternal;
|
||||
this.IconSVG = string.Empty;
|
||||
this.IconDataUrl = string.Empty;
|
||||
this.baseIssues = issues;
|
||||
return;
|
||||
}
|
||||
|
||||
// Notice: when no icon is specified, the default icon will be used.
|
||||
this.TryInitIconSVG(out _, out var iconSVG);
|
||||
this.IconSVG = iconSVG;
|
||||
this.TryInitIconDataUrl(out _, out var iconDataUrl);
|
||||
this.IconDataUrl = iconDataUrl;
|
||||
|
||||
if(this.TryInitId(out var issue, out var id))
|
||||
{
|
||||
|
||||
@@ -297,13 +297,13 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
this.TryProcessEnterpriseApprovedAssistantPlugins(settingsTable, dryRun);
|
||||
|
||||
// Handle configured LLM providers:
|
||||
PluginConfigurationObject.TryParse(PluginConfigurationObjectType.LLM_PROVIDER, x => x.Providers, x => x.NextProviderNum, mainTable, this.Id, ref this.configObjects, dryRun);
|
||||
PluginConfigurationObject.TryParse(PluginConfigurationObjectType.LLM_PROVIDER, x => x.Providers, x => x.NextProviderNum, mainTable, this.Id, ref this.configObjects, dryRun, this.PluginPath);
|
||||
|
||||
// Handle configured transcription providers:
|
||||
PluginConfigurationObject.TryParse(PluginConfigurationObjectType.TRANSCRIPTION_PROVIDER, x => x.TranscriptionProviders, x => x.NextTranscriptionNum, mainTable, this.Id, ref this.configObjects, dryRun);
|
||||
PluginConfigurationObject.TryParse(PluginConfigurationObjectType.TRANSCRIPTION_PROVIDER, x => x.TranscriptionProviders, x => x.NextTranscriptionNum, mainTable, this.Id, ref this.configObjects, dryRun, this.PluginPath);
|
||||
|
||||
// Handle configured embedding providers:
|
||||
PluginConfigurationObject.TryParse(PluginConfigurationObjectType.EMBEDDING_PROVIDER, x => x.EmbeddingProviders, x => x.NextEmbeddingNum, mainTable, this.Id, ref this.configObjects, dryRun);
|
||||
PluginConfigurationObject.TryParse(PluginConfigurationObjectType.EMBEDDING_PROVIDER, x => x.EmbeddingProviders, x => x.NextEmbeddingNum, mainTable, this.Id, ref this.configObjects, dryRun, this.PluginPath);
|
||||
|
||||
// Handle configured chat templates:
|
||||
PluginConfigurationObject.TryParse(PluginConfigurationObjectType.CHAT_TEMPLATE, x => x.ChatTemplates, x => x.NextChatTemplateNum, mainTable, this.Id, ref this.configObjects, dryRun, this.PluginPath);
|
||||
@@ -598,4 +598,4 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
LOG.LogWarning("The table 'INTRODUCTIONS' entry at index {Index} does not contain a valid introduction (config plugin id: {ConfigPluginId}).", i, this.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,11 +142,11 @@ public sealed record PluginConfigurationObject
|
||||
|
||||
var (wasParsingSuccessful, configObject) = configObjectType switch
|
||||
{
|
||||
PluginConfigurationObjectType.LLM_PROVIDER => (Settings.Provider.TryParseProviderTable(i, luaObjectTable, configPluginId, out var configurationObject) && configurationObject != Settings.Provider.NONE, configurationObject),
|
||||
PluginConfigurationObjectType.LLM_PROVIDER => (Settings.Provider.TryParseProviderTable(i, luaObjectTable, configPluginId, pluginPath, out var configurationObject) && configurationObject != Settings.Provider.NONE, configurationObject),
|
||||
PluginConfigurationObjectType.CHAT_TEMPLATE => (ChatTemplate.TryParseChatTemplateTable(i, luaObjectTable, configPluginId, pluginPath, out var configurationObject) && configurationObject != ChatTemplate.NO_CHAT_TEMPLATE, configurationObject),
|
||||
PluginConfigurationObjectType.PROFILE => (Profile.TryParseProfileTable(i, luaObjectTable, configPluginId, out var configurationObject) && configurationObject != Profile.NO_PROFILE, configurationObject),
|
||||
PluginConfigurationObjectType.TRANSCRIPTION_PROVIDER => (TranscriptionProvider.TryParseTranscriptionProviderTable(i, luaObjectTable, configPluginId, out var configurationObject) && configurationObject != TranscriptionProvider.NONE, configurationObject),
|
||||
PluginConfigurationObjectType.EMBEDDING_PROVIDER => (EmbeddingProvider.TryParseEmbeddingProviderTable(i, luaObjectTable, configPluginId, out var configurationObject) && configurationObject != EmbeddingProvider.NONE, configurationObject),
|
||||
PluginConfigurationObjectType.TRANSCRIPTION_PROVIDER => (TranscriptionProvider.TryParseTranscriptionProviderTable(i, luaObjectTable, configPluginId, pluginPath, out var configurationObject) && configurationObject != TranscriptionProvider.NONE, configurationObject),
|
||||
PluginConfigurationObjectType.EMBEDDING_PROVIDER => (EmbeddingProvider.TryParseEmbeddingProviderTable(i, luaObjectTable, configPluginId, pluginPath, out var configurationObject) && configurationObject != EmbeddingProvider.NONE, configurationObject),
|
||||
PluginConfigurationObjectType.DOCUMENT_ANALYSIS_POLICY => (DataDocumentAnalysisPolicy.TryProcessConfiguration(i, luaObjectTable, configPluginId, out var configurationObject) && configurationObject is DataDocumentAnalysisPolicy, configurationObject),
|
||||
|
||||
_ => (false, NoConfigurationObject.INSTANCE)
|
||||
@@ -426,4 +426,4 @@ public sealed record PluginConfigurationObject
|
||||
|
||||
return wasConfigurationChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ public sealed class PluginMetadata(PluginBase plugin, string localPath, bool isM
|
||||
#region Implementation of IPluginMetadata
|
||||
|
||||
/// <inheritdoc />
|
||||
public string IconSVG { get; } = plugin.IconSVG;
|
||||
public string IconDataUrl { get; } = plugin.IconDataUrl;
|
||||
|
||||
/// <inheritdoc />
|
||||
public PluginType Type { get; } = plugin.Type;
|
||||
|
||||
Reference in new issue
Block a user