mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-05-14 10:14:08 +00:00
small ui fixes
This commit is contained in:
parent
3f2d76337a
commit
92267b129f
@ -9,11 +9,11 @@ public static class AssistantAuditLevelExtensions
|
||||
public static string GetName(this AssistantAuditLevel level) => level switch
|
||||
{
|
||||
AssistantAuditLevel.DANGEROUS => TB("Dangerous"),
|
||||
AssistantAuditLevel.CAUTION => TB("Needs Review"),
|
||||
AssistantAuditLevel.CAUTION => TB("Concerning"),
|
||||
AssistantAuditLevel.SAFE => TB("Safe"),
|
||||
_ => TB("Unknown"),
|
||||
};
|
||||
|
||||
|
||||
public static Severity GetSeverity(this AssistantAuditLevel level) => level switch
|
||||
{
|
||||
AssistantAuditLevel.DANGEROUS => Severity.Error,
|
||||
@ -22,5 +22,26 @@ public static class AssistantAuditLevelExtensions
|
||||
_ => Severity.Info,
|
||||
};
|
||||
|
||||
public static Color GetColor(this AssistantAuditLevel level) => level switch
|
||||
{
|
||||
AssistantAuditLevel.DANGEROUS => Color.Error,
|
||||
AssistantAuditLevel.CAUTION => Color.Warning,
|
||||
AssistantAuditLevel.SAFE => Color.Success,
|
||||
_ => Color.Default,
|
||||
};
|
||||
|
||||
public static string GetIcon(this AssistantAuditLevel level) => level switch
|
||||
{
|
||||
AssistantAuditLevel.DANGEROUS => Icons.Material.Filled.Dangerous,
|
||||
AssistantAuditLevel.CAUTION => Icons.Material.Filled.Warning,
|
||||
AssistantAuditLevel.SAFE => Icons.Material.Filled.Verified,
|
||||
_ => Icons.Material.Filled.HelpOutline,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Parses an audit level string and falls back to <see cref="AssistantAuditLevel.UNKNOWN"/> when parsing fails.
|
||||
/// </summary>
|
||||
/// <param name="value">The audit level text to parse.</param>
|
||||
/// <returns>The parsed audit level, or <see cref="AssistantAuditLevel.UNKNOWN"/> for null, empty, or invalid values.</returns>
|
||||
public static AssistantAuditLevel Parse(string? value) => Enum.TryParse<AssistantAuditLevel>(value, true, out var level) ? level : AssistantAuditLevel.UNKNOWN;
|
||||
}
|
||||
|
||||
@ -5,7 +5,21 @@
|
||||
@using AIStudio.Tools.PluginSystem.Assistants.DataModel.Layout
|
||||
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogDynamic>
|
||||
|
||||
@if (this.RootComponent is null)
|
||||
@if (!string.IsNullOrWhiteSpace(this.securityMessage))
|
||||
{
|
||||
<MudPaper Class="pa-4 ma-4" Elevation="0">
|
||||
<MudAlert Severity="Severity.Error" Variant="Variant.Filled" Square="false" Elevation="6" Class="pa-4">
|
||||
@this.securityMessage
|
||||
</MudAlert>
|
||||
@if (this.assistantPlugin is not null)
|
||||
{
|
||||
<div class="mt-4">
|
||||
<AssistantPluginSecurityCard Plugin="@this.assistantPlugin"/>
|
||||
</div>
|
||||
}
|
||||
</MudPaper>
|
||||
}
|
||||
else if (this.RootComponent is null)
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning">
|
||||
@this.T("No assistant plugin are currently installed.")
|
||||
|
||||
@ -22,6 +22,7 @@ public partial class AssistantDynamic : AssistantBaseCore<SettingsDialogDynamic>
|
||||
protected override bool ShowProfileSelection => this.showFooterProfileSelection;
|
||||
protected override string SubmitText => this.submitText;
|
||||
protected override Func<Task> SubmitAction => this.Submit;
|
||||
protected override bool SubmitDisabled => this.isSecurityBlocked;
|
||||
// Dynamic assistants do not have dedicated settings yet.
|
||||
// Reuse chat-level provider filtering/preselection instead of NONE.
|
||||
protected override Tools.Components Component => Tools.Components.CHAT;
|
||||
@ -40,6 +41,8 @@ public partial class AssistantDynamic : AssistantBaseCore<SettingsDialogDynamic>
|
||||
private readonly HashSet<string> executingSwitchActions = [];
|
||||
private string pluginPath = string.Empty;
|
||||
private PluginAssistantAudit? audit;
|
||||
private string securityMessage = string.Empty;
|
||||
private bool isSecurityBlocked;
|
||||
private const string ASSISTANT_QUERY_KEY = "assistantId";
|
||||
|
||||
#region Implementation of AssistantBase
|
||||
@ -66,6 +69,16 @@ public partial class AssistantDynamic : AssistantBaseCore<SettingsDialogDynamic>
|
||||
var pluginHash = pluginAssistant.ComputeAuditHash();
|
||||
this.audit = this.SettingsManager.ConfigurationData.AssistantPluginAudits.FirstOrDefault(x => x.PluginId == pluginAssistant.Id && x.PluginHash == pluginHash);
|
||||
|
||||
var securityState = PluginAssistantSecurityResolver.Resolve(this.SettingsManager, pluginAssistant);
|
||||
if (!securityState.CanStartAssistant)
|
||||
{
|
||||
this.assistantPlugin = pluginAssistant;
|
||||
this.securityMessage = securityState.Description;
|
||||
this.isSecurityBlocked = true;
|
||||
base.OnInitialized();
|
||||
return;
|
||||
}
|
||||
|
||||
var rootComponent = this.RootComponent;
|
||||
if (rootComponent is not null)
|
||||
{
|
||||
@ -387,6 +400,13 @@ public partial class AssistantDynamic : AssistantBaseCore<SettingsDialogDynamic>
|
||||
|
||||
private async Task Submit()
|
||||
{
|
||||
if (this.assistantPlugin is not null)
|
||||
{
|
||||
var securityState = PluginAssistantSecurityResolver.Resolve(this.SettingsManager, this.assistantPlugin);
|
||||
if (!securityState.CanStartAssistant)
|
||||
return;
|
||||
}
|
||||
|
||||
this.CreateChatThread();
|
||||
var time = this.AddUserRequest(await this.CollectUserPromptAsync());
|
||||
await this.AddAIResponseAsync(time);
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
@using AIStudio.Agents.AssistantAudit
|
||||
@using AIStudio.Components
|
||||
@inherits MSGComponentBase
|
||||
|
||||
<MudDialog DefaultFocus="DefaultFocus.FirstChild">
|
||||
@ -299,7 +298,7 @@
|
||||
<MudButton OnClick="@this.CloseWithoutActivation" Variant="Variant.Filled">
|
||||
@(this.audit is null ? T("Cancel") : T("Close"))
|
||||
</MudButton>
|
||||
<MudButton OnClick="@this.RunAudit" Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!this.CanRunAudit)">
|
||||
<MudButton OnClick="@this.RunAudit" Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!this.CanRunAudit || this.justAudited)">
|
||||
@T("Start Security Check")
|
||||
</MudButton>
|
||||
@if (this.CanEnablePlugin)
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using AIStudio.Agents.AssistantAudit;
|
||||
using AIStudio.Components;
|
||||
using AIStudio.Provider;
|
||||
@ -6,17 +10,12 @@ using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.PluginSystem.Assistants;
|
||||
using AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections;
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace AIStudio.Dialogs;
|
||||
|
||||
public partial class AssistantPluginAuditDialog : MSGComponentBase
|
||||
{
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(AssistantPluginAuditDialog).Namespace,
|
||||
nameof(AssistantPluginAuditDialog));
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(AssistantPluginAuditDialog).Namespace, nameof(AssistantPluginAuditDialog));
|
||||
|
||||
[CascadingParameter]
|
||||
private IMudDialogInstance MudDialog { get; set; } = null!;
|
||||
@ -37,7 +36,7 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
|
||||
private ImmutableDictionary<string, string> luaFiles = ImmutableDictionary.Create<string, string>();
|
||||
private IReadOnlyCollection<TreeItemData<ITreeItem>> componentTreeItems = [];
|
||||
private IReadOnlyCollection<TreeItemData<ITreeItem>> fileSystemTreeItems = [];
|
||||
private CultureInfo fileInfoCulture = CultureInfo.InvariantCulture;
|
||||
private CultureInfo currentCultureInfo = CultureInfo.InvariantCulture;
|
||||
private bool isAuditing;
|
||||
|
||||
private AIStudio.Settings.Provider CurrentProvider => this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_ASSISTANT_PLUGIN_AUDIT, null, true);
|
||||
@ -63,13 +62,14 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
|
||||
private bool CanEnablePlugin => this.audit is not null && !this.isAuditing && !this.IsActivationBlockedBySettings;
|
||||
|
||||
private Color EnableButtonColor => this.RequiresActivationConfirmation ? Color.Warning : Color.Success;
|
||||
private bool justAudited;
|
||||
|
||||
private const ushort BYTES_PER_KILOBYTE = 1024;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var activeLanguagePlugin = await this.SettingsManager.GetActiveLanguagePlugin();
|
||||
this.fileInfoCulture = this.CreateFileInfoCulture(activeLanguagePlugin.IETFTag);
|
||||
this.currentCultureInfo = CommonTools.DeriveActiveCultureOrInvariant(activeLanguagePlugin.IETFTag);
|
||||
|
||||
this.plugin = PluginFactory.RunningPlugins.OfType<PluginAssistants>()
|
||||
.FirstOrDefault(x => x.Id == this.PluginId);
|
||||
@ -116,6 +116,7 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
|
||||
finally
|
||||
{
|
||||
this.isAuditing = false;
|
||||
this.justAudited = true;
|
||||
await this.InvokeAsync(this.StateHasChanged);
|
||||
}
|
||||
}
|
||||
@ -453,7 +454,7 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
|
||||
string stringValue when string.IsNullOrWhiteSpace(stringValue) => TB("empty"),
|
||||
string stringValue => stringValue,
|
||||
bool boolValue => boolValue ? "true" : "false",
|
||||
_ => Convert.ToString(value, System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty,
|
||||
_ => Convert.ToString(value, CultureInfo.InvariantCulture) ?? string.Empty,
|
||||
};
|
||||
|
||||
private string GetStructuredValueCaption(object? value) => value switch
|
||||
@ -477,37 +478,23 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
|
||||
_ => Icons.Material.Filled.DataArray,
|
||||
};
|
||||
|
||||
private string FormatFileTimestamp(DateTime timestamp) => timestamp.ToString("g", this.fileInfoCulture);
|
||||
private string FormatFileTimestamp(DateTime timestamp) => CommonTools.FormatTimestampToGeneral(timestamp, this.currentCultureInfo);
|
||||
|
||||
private string FormatFileSize(long bytes)
|
||||
{
|
||||
if (bytes < BYTES_PER_KILOBYTE)
|
||||
return string.Format(this.fileInfoCulture, TB("{0} B"), bytes);
|
||||
return string.Format(this.currentCultureInfo, TB("{0} B"), bytes);
|
||||
|
||||
var kilobyte = bytes / (double)BYTES_PER_KILOBYTE;
|
||||
if (kilobyte < BYTES_PER_KILOBYTE)
|
||||
return string.Format(this.fileInfoCulture, TB("{0:0.##} KB"), kilobyte);
|
||||
return string.Format(this.currentCultureInfo, TB("{0:0.##} KB"), kilobyte);
|
||||
|
||||
var megabyte = kilobyte / BYTES_PER_KILOBYTE;
|
||||
if (megabyte < BYTES_PER_KILOBYTE)
|
||||
return string.Format(this.fileInfoCulture, TB("{0:0.##} MB"), megabyte);
|
||||
return string.Format(this.currentCultureInfo, TB("{0:0.##} MB"), megabyte);
|
||||
|
||||
var gigabyte = megabyte / BYTES_PER_KILOBYTE;
|
||||
return string.Format(this.fileInfoCulture, TB("{0:0.##} GB"), gigabyte);
|
||||
return string.Format(this.currentCultureInfo, TB("{0:0.##} GB"), gigabyte);
|
||||
}
|
||||
|
||||
private CultureInfo CreateFileInfoCulture(string ietfTag)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ietfTag))
|
||||
return CultureInfo.InvariantCulture;
|
||||
|
||||
try
|
||||
{
|
||||
return CultureInfo.GetCultureInfo(ietfTag);
|
||||
}
|
||||
catch (CultureNotFoundException)
|
||||
{
|
||||
return CultureInfo.InvariantCulture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user