Added support for organization-approved assistant plugins (#821)
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions

This commit is contained in:
Peer Hogeterp authored and GitHub committed 2026-07-05 15:20:29 +02:00
1 parent 972ed73fe8
commit 13cc2f837a
35 files changed
+954 -62

No files matched your search

@@ -1,3 +1,4 @@
using System.Globalization;
using AIStudio.Settings;
using AIStudio.Settings.DataModel;
using AIStudio.Tools.Services;
@@ -221,6 +222,9 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
ManagedConfiguration.TryProcessConfiguration(x => x.AssistantPluginAudit, x => x.MinimumLevel, this.Id, settingsTable, dryRun);
ManagedConfiguration.TryProcessConfiguration(x => x.AssistantPluginAudit, x => x.BlockActivationBelowMinimum, this.Id, settingsTable, dryRun);
ManagedConfiguration.TryProcessConfiguration(x => x.AssistantPluginAudit, x => x.AutomaticallyAuditAssistants, this.Id, settingsTable, dryRun);
// Config: enterprise-managed approvals for assistant plugins
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);
@@ -273,6 +277,120 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
return true;
}
private void TryProcessEnterpriseApprovedAssistantPlugins(LuaTable settingsTable, bool dryRun)
{
if (!ManagedConfiguration.TryGet(x => x.AssistantPluginAudit, x => x.EnterpriseApprovedPlugins, out ConfigMeta<DataAssistantPluginAudit, IList<DataAssistantPluginEnterpriseApproval>> configMeta))
return;
var settingName = SettingsManager.ToSettingName<DataAssistantPluginAudit, IList<DataAssistantPluginEnterpriseApproval>>(x => x.EnterpriseApprovedPlugins);
var successful = false;
IList<DataAssistantPluginEnterpriseApproval> configuredApprovals = [];
if (settingsTable.TryGetValue(settingName, out var configuredLuaValue)
&& configuredLuaValue.Type is LuaValueType.Table
&& configuredLuaValue.TryRead<LuaTable>(out var approvalsTable))
{
var approvals = new List<DataAssistantPluginEnterpriseApproval>(approvalsTable.ArrayLength);
for (var index = 1; index <= approvalsTable.ArrayLength; index++)
{
var entryValue = approvalsTable[index];
if (entryValue.TryRead<string>(out var hashText))
{
var normalizedHash = NormalizeApprovalHash(hashText);
if (!string.IsNullOrWhiteSpace(normalizedHash))
approvals.Add(new() { PluginHash = normalizedHash });
else
LOG.LogWarning("The enterprise assistant approval entry at index {Index} contains an empty hash (config plugin id: {ConfigPluginId}).", index, this.Id);
continue;
}
if (!entryValue.TryRead<LuaTable>(out var entryTable))
{
LOG.LogWarning("The enterprise assistant approval entry at index {Index} is neither a string nor a table (config plugin id: {ConfigPluginId}).", index, this.Id);
continue;
}
if (!TryParseEnterpriseApprovedAssistantPlugin(index, entryTable, this.Id, out var approval))
continue;
approvals.Add(approval);
}
configuredApprovals = approvals;
successful = true;
}
if (dryRun)
return;
switch (successful)
{
case true:
configMeta.SetValue(configuredApprovals);
configMeta.LockConfiguration(this.Id);
break;
case false when configMeta.IsLocked && configMeta.LockedByConfigPluginId == this.Id:
configMeta.ResetLockedConfiguration();
break;
}
}
private static bool TryParseEnterpriseApprovedAssistantPlugin(int index, LuaTable table, Guid configPluginId, out DataAssistantPluginEnterpriseApproval approval)
{
approval = new();
if (!table.TryGetValue("PluginHash", out var pluginHashValue) || !pluginHashValue.TryRead<string>(out var pluginHash))
{
LOG.LogWarning("The enterprise assistant approval entry at index {Index} is missing a valid PluginHash (config plugin id: {ConfigPluginId}).", index, configPluginId);
return false;
}
var normalizedHash = NormalizeApprovalHash(pluginHash);
if (string.IsNullOrWhiteSpace(normalizedHash))
{
LOG.LogWarning("The enterprise assistant approval entry at index {Index} contains an empty PluginHash (config plugin id: {ConfigPluginId}).", index, configPluginId);
return false;
}
var displayName = TryReadOptionalString(table, "DisplayName");
var comment = TryReadOptionalString(table, "Comment");
var approvedBy = TryReadOptionalString(table, "ApprovedBy");
var approvedAtUtc = TryReadOptionalDateTimeOffset(table, "ApprovedAtUtc", index, configPluginId);
approval = new()
{
PluginHash = normalizedHash,
DisplayName = displayName,
Comment = comment,
ApprovedBy = approvedBy,
ApprovedAtUtc = approvedAtUtc,
};
return true;
}
private static string TryReadOptionalString(LuaTable table, string key)
{
return table.TryGetValue(key, out var value) && value.TryRead<string>(out var text)
? text
: string.Empty;
}
private static DateTimeOffset? TryReadOptionalDateTimeOffset(LuaTable table, string key, int index, Guid configPluginId)
{
if (!table.TryGetValue(key, out var value))
return null;
if (value.TryRead<string>(out var text) && DateTimeOffset.TryParse(text, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var parsed))
return parsed.ToUniversalTime();
LOG.LogWarning("The enterprise assistant approval entry at index {Index} contains an invalid {Key} value (config plugin id: {ConfigPluginId}).", index, key, configPluginId);
return null;
}
private static string NormalizeApprovalHash(string hash) => string.IsNullOrWhiteSpace(hash) ? string.Empty : hash.Trim().ToUpperInvariant();
private void TryReadMandatoryInfos(LuaTable mainTable)
{
if (!mainTable.TryGetValue("MANDATORY_INFOS", out var mandatoryInfosValue) || !mandatoryInfosValue.TryRead<LuaTable>(out var mandatoryInfosTable))