mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-05-14 12:14:09 +00:00
finished audit dialog
This commit is contained in:
parent
edfe6aa046
commit
dbe4ece333
@ -1,3 +1,4 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Provider;
|
||||
@ -20,9 +21,9 @@ public sealed class AssistantAuditAgent(ILogger<AssistantAuditAgent> logger, ILo
|
||||
protected override string JobDescription =>
|
||||
"""
|
||||
You audit Lua-based newly installed or updated assistant plugins in-depth for security risks in private and enterprise environments.
|
||||
The Lua code is parsed into functional assistants that help users with various tasks, like coding, e-mails, translations
|
||||
The Lua code is parsed into functional assistants that help users with various tasks, like coding, emails, translations
|
||||
and now everything that plugin devs develop. Assistants have a system prompt that is set once and sanitized by us with a security pre- and postamble.
|
||||
The user prompt is build dynamically at submit and consists of user prompt context followed by the actual user input (Text, Decisions, Time and Date, File and Web content etc.)
|
||||
The user prompt is built dynamically when the assistant is submitted and consists of user prompt context followed by the actual user input (text, decisions, time and date, file and web content, etc.)
|
||||
You analyze the plugin manifest code, the assistants' system prompt, the simulated user prompt,
|
||||
and the list of UI components. The simulated user prompt may contain empty, null-like, or
|
||||
placeholder values. Treat these placeholders as intentional audit input and focus on prompt
|
||||
@ -92,7 +93,7 @@ public sealed class AssistantAuditAgent(ILogger<AssistantAuditAgent> logger, ILo
|
||||
var provider = this.ResolveProvider();
|
||||
if (provider == AIStudio.Settings.Provider.NONE)
|
||||
{
|
||||
await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.SettingsSuggest, string.Format(TB("No provider is configured for Security Audit-Agent."))));
|
||||
await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.SettingsSuggest, string.Format(TB("No provider is configured for the Security Audit Agent."))));
|
||||
|
||||
return new AssistantAuditResult
|
||||
{
|
||||
@ -104,6 +105,7 @@ public sealed class AssistantAuditAgent(ILogger<AssistantAuditAgent> logger, ILo
|
||||
logger.LogInformation($"The assistant plugin audit agent uses the provider '{provider.InstanceName}' ({provider.UsedLLMProvider.ToName()}, confidence={provider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()}).");
|
||||
|
||||
var promptPreview = await plugin.BuildAuditPromptPreviewAsync(token);
|
||||
var luaManifest = FormatLuaManifest(plugin.ReadAllLuaFiles());
|
||||
var userPrompt = $$"""
|
||||
Audit this assistant plugin.
|
||||
|
||||
@ -115,7 +117,7 @@ public sealed class AssistantAuditAgent(ILogger<AssistantAuditAgent> logger, ILo
|
||||
|
||||
Assistant system prompt:
|
||||
```
|
||||
{{plugin.SystemPrompt}}
|
||||
{{plugin.RawSystemPrompt}}
|
||||
```
|
||||
|
||||
Simulated user prompt preview:
|
||||
@ -130,7 +132,7 @@ public sealed class AssistantAuditAgent(ILogger<AssistantAuditAgent> logger, ILo
|
||||
|
||||
Lua manifest:
|
||||
```lua
|
||||
{{plugin.ReadManifestCode()}}
|
||||
{{luaManifest}}
|
||||
```
|
||||
""";
|
||||
|
||||
@ -148,7 +150,7 @@ public sealed class AssistantAuditAgent(ILogger<AssistantAuditAgent> logger, ILo
|
||||
if (response.Content is not ContentText content || string.IsNullOrWhiteSpace(content.Text))
|
||||
{
|
||||
logger.LogWarning($"The assistant plugin audit agent did not return text: {response}");
|
||||
await MessageBus.INSTANCE.SendWarning(new (Icons.Material.Filled.PendingActions, string.Format(TB("The Security Audit was unsuccessful, because the LLMs response was unusable. The Audit Level remains Unknown, so please try again later."))));
|
||||
await MessageBus.INSTANCE.SendWarning(new (Icons.Material.Filled.PendingActions, string.Format(TB("The security check could not be completed because the LLM's response was unusable. The audit level remains Unknown, so please try again later."))));
|
||||
|
||||
return new AssistantAuditResult
|
||||
{
|
||||
@ -210,4 +212,24 @@ public sealed class AssistantAuditAgent(ILogger<AssistantAuditAgent> logger, ILo
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private static string FormatLuaManifest(IReadOnlyDictionary<string, string> luaFiles)
|
||||
{
|
||||
if (luaFiles.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
||||
foreach (var luaFile in luaFiles.OrderBy(file => file.Key, StringComparer.Ordinal))
|
||||
{
|
||||
if (builder.Length > 0)
|
||||
builder.AppendLine().AppendLine();
|
||||
|
||||
builder.Append("-- File: ");
|
||||
builder.AppendLine(luaFile.Key);
|
||||
builder.AppendLine(luaFile.Value);
|
||||
}
|
||||
|
||||
return builder.ToString().TrimEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,34 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Agents.AssistantAudit;
|
||||
|
||||
public sealed class AssistantAuditFinding
|
||||
{
|
||||
private readonly AssistantAuditLevel severity = AssistantAuditLevel.UNKNOWN;
|
||||
|
||||
[JsonIgnore]
|
||||
public AssistantAuditLevel Severity => this.severity;
|
||||
|
||||
[JsonPropertyName("severity")]
|
||||
public string SeverityText
|
||||
{
|
||||
get => this.Severity switch
|
||||
{
|
||||
AssistantAuditLevel.DANGEROUS => "critical",
|
||||
AssistantAuditLevel.CAUTION => "medium",
|
||||
AssistantAuditLevel.SAFE => "low",
|
||||
_ => "unknown",
|
||||
};
|
||||
init => this.severity = value?.Trim().ToLowerInvariant() switch
|
||||
{
|
||||
"critical" => AssistantAuditLevel.DANGEROUS,
|
||||
"medium" => AssistantAuditLevel.CAUTION,
|
||||
"low" => AssistantAuditLevel.SAFE,
|
||||
_ => AssistantAuditLevel.UNKNOWN,
|
||||
};
|
||||
}
|
||||
|
||||
public string Category { get; init; } = string.Empty;
|
||||
public string Location { get; init; } = string.Empty;
|
||||
public string Description { get; init; } = string.Empty;
|
||||
public string Recommendation { get; init; } = string.Empty;
|
||||
}
|
||||
|
||||
@ -46,11 +46,11 @@ LANG_NAME = "English (United States)"
|
||||
|
||||
UI_TEXT_CONTENT = {}
|
||||
|
||||
-- The Security Audit was unsuccessful, because the LLMs response was unusable. The Audit Level remains Unknown, so please try again later.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2113359519"] = "The Security Audit was unsuccessful, because the LLMs response was unusable. The Audit Level remains Unknown, so please try again later."
|
||||
-- The security check could not be completed because the LLM's response was unusable. The audit level remains Unknown, so please try again later.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2451573087"] = "The security check could not be completed because the LLM's response was unusable. The audit level remains Unknown, so please try again later."
|
||||
|
||||
-- No provider is configured for Security Audit-Agent.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T4000913009"] = "No provider is configured for Security Audit-Agent."
|
||||
-- No provider is configured for the Security Audit Agent.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T3605554201"] = "No provider is configured for the Security Audit Agent."
|
||||
|
||||
-- Needs Review
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITLEVELEXTENSIONS::T1114911302"] = "Needs Review"
|
||||
@ -2935,17 +2935,74 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T474393241"] = "Please select
|
||||
-- Delete Workspace
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T701874671"] = "Delete Workspace"
|
||||
|
||||
-- Entries: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1098127509"] = "Entries: {0}"
|
||||
|
||||
-- {0:0.##} GB
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1224874808"] = "{0:0.##} GB"
|
||||
|
||||
-- Potentially Dangerous Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1229643769"] = "Potentially Dangerous Plugin"
|
||||
|
||||
-- Plugin root
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1303883002"] = "Plugin root"
|
||||
|
||||
-- Last modified
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1310524248"] = "Last modified"
|
||||
|
||||
-- Count: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T131135808"] = "Count: {0}"
|
||||
|
||||
-- {0:0.##} MB
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1357418474"] = "{0:0.##} MB"
|
||||
|
||||
-- No security issues were found during this check.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1423034104"] = "No security issues were found during this check."
|
||||
|
||||
-- No provider configured
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1476185409"] = "No provider configured"
|
||||
|
||||
-- {0:0.##} KB
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T14914764"] = "{0:0.##} KB"
|
||||
|
||||
-- Prompt: empty
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1533307170"] = "Prompt: empty"
|
||||
|
||||
-- This plugin is below the required safety level. Your settings still allow activation, but enabling it requires an extra confirmation because it may be unsafe.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1539381299"] = "This plugin is below the required safety level. Your settings still allow activation, but enabling it requires an extra confirmation because it may be unsafe."
|
||||
|
||||
-- Components
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1550582665"] = "Components"
|
||||
|
||||
-- Created
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T165548891"] = "Created"
|
||||
|
||||
-- Lua Manifest
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T165738710"] = "Lua Manifest"
|
||||
|
||||
-- Required minimum level
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1862086522"] = "Required minimum level"
|
||||
-- Enable Assistant Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1676241565"] = "Enable Assistant Plugin"
|
||||
|
||||
-- Unknown plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1834795216"] = "Unknown plugin"
|
||||
|
||||
-- This plugin cannot be activated because its audit result is below the required safety level and your settings block activation in this case.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1839656215"] = "This plugin cannot be activated because its audit result is below the required safety level and your settings block activation in this case."
|
||||
|
||||
-- Children: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T193192210"] = "Children: {0}"
|
||||
|
||||
-- null
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1996966820"] = "null"
|
||||
|
||||
-- Properties
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2177370620"] = "Properties"
|
||||
|
||||
-- Items: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2204150657"] = "Items: {0}"
|
||||
|
||||
-- {0} B
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2562655035"] = "{0} B"
|
||||
|
||||
-- The assistant plugin could not be resolved for auditing.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T273798258"] = "The assistant plugin could not be resolved for auditing."
|
||||
@ -2953,17 +3010,50 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T273798258"] = "
|
||||
-- Audit provider
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2757790517"] = "Audit provider"
|
||||
|
||||
-- Enable Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3233590741"] = "Enable Plugin"
|
||||
-- Size
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2789707388"] = "Size"
|
||||
|
||||
-- Prompt: set
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3156437951"] = "Prompt: set"
|
||||
|
||||
-- Findings
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3224848879"] = "Findings"
|
||||
|
||||
-- {0} | Last modified {1}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3350447013"] = "{0} | Last modified {1}"
|
||||
|
||||
-- The assistant plugin \"{0}\" was audited with the level \"{1}\", which is below the required safety level \"{2}\". Your current settings still allow activation, but this may be unsafe. Do you really want to enable this plugin?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3418077666"] = "The assistant plugin \\\"{0}\\\" was audited with the level \\\"{1}\\\", which is below the required safety level \\\"{2}\\\". Your current settings still allow activation, but this may be unsafe. Do you really want to enable this plugin?"
|
||||
|
||||
-- Unknown
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3424652889"] = "Unknown"
|
||||
|
||||
-- Close
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3448155331"] = "Close"
|
||||
|
||||
-- The audit uses a simulated prompt preview. Empty or placeholder values in the preview are expected during this security check.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T439841458"] = "The audit uses a simulated prompt preview. Empty or placeholder values in the preview are expected during this security check."
|
||||
-- Value
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3511155050"] = "Value"
|
||||
|
||||
-- Run Audit
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T564725977"] = "Run Audit"
|
||||
-- Last accessed
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3579946376"] = "Last accessed"
|
||||
|
||||
-- Unknown key
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3647690370"] = "Unknown key"
|
||||
|
||||
-- Minimum required safety level
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3652671056"] = "Minimum required safety level"
|
||||
|
||||
-- Unavailable
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3662391977"] = "Unavailable"
|
||||
|
||||
-- Plugin Structure
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T371537943"] = "Plugin Structure"
|
||||
|
||||
-- Audit Result
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3844960449"] = "Audit Result"
|
||||
|
||||
-- empty
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T413646574"] = "empty"
|
||||
|
||||
-- Prompt Preview
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T576347259"] = "Prompt Preview"
|
||||
@ -2971,6 +3061,15 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T576347259"] = "
|
||||
-- System Prompt
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T628396066"] = "System Prompt"
|
||||
|
||||
-- This security check uses a sample prompt preview. Empty or placeholder values in the preview are expected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T737998363"] = "This security check uses a sample prompt preview. Empty or placeholder values in the preview are expected."
|
||||
|
||||
-- Safe
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T760494712"] = "Safe"
|
||||
|
||||
-- Start Security Check
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T811648299"] = "Start Security Check"
|
||||
|
||||
-- Cancel
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T900713019"] = "Cancel"
|
||||
|
||||
@ -5773,6 +5872,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T870640199"] = "For some data tra
|
||||
-- Install Pandoc
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T986578435"] = "Install Pandoc"
|
||||
|
||||
-- Potentially Dangerous Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1229643769"] = "Potentially Dangerous Plugin"
|
||||
|
||||
-- Disable plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1430375822"] = "Disable plugin"
|
||||
|
||||
@ -5794,6 +5896,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2057806005"] = "Enable plugin"
|
||||
-- Plugins
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2222816203"] = "Plugins"
|
||||
|
||||
-- The assistant plugin \"{0}\" was audited with the level \"{1}\", which is below the required minimum level \"{2}\". Your current settings allow activation anyway, but this may be potentially dangerous. Do you really want to enable this plugin?
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2531356312"] = "The assistant plugin \\\"{0}\\\" was audited with the level \\\"{1}\\\", which is below the required minimum level \\\"{2}\\\". Your current settings allow activation anyway, but this may be potentially dangerous. Do you really want to enable this plugin?"
|
||||
|
||||
-- Enabled Plugins
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2738444034"] = "Enabled Plugins"
|
||||
|
||||
@ -6529,6 +6634,81 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T3290596792"] = "Error during Mi
|
||||
-- Microsoft Word export successful
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T4256043333"] = "Microsoft Word export successful"
|
||||
|
||||
-- Stack
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T135058847"] = "Stack"
|
||||
|
||||
-- Button group
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1392576058"] = "Button group"
|
||||
|
||||
-- Profiles Selection
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1437749589"] = "Profiles Selection"
|
||||
|
||||
-- Image
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1494001562"] = "Image"
|
||||
|
||||
-- Text Area
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1593629311"] = "Text Area"
|
||||
|
||||
-- File Content
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T165091006"] = "File Content"
|
||||
|
||||
-- Grid Item
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1991378436"] = "Grid Item"
|
||||
|
||||
-- List
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T2368288673"] = "List"
|
||||
|
||||
-- Provider Selection
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T268262394"] = "Provider Selection"
|
||||
|
||||
-- Root
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T2703841893"] = "Root"
|
||||
|
||||
-- Container
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T2990360344"] = "Container"
|
||||
|
||||
-- Accordion
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3372988345"] = "Accordion"
|
||||
|
||||
-- Date Range
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3400615792"] = "Date Range"
|
||||
|
||||
-- Plane Text
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3557717784"] = "Plane Text"
|
||||
|
||||
-- Switch
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3656636817"] = "Switch"
|
||||
|
||||
-- Time
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3756319748"] = "Time"
|
||||
|
||||
-- Dropdown
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3829804792"] = "Dropdown"
|
||||
|
||||
-- Color
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3853794552"] = "Color"
|
||||
|
||||
-- Accordion Section
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T4180733902"] = "Accordion Section"
|
||||
|
||||
-- Heading
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T4231005109"] = "Heading"
|
||||
|
||||
-- Unknown Element
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T434854509"] = "Unknown Element"
|
||||
|
||||
-- Web Content
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T590188228"] = "Web Content"
|
||||
|
||||
-- Grid
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T800286385"] = "Grid"
|
||||
|
||||
-- Button
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T864557713"] = "Button"
|
||||
|
||||
-- Date
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T995259257"] = "Date"
|
||||
|
||||
-- Failed to parse the UI render tree from the ASSISTANT lua table.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T1318499252"] = "Failed to parse the UI render tree from the ASSISTANT lua table."
|
||||
|
||||
|
||||
10
app/MindWork AI Studio/Components/AssistantAuditTreeItem.cs
Normal file
10
app/MindWork AI Studio/Components/AssistantAuditTreeItem.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace AIStudio.Components;
|
||||
|
||||
public sealed class AssistantAuditTreeItem : ITreeItem
|
||||
{
|
||||
public string Text { get; init; } = string.Empty;
|
||||
public string Icon { get; init; } = string.Empty;
|
||||
public string Caption { get; init; } = string.Empty;
|
||||
public bool Expandable { get; init; }
|
||||
public bool IsComponent { get; init; } = true;
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
@using AIStudio.Agents.AssistantAudit
|
||||
@using AIStudio.Components
|
||||
@inherits MSGComponentBase
|
||||
|
||||
<MudDialog DefaultFocus="DefaultFocus.FirstChild">
|
||||
@ -11,9 +12,9 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudStack Spacing="2">
|
||||
<MudAlert Severity="Severity.Info" Dense="true">
|
||||
@T("The audit uses a simulated prompt preview. Empty or placeholder values in the preview are expected during this security check.")
|
||||
<MudStack Spacing="2">
|
||||
<MudAlert Severity="Severity.Info" Dense="true">
|
||||
@T("This security check uses a sample prompt preview. Empty or placeholder values in the preview are expected.")
|
||||
</MudAlert>
|
||||
|
||||
<MudPaper Class="pa-3 border-dashed border rounded-lg">
|
||||
@ -23,53 +24,214 @@
|
||||
@T("Audit provider"): <strong>@this.ProviderLabel</strong>
|
||||
</MudText>
|
||||
<MudText Typo="Typo.body2">
|
||||
@T("Required minimum level"): <strong>@this.MinimumLevelLabel</strong>
|
||||
@T("Minimum required safety level"): <strong>@this.MinimumLevelLabel</strong>
|
||||
</MudText>
|
||||
</MudPaper>
|
||||
|
||||
<MudExpansionPanels MultiExpansion="true">
|
||||
<MudExpansionPanel Text="@T("System Prompt")" Expanded="true">
|
||||
<MudTextField T="string" Text="@this.plugin.SystemPrompt" ReadOnly="true" Variant="Variant.Outlined" Lines="8" Class="mt-2" />
|
||||
<MudExpansionPanel Expanded="true">
|
||||
<TitleContent>
|
||||
<div class="d-flex">
|
||||
<MudIcon Icon="@Icons.Material.Filled.EditNote" class="mr-3" Color="Color.Primary"></MudIcon>
|
||||
<MudText>@T("System Prompt")</MudText>
|
||||
</div>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
<MudTextField T="string" Text="@this.plugin.RawSystemPrompt" ReadOnly="true" Variant="Variant.Outlined" Lines="8" Class="mt-2"/>
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
<MudExpansionPanel Text="@T("Prompt Preview")" Expanded="true">
|
||||
<MudTextField T="string" Text="@this.promptPreview" ReadOnly="true" Variant="Variant.Outlined" Lines="8" Class="mt-2" />
|
||||
<MudExpansionPanel Expanded="false">
|
||||
<TitleContent>
|
||||
<div class="d-flex">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Preview" class="mr-3" Color="Color.Primary"></MudIcon>
|
||||
<MudText>@T("Prompt Preview")</MudText>
|
||||
</div>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
<MudTextField T="string" Text="@this.promptPreview" ReadOnly="true" Variant="Variant.Outlined" Lines="8" Class="mt-2"/>
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
<MudExpansionPanel Text="@T("Components")">
|
||||
<MudTextField T="string" Text="@this.componentSummary" ReadOnly="true" Variant="Variant.Outlined" Lines="10" Class="mt-2" />
|
||||
<MudExpansionPanel KeepContentAlive="false">
|
||||
<TitleContent>
|
||||
<div class="d-flex">
|
||||
<MudIcon Icon="@Icons.Material.Filled.AccountTree" class="mr-3" Color="Color.Primary"></MudIcon>
|
||||
<MudText>@T("Components")</MudText>
|
||||
</div>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
<MudTreeView T="ITreeItem" Items="@this.componentTreeItems" ReadOnly="true" Hover="true" Dense="true" Disabled="false" ExpandOnClick="true" Class="mt-3">
|
||||
<ItemTemplate Context="item">
|
||||
@if (item.Value is AssistantAuditTreeItem treeItem)
|
||||
{
|
||||
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@item.Children">
|
||||
<BodyContent>
|
||||
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
||||
<MudText Style="justify-self: start;">
|
||||
@treeItem.Text
|
||||
</MudText>
|
||||
@if (!string.IsNullOrWhiteSpace(treeItem.Caption))
|
||||
{
|
||||
if (treeItem.IsComponent)
|
||||
{
|
||||
<MudText Typo="Typo.caption" Color="Color.Secondary" Style="justify-self: end;">
|
||||
@treeItem.Caption
|
||||
</MudText>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.overline" Color="Color.Primary" Style="justify-self: end;">
|
||||
@treeItem.Caption
|
||||
</MudText>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</BodyContent>
|
||||
</MudTreeViewItem>
|
||||
}
|
||||
</ItemTemplate>
|
||||
</MudTreeView>
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
<MudExpansionPanel Text="@T("Lua Manifest")">
|
||||
<MudTextField T="string" Text="@this.luaCode" ReadOnly="true" Variant="Variant.Outlined" Lines="18" Class="mt-2" />
|
||||
<MudExpansionPanel KeepContentAlive="false">
|
||||
<TitleContent>
|
||||
<div class="d-flex">
|
||||
<MudIcon Icon="@Icons.Material.Filled.FolderZip" class="mr-3" Color="Color.Primary"></MudIcon>
|
||||
<MudText>@T("Plugin Structure")</MudText>
|
||||
</div>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
<MudTreeView T="ITreeItem" Items="@this.fileSystemTreeItems" ReadOnly="true" Hover="true" Dense="true" Disabled="false" ExpandOnClick="true" Class="mt-3">
|
||||
<ItemTemplate Context="item">
|
||||
@if (item.Value is AssistantAuditTreeItem treeItem)
|
||||
{
|
||||
<MudTreeViewItem T="ITreeItem" Icon="@treeItem.Icon" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@item.Children">
|
||||
<BodyContent>
|
||||
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
||||
<MudText Style="justify-self: start;">
|
||||
@treeItem.Text
|
||||
</MudText>
|
||||
@if (!string.IsNullOrWhiteSpace(treeItem.Caption))
|
||||
{
|
||||
<MudText Typo="Typo.caption" Color="Color.Secondary" Style="justify-self: end;">
|
||||
@treeItem.Caption
|
||||
</MudText>
|
||||
}
|
||||
</div>
|
||||
</BodyContent>
|
||||
</MudTreeViewItem>
|
||||
}
|
||||
</ItemTemplate>
|
||||
</MudTreeView>
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
<MudExpansionPanel KeepContentAlive="false">
|
||||
<TitleContent>
|
||||
<div class="d-flex">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Code" class="mr-3" Color="Color.Primary"></MudIcon>
|
||||
<MudText>@T("Lua Manifest")</MudText>
|
||||
</div>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
<MudExpansionPanels Elevation="0" Dense="true">
|
||||
@foreach (var file in this.luaFiles)
|
||||
{
|
||||
var fileInfo = new FileInfo(Path.Combine(this.plugin.PluginPath, file.Key));
|
||||
<MudExpansionPanel Expanded="false" Icon="@Icons.Material.Outlined.ArrowDropDown">
|
||||
<TitleContent>
|
||||
<div class="d-flex align-center justify-start">
|
||||
<MudTooltip Placement="Placement.Left" Arrow="true">
|
||||
<ChildContent>
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Info" Size="Size.Small" Color="Color.Info" Class="mr-1"/>
|
||||
</ChildContent>
|
||||
<TooltipContent>
|
||||
<MudPaper Class="pa-3" >
|
||||
<MudStack Spacing="1">
|
||||
<MudText Typo="Typo.subtitle2">@file.Key</MudText>
|
||||
<MudDivider/>
|
||||
<MudText Typo="Typo.body2">@T("Size"): @this.FormatFileSize(fileInfo.Length)</MudText>
|
||||
<MudText Typo="Typo.body2">@T("Created"): @this.FormatFileTimestamp(fileInfo.CreationTime)</MudText>
|
||||
<MudText Typo="Typo.body2">@T("Last accessed"): @this.FormatFileTimestamp(fileInfo.LastAccessTime)</MudText>
|
||||
<MudText Typo="Typo.body2">@T("Last modified"): @this.FormatFileTimestamp(fileInfo.LastWriteTime)</MudText>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
</TooltipContent>
|
||||
</MudTooltip>
|
||||
<MudText Class="">@file.Key</MudText>
|
||||
</div>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
<MudTextField T="string" Text="@file.Value" ReadOnly="true" Variant="Variant.Outlined" Lines="25" Class="mt-2" Style="font-family: monospace"/>
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
</MudExpansionPanels>
|
||||
|
||||
@if (this.audit is not null)
|
||||
{
|
||||
<MudAlert Severity="@this.audit.Level.GetSeverity()" Dense="true">
|
||||
<strong>@this.audit.Level.GetName()</strong>: @this.audit.Summary
|
||||
</MudAlert>
|
||||
<MudStack Spacing="2" Class="mt-4">
|
||||
<MudText Typo="Typo.h6">@T("Audit Result")</MudText>
|
||||
|
||||
@if (this.audit.Findings.Count > 0)
|
||||
{
|
||||
<MudList T="string" Dense="true" Class="border rounded-lg">
|
||||
@foreach (var finding in this.audit.Findings)
|
||||
@if (this.audit.Findings.Count == 0 && this.audit.Level is not AssistantAuditLevel.UNKNOWN)
|
||||
{
|
||||
<MudAlert Severity="Severity.Success" Variant="Variant.Filled" Dense="true" Icon="@Icons.Material.Filled.VerifiedUser">
|
||||
<strong>@T("Safe")</strong><span>: @T("No security issues were found during this check.")</span>
|
||||
</MudAlert>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudAlert Severity="@this.GetAuditResultSeverity()" Variant="Variant.Filled" Dense="true">
|
||||
<strong>@this.audit.Level.GetName()</strong><span>: @this.audit.Summary</span>
|
||||
</MudAlert>
|
||||
|
||||
@if (this.IsActivationBlockedBySettings)
|
||||
{
|
||||
<MudListItem T="string">
|
||||
<div>
|
||||
<strong>@finding.Category</strong>
|
||||
@if (!string.IsNullOrWhiteSpace(finding.Location))
|
||||
{
|
||||
<span> (@finding.Location)</span>
|
||||
}
|
||||
<div>@finding.Description</div>
|
||||
@if (!string.IsNullOrWhiteSpace(finding.Recommendation))
|
||||
{
|
||||
<div><em>@finding.Recommendation</em></div>
|
||||
}
|
||||
</div>
|
||||
</MudListItem>
|
||||
<MudAlert Severity="Severity.Error" Variant="Variant.Text" Dense="true" Icon="@Icons.Material.Filled.Block">
|
||||
@T("This plugin cannot be activated because its audit result is below the required safety level and your settings block activation in this case.")
|
||||
</MudAlert>
|
||||
}
|
||||
</MudList>
|
||||
}
|
||||
else if (this.RequiresActivationConfirmation)
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning" Variant="Variant.Text" Dense="true" Icon="@Icons.Material.Filled.WarningAmber">
|
||||
@T("This plugin is below the required safety level. Your settings still allow activation, but enabling it requires an extra confirmation because it may be unsafe.")
|
||||
</MudAlert>
|
||||
}
|
||||
|
||||
<MudText Typo="Typo.subtitle2">@T("Findings")</MudText>
|
||||
<MudStack Spacing="2">
|
||||
@foreach (var finding in this.audit.Findings)
|
||||
{
|
||||
<MudAlert Severity="@this.GetFindingSeverity(finding.Severity)"
|
||||
Variant="Variant.Text"
|
||||
Dense="true"
|
||||
Icon="@this.GetFindingIcon(finding.Severity)"
|
||||
Class="pa-3"
|
||||
Elevation="3">
|
||||
<MudStack Spacing="1" Class="mt-n2">
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween">
|
||||
<MudText Typo="Typo.subtitle2">@finding.Category</MudText>
|
||||
<MudChip T="string"
|
||||
Variant="Variant.Text"
|
||||
Color="@this.GetFindingColor(finding.Severity)"
|
||||
Size="Size.Small">
|
||||
@finding.Severity.GetName()
|
||||
</MudChip>
|
||||
</MudStack>
|
||||
|
||||
@if (!string.IsNullOrEmpty(finding.Location))
|
||||
{
|
||||
<MudText Typo="Typo.caption">@finding.Location</MudText>
|
||||
}
|
||||
|
||||
<MudText Typo="Typo.body2">@finding.Description</MudText>
|
||||
</MudStack>
|
||||
</MudAlert>
|
||||
}
|
||||
</MudStack>
|
||||
}
|
||||
</MudStack>
|
||||
}
|
||||
</MudStack>
|
||||
}
|
||||
@ -79,10 +241,13 @@
|
||||
@(this.audit is null ? T("Cancel") : T("Close"))
|
||||
</MudButton>
|
||||
<MudButton OnClick="@this.RunAudit" Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!this.CanRunAudit)">
|
||||
@T("Run Audit")
|
||||
</MudButton>
|
||||
<MudButton OnClick="@this.EnablePlugin" Variant="Variant.Filled" Color="@this.EnableButtonColor" Disabled="@(!this.CanEnablePlugin)">
|
||||
@T("Enable Plugin")
|
||||
@T("Start Security Check")
|
||||
</MudButton>
|
||||
@if (this.CanEnablePlugin)
|
||||
{
|
||||
<MudButton OnClick="@this.EnablePlugin" Variant="Variant.Filled" Color="@this.EnableButtonColor">
|
||||
@T("Enable Assistant Plugin")
|
||||
</MudButton>
|
||||
}
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@ -1,48 +1,85 @@
|
||||
using AIStudio.Agents.AssistantAudit;
|
||||
using AIStudio.Components;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings.DataModel;
|
||||
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
|
||||
{
|
||||
[CascadingParameter]
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(AssistantPluginAuditDialog).Namespace,
|
||||
nameof(AssistantPluginAuditDialog));
|
||||
|
||||
[CascadingParameter]
|
||||
private IMudDialogInstance MudDialog { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private AssistantAuditAgent AuditAgent { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public Guid PluginId { get; set; }
|
||||
[Parameter] public Guid PluginId { get; set; }
|
||||
|
||||
private PluginAssistants? plugin;
|
||||
private PluginAssistantAudit? audit;
|
||||
private string promptPreview = string.Empty;
|
||||
private string componentSummary = string.Empty;
|
||||
private string luaCode = string.Empty;
|
||||
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 bool isAuditing;
|
||||
|
||||
private AIStudio.Settings.Provider CurrentProvider => this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_ASSISTANT_PLUGIN_AUDIT, null, true);
|
||||
|
||||
private string ProviderLabel => this.CurrentProvider == AIStudio.Settings.Provider.NONE
|
||||
? this.T("No provider configured")
|
||||
: $"{this.CurrentProvider.InstanceName} ({this.CurrentProvider.UsedLLMProvider.ToName()})";
|
||||
|
||||
private DataAssistantPluginAudit AuditSettings => this.SettingsManager.ConfigurationData.AssistantPluginAudit;
|
||||
|
||||
private AssistantAuditLevel MinimumLevel => this.SettingsManager.ConfigurationData.AssistantPluginAudit.MinimumLevel;
|
||||
|
||||
private string MinimumLevelLabel => this.MinimumLevel.GetName();
|
||||
private bool CanRunAudit => this.plugin is not null && this.CurrentProvider != AIStudio.Settings.Provider.NONE && !this.isAuditing;
|
||||
private bool CanEnablePlugin => this.audit is not null && (this.audit.Level >= this.MinimumLevel || !this.SettingsManager.ConfigurationData.AssistantPluginAudit.BlockActivationBelowMinimum);
|
||||
private Color EnableButtonColor => this.audit is not null && this.audit.Level >= this.MinimumLevel ? Color.Success : Color.Warning;
|
||||
|
||||
private bool CanRunAudit => this.plugin is not null && this.CurrentProvider != AIStudio.Settings.Provider.NONE &&
|
||||
!this.isAuditing;
|
||||
|
||||
private bool IsAuditBelowMinimum => this.audit is not null && this.audit.Level < this.MinimumLevel;
|
||||
|
||||
private bool IsActivationBlockedBySettings => this.audit is null || this.IsAuditBelowMinimum && this.AuditSettings.BlockActivationBelowMinimum;
|
||||
|
||||
private bool RequiresActivationConfirmation => this.audit is not null && this.IsAuditBelowMinimum && !this.AuditSettings.BlockActivationBelowMinimum;
|
||||
|
||||
private bool CanEnablePlugin => this.audit is not null && !this.isAuditing && !this.IsActivationBlockedBySettings;
|
||||
|
||||
private Color EnableButtonColor => this.RequiresActivationConfirmation ? Color.Warning : Color.Success;
|
||||
|
||||
private const ushort BYTES_PER_KILOBYTE = 1024;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
this.plugin = PluginFactory.RunningPlugins.OfType<PluginAssistants>().FirstOrDefault(x => x.Id == this.PluginId);
|
||||
var activeLanguagePlugin = await this.SettingsManager.GetActiveLanguagePlugin();
|
||||
this.fileInfoCulture = this.CreateFileInfoCulture(activeLanguagePlugin.IETFTag);
|
||||
|
||||
this.plugin = PluginFactory.RunningPlugins.OfType<PluginAssistants>()
|
||||
.FirstOrDefault(x => x.Id == this.PluginId);
|
||||
if (this.plugin is not null)
|
||||
{
|
||||
this.promptPreview = await this.plugin.BuildAuditPromptPreviewAsync();
|
||||
this.componentSummary = this.plugin.CreateAuditComponentSummary();
|
||||
this.luaCode = this.plugin.ReadManifestCode();
|
||||
this.componentTreeItems = this.CreateAuditTreeItems(this.plugin.RootComponent);
|
||||
this.fileSystemTreeItems = this.CreatePluginFileSystemTreeItems(this.plugin.PluginPath);
|
||||
this.luaFiles = this.plugin.ReadAllLuaFiles();
|
||||
}
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
@ -65,7 +102,9 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
|
||||
PluginHash = this.plugin.ComputeAuditHash(),
|
||||
AuditedAtUtc = DateTimeOffset.UtcNow,
|
||||
AuditProviderId = this.CurrentProvider.Id,
|
||||
AuditProviderName = this.CurrentProvider == AIStudio.Settings.Provider.NONE ? string.Empty : this.CurrentProvider.InstanceName,
|
||||
AuditProviderName = this.CurrentProvider == AIStudio.Settings.Provider.NONE
|
||||
? string.Empty
|
||||
: this.CurrentProvider.InstanceName,
|
||||
Level = AssistantAuditLevelExtensions.Parse(result.Level),
|
||||
Summary = result.Summary,
|
||||
Confidence = result.Confidence,
|
||||
@ -91,11 +130,408 @@ public partial class AssistantPluginAuditDialog : MSGComponentBase
|
||||
this.MudDialog.Close(DialogResult.Ok(new AssistantPluginAuditDialogResult(this.audit, false)));
|
||||
}
|
||||
|
||||
private void EnablePlugin()
|
||||
private async Task EnablePlugin()
|
||||
{
|
||||
if (this.audit is null)
|
||||
return;
|
||||
|
||||
if (this.IsActivationBlockedBySettings)
|
||||
return;
|
||||
|
||||
if (this.RequiresActivationConfirmation && !await this.ConfirmActivationBelowMinimumAsync())
|
||||
return;
|
||||
|
||||
this.MudDialog.Close(DialogResult.Ok(new AssistantPluginAuditDialogResult(this.audit, true)));
|
||||
}
|
||||
|
||||
private async Task<bool> ConfirmActivationBelowMinimumAsync()
|
||||
{
|
||||
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||
{
|
||||
{
|
||||
x => x.Message,
|
||||
string.Format(
|
||||
T("The assistant plugin \"{0}\" was audited with the level \"{1}\", which is below the required safety level \"{2}\". Your current settings still allow activation, but this may be unsafe. Do you really want to enable this plugin?"),
|
||||
this.plugin?.Name ?? T("Unknown plugin"),
|
||||
this.audit?.Level.GetName() ?? T("Unknown"),
|
||||
this.MinimumLevelLabel)
|
||||
},
|
||||
};
|
||||
|
||||
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(T("Potentially Dangerous Plugin"), dialogParameters, DialogOptions.FULLSCREEN);
|
||||
var dialogResult = await dialogReference.Result;
|
||||
return dialogResult is not null && !dialogResult.Canceled;
|
||||
}
|
||||
|
||||
private Severity GetAuditResultSeverity() => this.audit?.Level switch
|
||||
{
|
||||
AssistantAuditLevel.DANGEROUS => Severity.Error,
|
||||
AssistantAuditLevel.CAUTION => Severity.Warning,
|
||||
AssistantAuditLevel.SAFE => Severity.Success,
|
||||
_ => Severity.Normal,
|
||||
};
|
||||
|
||||
private Severity GetFindingSeverity(AssistantAuditLevel severity) => severity switch
|
||||
{
|
||||
AssistantAuditLevel.DANGEROUS => Severity.Error,
|
||||
AssistantAuditLevel.CAUTION => Severity.Warning,
|
||||
AssistantAuditLevel.SAFE => Severity.Success,
|
||||
_ => Severity.Normal,
|
||||
};
|
||||
|
||||
private string GetFindingIcon(AssistantAuditLevel severity) => severity switch
|
||||
{
|
||||
AssistantAuditLevel.DANGEROUS => Icons.Material.Filled.Dangerous,
|
||||
AssistantAuditLevel.CAUTION => Icons.Material.Filled.WarningAmber,
|
||||
AssistantAuditLevel.SAFE => Icons.Material.Filled.Verified,
|
||||
_ => Icons.Material.Filled.Info,
|
||||
};
|
||||
|
||||
private Color GetFindingColor(AssistantAuditLevel severity) => severity switch
|
||||
{
|
||||
AssistantAuditLevel.DANGEROUS => Color.Error,
|
||||
AssistantAuditLevel.CAUTION => Color.Warning,
|
||||
AssistantAuditLevel.SAFE => Color.Success,
|
||||
_ => Color.Default,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Creates the full audit tree for the assistant component hierarchy.
|
||||
/// The dialog owns this mapping because it is pure presentation logic for the audit UI.
|
||||
/// </summary>
|
||||
private IReadOnlyCollection<TreeItemData<ITreeItem>> CreateAuditTreeItems(IAssistantComponent? rootComponent)
|
||||
{
|
||||
if (rootComponent is null)
|
||||
return [];
|
||||
|
||||
return [this.CreateComponentTreeItem(rootComponent, index: 0, depth: 0)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps one assistant component into a tree node and recursively appends its value, props and child components.
|
||||
/// </summary>
|
||||
private TreeItemData<ITreeItem> CreateComponentTreeItem(IAssistantComponent component, int index, int depth)
|
||||
{
|
||||
var children = new List<TreeItemData<ITreeItem>>();
|
||||
|
||||
if (component.Props.TryGetValue("Value", out var value))
|
||||
children.Add(this.CreateValueTreeItem(TB("Value"), value, depth + 1));
|
||||
|
||||
if (component.Props.Count > 0)
|
||||
children.Add(this.CreatePropsTreeItem(component.Props, depth + 1));
|
||||
|
||||
children.AddRange(component.Children.Select((child, childIndex) =>
|
||||
this.CreateComponentTreeItem(child, childIndex, depth + 1)));
|
||||
|
||||
return new TreeItemData<ITreeItem>
|
||||
{
|
||||
Expanded = depth < 2,
|
||||
Expandable = children.Count > 0,
|
||||
Value = new AssistantAuditTreeItem
|
||||
{
|
||||
Text = this.GetComponentTreeItemText(component),
|
||||
Caption = this.GetComponentTreeItemCaption(component, index),
|
||||
Icon = component.Type.GetIcon(),
|
||||
Expandable = children.Count > 0,
|
||||
},
|
||||
Children = children,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Groups all props of a component under a single "Props" branch to keep the component nodes compact.
|
||||
/// </summary>
|
||||
private TreeItemData<ITreeItem> CreatePropsTreeItem(IReadOnlyDictionary<string, object> props, int depth)
|
||||
{
|
||||
var children = props
|
||||
.OrderBy(prop => prop.Key, StringComparer.Ordinal)
|
||||
.Select(prop => this.CreateValueTreeItem(prop.Key, prop.Value, depth + 1))
|
||||
.ToList();
|
||||
|
||||
return new TreeItemData<ITreeItem>
|
||||
{
|
||||
Expanded = depth < 2,
|
||||
Expandable = children.Count > 0,
|
||||
Value = new AssistantAuditTreeItem
|
||||
{
|
||||
Text = TB("Properties"),
|
||||
Caption = string.Format(TB("Count: {0}"), props.Count),
|
||||
Icon = Icons.Material.Filled.Code,
|
||||
Expandable = children.Count > 0,
|
||||
IsComponent = false,
|
||||
},
|
||||
Children = children,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a scalar or structured prop value into a tree node.
|
||||
/// Scalars stay on one line, while structured values recursively expose their children.
|
||||
/// </summary>
|
||||
private TreeItemData<ITreeItem> CreateValueTreeItem(string label, object? value, int depth)
|
||||
{
|
||||
var children = this.CreateValueChildren(value, depth + 1);
|
||||
return new TreeItemData<ITreeItem>
|
||||
{
|
||||
Expanded = depth < 2,
|
||||
Expandable = children.Count > 0,
|
||||
Value = new AssistantAuditTreeItem
|
||||
{
|
||||
Text = label,
|
||||
Caption = children.Count == 0 ? this.FormatScalarValue(value) : this.GetStructuredValueCaption(value),
|
||||
Icon = this.GetValueIcon(value),
|
||||
Expandable = children.Count > 0,
|
||||
IsComponent = false,
|
||||
},
|
||||
Children = children,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recursively expands structured values for the tree.
|
||||
/// Lists, dictionaries and known DTO-style assistant values become nested tree branches.
|
||||
/// </summary>
|
||||
private List<TreeItemData<ITreeItem>> CreateValueChildren(object? value, int depth)
|
||||
{
|
||||
if (value is null || IsScalarValue(value))
|
||||
return [];
|
||||
|
||||
if (value is IDictionary dictionary)
|
||||
return this.CreateDictionaryChildren(dictionary, depth);
|
||||
|
||||
if (value is IEnumerable enumerable && value is not string)
|
||||
return this.CreateEnumerableChildren(enumerable, depth);
|
||||
|
||||
return this.CreateObjectChildren(value, depth);
|
||||
}
|
||||
|
||||
private List<TreeItemData<ITreeItem>> CreateDictionaryChildren(IDictionary dictionary, int depth)
|
||||
{
|
||||
var children = new List<TreeItemData<ITreeItem>>();
|
||||
foreach (DictionaryEntry entry in dictionary)
|
||||
{
|
||||
var keyText = entry.Key.ToString() ?? TB("Unknown key");
|
||||
children.Add(this.CreateValueTreeItem(keyText, entry.Value, depth));
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a tree for the plugin directory so the audit can show unexpected folders and files, while excluding irrelevant dependency folders.
|
||||
/// </summary>
|
||||
private IReadOnlyCollection<TreeItemData<ITreeItem>> CreatePluginFileSystemTreeItems(string pluginPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pluginPath) || !Directory.Exists(pluginPath))
|
||||
return [];
|
||||
|
||||
return [this.CreateDirectoryTreeItem(pluginPath, pluginPath, depth: 0)];
|
||||
}
|
||||
|
||||
private TreeItemData<ITreeItem> CreateDirectoryTreeItem(string directoryPath, string rootPath, int depth)
|
||||
{
|
||||
var childDirectories = Directory.EnumerateDirectories(directoryPath)
|
||||
.OrderBy(path => path, StringComparer.Ordinal)
|
||||
.Select(path => this.CreateDirectoryTreeItem(path, rootPath, depth + 1))
|
||||
.ToList();
|
||||
|
||||
var childFiles = Directory.EnumerateFiles(directoryPath)
|
||||
.OrderBy(path => path, StringComparer.Ordinal)
|
||||
.Select(path => this.CreateFileTreeItem(path, depth + 1))
|
||||
.ToList();
|
||||
|
||||
var children = new List<TreeItemData<ITreeItem>>(childDirectories.Count + childFiles.Count);
|
||||
children.AddRange(childDirectories);
|
||||
children.AddRange(childFiles);
|
||||
|
||||
var relativePath = Path.GetRelativePath(rootPath, directoryPath);
|
||||
var displayName = depth == 0
|
||||
? Path.GetFileName(directoryPath)
|
||||
: relativePath.Split(Path.DirectorySeparatorChar).Last();
|
||||
|
||||
return new TreeItemData<ITreeItem>
|
||||
{
|
||||
Expanded = depth < 2,
|
||||
Expandable = children.Count > 0,
|
||||
Value = new AssistantAuditTreeItem
|
||||
{
|
||||
Text = string.IsNullOrWhiteSpace(displayName) ? directoryPath : displayName,
|
||||
Caption = depth == 0 ? TB("Plugin root") : string.Format(TB("Items: {0}"), children.Count),
|
||||
Icon = children.Count > 0 ? Icons.Material.Filled.FolderCopy : Icons.Material.Filled.Folder,
|
||||
Expandable = children.Count > 0,
|
||||
IsComponent = false,
|
||||
},
|
||||
Children = children,
|
||||
};
|
||||
}
|
||||
|
||||
private TreeItemData<ITreeItem> CreateFileTreeItem(string filePath, int depth)
|
||||
{
|
||||
var fileInfo = new FileInfo(filePath);
|
||||
|
||||
return new TreeItemData<ITreeItem>
|
||||
{
|
||||
Expanded = depth < 2,
|
||||
Expandable = false,
|
||||
Value = new AssistantAuditTreeItem
|
||||
{
|
||||
Text = Path.GetFileName(filePath),
|
||||
Caption = string.Format(TB("{0} | Last modified {1}"), this.FormatFileSize(fileInfo.Length),
|
||||
this.FormatFileTimestamp(fileInfo.LastWriteTime)),
|
||||
Icon = this.GetFileIcon(filePath),
|
||||
Expandable = false,
|
||||
IsComponent = false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private string GetFileIcon(string filePath)
|
||||
{
|
||||
var extension = Path.GetExtension(filePath);
|
||||
return extension.ToLowerInvariant() switch
|
||||
{
|
||||
".lua" => Icons.Material.Filled.Code,
|
||||
".md" => Icons.Material.Filled.Article,
|
||||
".json" => Icons.Material.Filled.DataObject,
|
||||
".png" or ".jpg" or ".jpeg" or ".svg" or ".webp" => Icons.Material.Filled.Image,
|
||||
_ => Icons.Material.Filled.InsertDriveFile,
|
||||
};
|
||||
}
|
||||
|
||||
private List<TreeItemData<ITreeItem>> CreateEnumerableChildren(IEnumerable enumerable, int depth)
|
||||
{
|
||||
var children = new List<TreeItemData<ITreeItem>>();
|
||||
var index = 0;
|
||||
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
children.Add(this.CreateValueTreeItem($"[{index}]", item, depth));
|
||||
index++;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Falls back to public instance properties for simple DTO-style values such as dropdown items.
|
||||
/// Getter failures are treated defensively so the audit dialog never crashes because of a problematic property.
|
||||
/// </summary>
|
||||
private List<TreeItemData<ITreeItem>> CreateObjectChildren(object value, int depth)
|
||||
{
|
||||
var children = new List<TreeItemData<ITreeItem>>();
|
||||
|
||||
foreach (var property in value.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
|
||||
{
|
||||
if (!property.CanRead || property.GetIndexParameters().Length != 0)
|
||||
continue;
|
||||
|
||||
object? propertyValue;
|
||||
try
|
||||
{
|
||||
propertyValue = property.GetValue(value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
propertyValue = TB("Unavailable");
|
||||
}
|
||||
|
||||
children.Add(this.CreateValueTreeItem(property.Name, propertyValue, depth));
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
private string GetComponentTreeItemText(IAssistantComponent component)
|
||||
{
|
||||
var type = component.Type.GetDisplayName();
|
||||
if (component is INamedAssistantComponent named && !string.IsNullOrWhiteSpace(named.Name))
|
||||
return $"{type}: {named.Name}";
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
private string GetComponentTreeItemCaption(IAssistantComponent component, int index)
|
||||
{
|
||||
var details = new List<string> { $"#{index + 1}" };
|
||||
|
||||
if (component is IStatefulAssistantComponent stateful)
|
||||
details.Add(string.IsNullOrWhiteSpace(stateful.UserPrompt) ? TB("Prompt: empty") : TB("Prompt: set"));
|
||||
|
||||
if (component.Children.Count > 0)
|
||||
details.Add(string.Format(TB("Children: {0}"), component.Children.Count));
|
||||
|
||||
return string.Join(" | ", details);
|
||||
}
|
||||
|
||||
private static bool IsScalarValue(object value)
|
||||
{
|
||||
return value is string or bool or char or Enum
|
||||
or byte or sbyte or short or ushort or int or uint or long or ulong
|
||||
or float or double or decimal
|
||||
or DateTime or DateTimeOffset or TimeSpan or Guid;
|
||||
}
|
||||
|
||||
private string FormatScalarValue(object? value) => value switch
|
||||
{
|
||||
null => TB("null"),
|
||||
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,
|
||||
};
|
||||
|
||||
private string GetStructuredValueCaption(object? value) => value switch
|
||||
{
|
||||
null => TB("null"),
|
||||
IDictionary dictionary => string.Format(TB("Entries: {0}"), dictionary.Count),
|
||||
IEnumerable enumerable when value is not string => string.Format(TB("Items: {0}"),
|
||||
enumerable.Cast<object?>().Count()),
|
||||
_ => value.GetType().Name,
|
||||
};
|
||||
|
||||
private string GetValueIcon(object? value) => value switch
|
||||
{
|
||||
null => Icons.Material.Filled.Block,
|
||||
bool => Icons.Material.Outlined.ToggleOn,
|
||||
string => Icons.Material.Outlined.Abc,
|
||||
int => Icons.Material.Filled.Numbers,
|
||||
Enum => Icons.Material.Filled.Label,
|
||||
IDictionary => Icons.Material.Filled.DataObject,
|
||||
IEnumerable when value is not string => Icons.Material.Filled.FormatListBulleted,
|
||||
_ => Icons.Material.Filled.DataArray,
|
||||
};
|
||||
|
||||
private string FormatFileTimestamp(DateTime timestamp) => timestamp.ToString("g", this.fileInfoCulture);
|
||||
|
||||
private string FormatFileSize(long bytes)
|
||||
{
|
||||
if (bytes < BYTES_PER_KILOBYTE)
|
||||
return string.Format(this.fileInfoCulture, 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);
|
||||
|
||||
var megabyte = kilobyte / BYTES_PER_KILOBYTE;
|
||||
if (megabyte < BYTES_PER_KILOBYTE)
|
||||
return string.Format(this.fileInfoCulture, TB("{0:0.##} MB"), megabyte);
|
||||
|
||||
var gigabyte = megabyte / BYTES_PER_KILOBYTE;
|
||||
return string.Format(this.fileInfoCulture, 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using AIStudio.Components;
|
||||
using AIStudio.Agents.AssistantAudit;
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.PluginSystem.Assistants;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
|
||||
@ -14,6 +15,8 @@ public partial class Plugins : MSGComponentBase
|
||||
private const string GROUP_ENABLED = "Enabled";
|
||||
private const string GROUP_DISABLED = "Disabled";
|
||||
private const string GROUP_INTERNAL = "Internal";
|
||||
|
||||
private DataAssistantPluginAudit AssistantPluginAuditSettings => this.SettingsManager.ConfigurationData.AssistantPluginAudit;
|
||||
|
||||
private TableGroupDefinition<IPluginMetadata> groupConfig = null!;
|
||||
|
||||
@ -56,7 +59,7 @@ public partial class Plugins : MSGComponentBase
|
||||
return;
|
||||
}
|
||||
|
||||
if (pluginMeta.Type is not PluginType.ASSISTANT || !this.SettingsManager.ConfigurationData.AssistantPluginAudit.RequireAuditBeforeActivation)
|
||||
if (pluginMeta.Type is not PluginType.ASSISTANT || !this.AssistantPluginAuditSettings.RequireAuditBeforeActivation)
|
||||
{
|
||||
this.SettingsManager.ConfigurationData.EnabledPlugins.Add(pluginMeta.Id);
|
||||
await this.SettingsManager.StoreSettings();
|
||||
@ -72,12 +75,18 @@ public partial class Plugins : MSGComponentBase
|
||||
var cachedAudit = this.SettingsManager.ConfigurationData.AssistantPluginAudits.FirstOrDefault(x => x.PluginId == pluginMeta.Id);
|
||||
if (cachedAudit is not null && cachedAudit.PluginHash == pluginHash)
|
||||
{
|
||||
if (cachedAudit.Level < this.SettingsManager.ConfigurationData.AssistantPluginAudit.MinimumLevel && this.SettingsManager.ConfigurationData.AssistantPluginAudit.BlockActivationBelowMinimum)
|
||||
if (cachedAudit.Level < this.AssistantPluginAuditSettings.MinimumLevel && this.AssistantPluginAuditSettings.BlockActivationBelowMinimum)
|
||||
{
|
||||
await this.DialogService.ShowMessageBox(this.T("Assistant Audit"), $"{cachedAudit.Level.GetName()}: {cachedAudit.Summary}", this.T("Close"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cachedAudit.Level < this.AssistantPluginAuditSettings.MinimumLevel &&
|
||||
!await this.ConfirmActivationBelowMinimumAsync(pluginMeta.Name, cachedAudit.Level))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.SettingsManager.ConfigurationData.EnabledPlugins.Add(pluginMeta.Id);
|
||||
await this.SettingsManager.StoreSettings();
|
||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||
@ -102,6 +111,26 @@ public partial class Plugins : MSGComponentBase
|
||||
await this.SettingsManager.StoreSettings();
|
||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||
}
|
||||
|
||||
private async Task<bool> ConfirmActivationBelowMinimumAsync(string pluginName, AssistantAuditLevel actualLevel)
|
||||
{
|
||||
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||
{
|
||||
{
|
||||
x => x.Message,
|
||||
string.Format(
|
||||
this.T("The assistant plugin \"{0}\" was audited with the level \"{1}\", which is below the required minimum level \"{2}\". Your current settings allow activation anyway, but this may be potentially dangerous. Do you really want to enable this plugin?"),
|
||||
pluginName,
|
||||
actualLevel.GetName(),
|
||||
this.AssistantPluginAuditSettings.MinimumLevel.GetName())
|
||||
},
|
||||
};
|
||||
|
||||
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>(this.T("Potentially Dangerous Plugin"), dialogParameters,
|
||||
DialogOptions.FULLSCREEN);
|
||||
var dialogResult = await dialogReference.Result;
|
||||
return dialogResult is not null && !dialogResult.Canceled;
|
||||
}
|
||||
|
||||
private static bool IsSendingMail(string sourceUrl) => sourceUrl.TrimStart().StartsWith("mailto:", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
|
||||
@ -48,11 +48,11 @@ LANG_NAME = "Deutsch (Deutschland)"
|
||||
|
||||
UI_TEXT_CONTENT = {}
|
||||
|
||||
-- The Security Audit was unsuccessful, because the LLMs response was unusable. The Audit Level remains Unknown, so please try again later.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2113359519"] = "Das Sicherheits-Audit war nicht erfolgreich, da die Antwort des LLM unbrauchbar war. Das Audit Level bleibt 'Unbekannt'. Bitte versuchen Sie es später erneut."
|
||||
-- The security check could not be completed because the LLM's response was unusable. The audit level remains Unknown, so please try again later.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2451573087"] = "Die Sicherheitsprüfung konnte nicht abgeschlossen werden, da die Antwort des LLM unbrauchbar war. Die Audit-Stufe bleibt „Unbekannt“, bitte versuchen Sie es später erneut."
|
||||
|
||||
-- No provider is configured for Security Audit-Agent.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T4000913009"] = "Für den Security Audit-Agenten ist kein Provider konfiguriert."
|
||||
-- No provider is configured for the Security Audit Agent.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T3605554201"] = "Für den Sicherheitsprüfungs-Agenten ist kein Anbieter konfiguriert."
|
||||
|
||||
-- Needs Review
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITLEVELEXTENSIONS::T1114911302"] = "Audit Erforderlich"
|
||||
@ -2937,17 +2937,74 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T474393241"] = "Bitte wählen
|
||||
-- Delete Workspace
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T701874671"] = "Arbeitsbereich löschen"
|
||||
|
||||
-- Entries: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1098127509"] = "Einträge: {0}"
|
||||
|
||||
-- {0:0.##} GB
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1224874808"] = "{0:0.##} GB"
|
||||
|
||||
-- Potentially Dangerous Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1229643769"] = "Potenziell gefährliches Plugin"
|
||||
|
||||
-- Plugin root
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1303883002"] = "Stammverzeichnis des Plugins"
|
||||
|
||||
-- Last modified
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1310524248"] = "Zuletzt geändert"
|
||||
|
||||
-- Count: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T131135808"] = "Anzahl: {0}"
|
||||
|
||||
-- {0:0.##} MB
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1357418474"] = "{0:0.##} MB"
|
||||
|
||||
-- No security issues were found during this check.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1423034104"] = "Bei dieser Überprüfung wurden keine Sicherheitsprobleme gefunden."
|
||||
|
||||
-- No provider configured
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1476185409"] = "Kein Provider konfiguriert"
|
||||
|
||||
-- {0:0.##} KB
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T14914764"] = "{0:0.##} KB"
|
||||
|
||||
-- Prompt: empty
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1533307170"] = "Prompt: leer"
|
||||
|
||||
-- This plugin is below the required safety level. Your settings still allow activation, but enabling it requires an extra confirmation because it may be unsafe.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1539381299"] = "Dieses Plugin unterschreitet das erforderliche Sicherheitsniveau. Ihre Einstellungen erlauben die Aktivierung zwar weiterhin, aber das Einschalten erfordert eine zusätzliche Bestätigung, da es möglicherweise unsicher ist."
|
||||
|
||||
-- Components
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1550582665"] = "Komponenten"
|
||||
|
||||
-- Created
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T165548891"] = "Erstellt"
|
||||
|
||||
-- Lua Manifest
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T165738710"] = "Lua-Manifest"
|
||||
|
||||
-- Required minimum level
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1862086522"] = "Erforderliches Mindest-Audit-Level"
|
||||
-- Enable Assistant Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1676241565"] = "Assistant-Plugin aktivieren"
|
||||
|
||||
-- Unknown plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1834795216"] = "Unbekanntes Plugin"
|
||||
|
||||
-- This plugin cannot be activated because its audit result is below the required safety level and your settings block activation in this case.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1839656215"] = "Dieses Plugin kann nicht aktiviert werden, weil sein Prüfergebnis unter dem erforderlichen Sicherheitsniveau liegt und Ihre Einstellungen die Aktivierung in diesem Fall blockieren."
|
||||
|
||||
-- Children: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T193192210"] = "Untergeordnete: {0}"
|
||||
|
||||
-- null
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1996966820"] = "null"
|
||||
|
||||
-- Properties
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2177370620"] = "Eigenschaften"
|
||||
|
||||
-- Items: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2204150657"] = "Elemente: {0}"
|
||||
|
||||
-- {0} B
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2562655035"] = "{0} B"
|
||||
|
||||
-- The assistant plugin could not be resolved for auditing.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T273798258"] = "Das Assistenten-Plugin konnte für die Überprüfung nicht aufgelöst werden."
|
||||
@ -2955,17 +3012,50 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T273798258"] = "
|
||||
-- Audit provider
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2757790517"] = "Provider prüfen"
|
||||
|
||||
-- Enable Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3233590741"] = "Plugin aktivieren"
|
||||
-- Size
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2789707388"] = "Größe"
|
||||
|
||||
-- Prompt: set
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3156437951"] = "Prompt: festlegen"
|
||||
|
||||
-- Findings
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3224848879"] = "Ergebnisse"
|
||||
|
||||
-- {0} | Last modified {1}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3350447013"] = "{0} | Zuletzt geändert {1}"
|
||||
|
||||
-- The assistant plugin \"{0}\" was audited with the level \"{1}\", which is below the required safety level \"{2}\". Your current settings still allow activation, but this may be unsafe. Do you really want to enable this plugin?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3418077666"] = "Das Assistenten-Plugin „{0}“ wurde mit der Stufe „{1}“ geprüft, die unter der erforderlichen Sicherheitsstufe „{2}“ liegt. Ihre aktuellen Einstellungen erlauben die Aktivierung dennoch, aber dies kann unsicher sein. Möchten Sie dieses Plugin wirklich aktivieren?"
|
||||
|
||||
-- Unknown
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3424652889"] = "Unbekannt"
|
||||
|
||||
-- Close
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3448155331"] = "Schließen"
|
||||
|
||||
-- The audit uses a simulated prompt preview. Empty or placeholder values in the preview are expected during this security check.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T439841458"] = "Das Audit verwendet eine simulierte Prompt-Vorschau. Leere oder Platzhalterwerte in der Vorschau sind während dieser Sicherheitsprüfung zu erwarten."
|
||||
-- Value
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3511155050"] = "Wert"
|
||||
|
||||
-- Run Audit
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T564725977"] = "Prüfung ausführen"
|
||||
-- Last accessed
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3579946376"] = "Zuletzt aufgerufen"
|
||||
|
||||
-- Unknown key
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3647690370"] = "Unbekannter Schlüssel"
|
||||
|
||||
-- Minimum required safety level
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3652671056"] = "Mindest erforderliches Sicherheitsniveau"
|
||||
|
||||
-- Unavailable
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3662391977"] = "Nicht verfügbar"
|
||||
|
||||
-- Plugin Structure
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T371537943"] = "Plugin-Struktur"
|
||||
|
||||
-- Audit Result
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3844960449"] = "Prüfungsergebnis"
|
||||
|
||||
-- empty
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T413646574"] = "leer"
|
||||
|
||||
-- Prompt Preview
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T576347259"] = "Prompt-Vorschau"
|
||||
@ -2973,6 +3063,15 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T576347259"] = "
|
||||
-- System Prompt
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T628396066"] = "System-Prompt"
|
||||
|
||||
-- This security check uses a sample prompt preview. Empty or placeholder values in the preview are expected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T737998363"] = "Diese Sicherheitsprüfung verwendet eine Beispielvorschau des Prompts. Leere oder Platzhalterwerte in der Vorschau sind zu erwarten."
|
||||
|
||||
-- Safe
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T760494712"] = "Sicher"
|
||||
|
||||
-- Start Security Check
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T811648299"] = "Sicherheitsprüfung starten"
|
||||
|
||||
-- Cancel
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T900713019"] = "Abbrechen"
|
||||
|
||||
@ -5775,6 +5874,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T870640199"] = "Für einige Daten
|
||||
-- Install Pandoc
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T986578435"] = "Pandoc installieren"
|
||||
|
||||
-- Potentially Dangerous Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1229643769"] = "Potenziell gefährliches Plugin"
|
||||
|
||||
-- Disable plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1430375822"] = "Plugin deaktivieren"
|
||||
|
||||
@ -5796,6 +5898,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2057806005"] = "Plugin aktivieren"
|
||||
-- Plugins
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2222816203"] = "Plugins"
|
||||
|
||||
-- The assistant plugin \"{0}\" was audited with the level \"{1}\", which is below the required minimum level \"{2}\". Your current settings allow activation anyway, but this may be potentially dangerous. Do you really want to enable this plugin?
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2531356312"] = "Das Assistenten-Plugin „{0}“ wurde mit der Stufe „{1}“ geprüft, die unter der erforderlichen Mindeststufe „{2}“ liegt. Ihre aktuellen Einstellungen erlauben die Aktivierung trotzdem, aber das kann potenziell gefährlich sein. Möchten Sie dieses Plugin wirklich aktivieren?"
|
||||
|
||||
-- Enabled Plugins
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2738444034"] = "Aktivierte Plugins"
|
||||
|
||||
@ -6531,6 +6636,81 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T3290596792"] = "Fehler beim Exp
|
||||
-- Microsoft Word export successful
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T4256043333"] = "Export nach Microsoft Word erfolgreich"
|
||||
|
||||
-- Stack
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T135058847"] = "Stapel"
|
||||
|
||||
-- Button group
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1392576058"] = "Schaltflächengruppe"
|
||||
|
||||
-- Profiles Selection
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1437749589"] = "Profilauswahl"
|
||||
|
||||
-- Image
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1494001562"] = "Bild"
|
||||
|
||||
-- Text Area
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1593629311"] = "Textfeld"
|
||||
|
||||
-- File Content
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T165091006"] = "Dateiinhalt"
|
||||
|
||||
-- Grid Item
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1991378436"] = "Rasterelement"
|
||||
|
||||
-- List
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T2368288673"] = "Liste"
|
||||
|
||||
-- Provider Selection
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T268262394"] = "Anbieterauswahl"
|
||||
|
||||
-- Root
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T2703841893"] = "Wurzel"
|
||||
|
||||
-- Container
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T2990360344"] = "Container"
|
||||
|
||||
-- Accordion
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3372988345"] = "Akkordeon"
|
||||
|
||||
-- Date Range
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3400615792"] = "Datumsbereich"
|
||||
|
||||
-- Plane Text
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3557717784"] = "Unformatierter Text"
|
||||
|
||||
-- Switch
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3656636817"] = "Umschalten"
|
||||
|
||||
-- Time
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3756319748"] = "Zeit"
|
||||
|
||||
-- Dropdown
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3829804792"] = "Dropdown"
|
||||
|
||||
-- Color
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3853794552"] = "Farbe"
|
||||
|
||||
-- Accordion Section
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T4180733902"] = "Akkordeon-Abschnitt"
|
||||
|
||||
-- Heading
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T4231005109"] = "Überschrift"
|
||||
|
||||
-- Unknown Element
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T434854509"] = "Unbekanntes Element"
|
||||
|
||||
-- Web Content
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T590188228"] = "Web-Inhalte"
|
||||
|
||||
-- Grid
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T800286385"] = "Raster"
|
||||
|
||||
-- Button
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T864557713"] = "Schaltfläche"
|
||||
|
||||
-- Date
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T995259257"] = "Datum"
|
||||
|
||||
-- Failed to parse the UI render tree from the ASSISTANT lua table.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T1318499252"] = "Der UI-Render-Baum konnte nicht aus der ASSISTANT-Lua-Tabelle geparst werden."
|
||||
|
||||
|
||||
@ -48,11 +48,11 @@ LANG_NAME = "English (United States)"
|
||||
|
||||
UI_TEXT_CONTENT = {}
|
||||
|
||||
-- The Security Audit was unsuccessful, because the LLMs response was unusable. The Audit Level remains Unknown, so please try again later.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2113359519"] = "The Security Audit was unsuccessful, because the LLMs response was unusable. The Audit Level remains Unknown, so please try again later."
|
||||
-- The security check could not be completed because the LLM's response was unusable. The audit level remains Unknown, so please try again later.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T2451573087"] = "The security check could not be completed because the LLM's response was unusable. The audit level remains Unknown, so please try again later."
|
||||
|
||||
-- No provider is configured for Security Audit-Agent.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T4000913009"] = "No provider is configured for Security Audit-Agent."
|
||||
-- No provider is configured for the Security Audit Agent.
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITAGENT::T3605554201"] = "No provider is configured for the Security Audit Agent."
|
||||
|
||||
-- Needs Review
|
||||
UI_TEXT_CONTENT["AISTUDIO::AGENTS::ASSISTANTAUDIT::ASSISTANTAUDITLEVELEXTENSIONS::T1114911302"] = "Needs Review"
|
||||
@ -2937,17 +2937,74 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T474393241"] = "Please select
|
||||
-- Delete Workspace
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::WORKSPACES::T701874671"] = "Delete Workspace"
|
||||
|
||||
-- Entries: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1098127509"] = "Entries: {0}"
|
||||
|
||||
-- {0:0.##} GB
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1224874808"] = "{0:0.##} GB"
|
||||
|
||||
-- Potentially Dangerous Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1229643769"] = "Potentially Dangerous Plugin"
|
||||
|
||||
-- Plugin root
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1303883002"] = "Plugin root"
|
||||
|
||||
-- Last modified
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1310524248"] = "Last modified"
|
||||
|
||||
-- Count: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T131135808"] = "Count: {0}"
|
||||
|
||||
-- {0:0.##} MB
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1357418474"] = "{0:0.##} MB"
|
||||
|
||||
-- No security issues were found during this check.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1423034104"] = "No security issues were found during this check."
|
||||
|
||||
-- No provider configured
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1476185409"] = "No provider configured"
|
||||
|
||||
-- {0:0.##} KB
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T14914764"] = "{0:0.##} KB"
|
||||
|
||||
-- Prompt: empty
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1533307170"] = "Prompt: empty"
|
||||
|
||||
-- This plugin is below the required safety level. Your settings still allow activation, but enabling it requires an extra confirmation because it may be unsafe.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1539381299"] = "This plugin is below the required safety level. Your settings still allow activation, but enabling it requires an extra confirmation because it may be unsafe."
|
||||
|
||||
-- Components
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1550582665"] = "Components"
|
||||
|
||||
-- Created
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T165548891"] = "Created"
|
||||
|
||||
-- Lua Manifest
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T165738710"] = "Lua Manifest"
|
||||
|
||||
-- Required minimum level
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1862086522"] = "Required minimum level"
|
||||
-- Enable Assistant Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1676241565"] = "Enable Assistant Plugin"
|
||||
|
||||
-- Unknown plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1834795216"] = "Unknown plugin"
|
||||
|
||||
-- This plugin cannot be activated because its audit result is below the required safety level and your settings block activation in this case.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1839656215"] = "This plugin cannot be activated because its audit result is below the required safety level and your settings block activation in this case."
|
||||
|
||||
-- Children: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T193192210"] = "Children: {0}"
|
||||
|
||||
-- null
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T1996966820"] = "null"
|
||||
|
||||
-- Properties
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2177370620"] = "Properties"
|
||||
|
||||
-- Items: {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2204150657"] = "Items: {0}"
|
||||
|
||||
-- {0} B
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2562655035"] = "{0} B"
|
||||
|
||||
-- The assistant plugin could not be resolved for auditing.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T273798258"] = "The assistant plugin could not be resolved for auditing."
|
||||
@ -2955,17 +3012,50 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T273798258"] = "
|
||||
-- Audit provider
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2757790517"] = "Audit provider"
|
||||
|
||||
-- Enable Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3233590741"] = "Enable Plugin"
|
||||
-- Size
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T2789707388"] = "Size"
|
||||
|
||||
-- Prompt: set
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3156437951"] = "Prompt: set"
|
||||
|
||||
-- Findings
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3224848879"] = "Findings"
|
||||
|
||||
-- {0} | Last modified {1}
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3350447013"] = "{0} | Last modified {1}"
|
||||
|
||||
-- The assistant plugin \"{0}\" was audited with the level \"{1}\", which is below the required safety level \"{2}\". Your current settings still allow activation, but this may be unsafe. Do you really want to enable this plugin?
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3418077666"] = "The assistant plugin \\\"{0}\\\" was audited with the level \\\"{1}\\\", which is below the required safety level \\\"{2}\\\". Your current settings still allow activation, but this may be unsafe. Do you really want to enable this plugin?"
|
||||
|
||||
-- Unknown
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3424652889"] = "Unknown"
|
||||
|
||||
-- Close
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3448155331"] = "Close"
|
||||
|
||||
-- The audit uses a simulated prompt preview. Empty or placeholder values in the preview are expected during this security check.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T439841458"] = "The audit uses a simulated prompt preview. Empty or placeholder values in the preview are expected during this security check."
|
||||
-- Value
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3511155050"] = "Value"
|
||||
|
||||
-- Run Audit
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T564725977"] = "Run Audit"
|
||||
-- Last accessed
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3579946376"] = "Last accessed"
|
||||
|
||||
-- Unknown key
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3647690370"] = "Unknown key"
|
||||
|
||||
-- Minimum required safety level
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3652671056"] = "Minimum required safety level"
|
||||
|
||||
-- Unavailable
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3662391977"] = "Unavailable"
|
||||
|
||||
-- Plugin Structure
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T371537943"] = "Plugin Structure"
|
||||
|
||||
-- Audit Result
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T3844960449"] = "Audit Result"
|
||||
|
||||
-- empty
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T413646574"] = "empty"
|
||||
|
||||
-- Prompt Preview
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T576347259"] = "Prompt Preview"
|
||||
@ -2973,6 +3063,15 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T576347259"] = "
|
||||
-- System Prompt
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T628396066"] = "System Prompt"
|
||||
|
||||
-- This security check uses a sample prompt preview. Empty or placeholder values in the preview are expected.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T737998363"] = "This security check uses a sample prompt preview. Empty or placeholder values in the preview are expected."
|
||||
|
||||
-- Safe
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T760494712"] = "Safe"
|
||||
|
||||
-- Start Security Check
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T811648299"] = "Start Security Check"
|
||||
|
||||
-- Cancel
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::ASSISTANTPLUGINAUDITDIALOG::T900713019"] = "Cancel"
|
||||
|
||||
@ -5775,6 +5874,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T870640199"] = "For some data tra
|
||||
-- Install Pandoc
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T986578435"] = "Install Pandoc"
|
||||
|
||||
-- Potentially Dangerous Plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1229643769"] = "Potentially Dangerous Plugin"
|
||||
|
||||
-- Disable plugin
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1430375822"] = "Disable plugin"
|
||||
|
||||
@ -5796,6 +5898,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2057806005"] = "Enable plugin"
|
||||
-- Plugins
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2222816203"] = "Plugins"
|
||||
|
||||
-- The assistant plugin \"{0}\" was audited with the level \"{1}\", which is below the required minimum level \"{2}\". Your current settings allow activation anyway, but this may be potentially dangerous. Do you really want to enable this plugin?
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2531356312"] = "The assistant plugin \\\"{0}\\\" was audited with the level \\\"{1}\\\", which is below the required minimum level \\\"{2}\\\". Your current settings allow activation anyway, but this may be potentially dangerous. Do you really want to enable this plugin?"
|
||||
|
||||
-- Enabled Plugins
|
||||
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T2738444034"] = "Enabled Plugins"
|
||||
|
||||
@ -6531,6 +6636,81 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T3290596792"] = "Error during Mi
|
||||
-- Microsoft Word export successful
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T4256043333"] = "Microsoft Word export successful"
|
||||
|
||||
-- Stack
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T135058847"] = "Stack"
|
||||
|
||||
-- Button group
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1392576058"] = "Button group"
|
||||
|
||||
-- Profiles Selection
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1437749589"] = "Profiles Selection"
|
||||
|
||||
-- Image
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1494001562"] = "Image"
|
||||
|
||||
-- Text Area
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1593629311"] = "Text Area"
|
||||
|
||||
-- File Content
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T165091006"] = "File Content"
|
||||
|
||||
-- Grid Item
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T1991378436"] = "Grid Item"
|
||||
|
||||
-- List
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T2368288673"] = "List"
|
||||
|
||||
-- Provider Selection
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T268262394"] = "Provider Selection"
|
||||
|
||||
-- Root
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T2703841893"] = "Root"
|
||||
|
||||
-- Container
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T2990360344"] = "Container"
|
||||
|
||||
-- Accordion
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3372988345"] = "Accordion"
|
||||
|
||||
-- Date Range
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3400615792"] = "Date Range"
|
||||
|
||||
-- Plane Text
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3557717784"] = "Plane Text"
|
||||
|
||||
-- Switch
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3656636817"] = "Switch"
|
||||
|
||||
-- Time
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3756319748"] = "Time"
|
||||
|
||||
-- Dropdown
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3829804792"] = "Dropdown"
|
||||
|
||||
-- Color
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T3853794552"] = "Color"
|
||||
|
||||
-- Accordion Section
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T4180733902"] = "Accordion Section"
|
||||
|
||||
-- Heading
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T4231005109"] = "Heading"
|
||||
|
||||
-- Unknown Element
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T434854509"] = "Unknown Element"
|
||||
|
||||
-- Web Content
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T590188228"] = "Web Content"
|
||||
|
||||
-- Grid
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T800286385"] = "Grid"
|
||||
|
||||
-- Button
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T864557713"] = "Button"
|
||||
|
||||
-- Date
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::DATAMODEL::ASSISTANTCOMPONENTTYPE::T995259257"] = "Date"
|
||||
|
||||
-- Failed to parse the UI render tree from the ASSISTANT lua table.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::PLUGINSYSTEM::ASSISTANTS::PLUGINASSISTANTS::T1318499252"] = "Failed to parse the UI render tree from the ASSISTANT lua table."
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
namespace AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||
|
||||
public enum AssistantComponentType
|
||||
{
|
||||
@ -27,3 +29,66 @@ public enum AssistantComponentType
|
||||
LAYOUT_ACCORDION,
|
||||
LAYOUT_ACCORDION_SECTION,
|
||||
}
|
||||
|
||||
public static class AssistantComponentTypeExtensions
|
||||
{
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(AssistantComponentTypeExtensions).Namespace, nameof(AssistantComponentTypeExtensions));
|
||||
|
||||
public static string GetDisplayName(this AssistantComponentType type) => type switch
|
||||
{
|
||||
AssistantComponentType.FORM => TB("Root"),
|
||||
AssistantComponentType.TEXT_AREA => TB("Text Area"),
|
||||
AssistantComponentType.BUTTON => TB("Button"),
|
||||
AssistantComponentType.BUTTON_GROUP => TB("Button group"),
|
||||
AssistantComponentType.DROPDOWN => TB("Dropdown"),
|
||||
AssistantComponentType.PROVIDER_SELECTION => TB("Provider Selection"),
|
||||
AssistantComponentType.PROFILE_SELECTION => TB("Profiles Selection"),
|
||||
AssistantComponentType.SWITCH => TB("Switch"),
|
||||
AssistantComponentType.HEADING => TB("Heading"),
|
||||
AssistantComponentType.TEXT => TB("Plane Text"),
|
||||
AssistantComponentType.LIST => TB("List"),
|
||||
AssistantComponentType.WEB_CONTENT_READER => TB("Web Content"),
|
||||
AssistantComponentType.FILE_CONTENT_READER => TB("File Content"),
|
||||
AssistantComponentType.IMAGE => TB("Image"),
|
||||
AssistantComponentType.COLOR_PICKER => TB("Color"),
|
||||
AssistantComponentType.DATE_PICKER => TB("Date"),
|
||||
AssistantComponentType.DATE_RANGE_PICKER => TB("Date Range"),
|
||||
AssistantComponentType.TIME_PICKER => TB("Time"),
|
||||
AssistantComponentType.LAYOUT_ITEM => TB("Grid Item"),
|
||||
AssistantComponentType.LAYOUT_GRID => TB("Grid"),
|
||||
AssistantComponentType.LAYOUT_PAPER => TB("Container"),
|
||||
AssistantComponentType.LAYOUT_STACK => TB("Stack"),
|
||||
AssistantComponentType.LAYOUT_ACCORDION => TB("Accordion"),
|
||||
AssistantComponentType.LAYOUT_ACCORDION_SECTION => TB("Accordion Section"),
|
||||
_ => TB("Unknown Element")
|
||||
};
|
||||
|
||||
public static string GetIcon(this AssistantComponentType type) => type switch
|
||||
{
|
||||
AssistantComponentType.BUTTON => MudBlazor.Icons.Material.Filled.AdsClick,
|
||||
AssistantComponentType.BUTTON_GROUP => MudBlazor.Icons.Material.Filled.LinearScale,
|
||||
AssistantComponentType.DROPDOWN => MudBlazor.Icons.Material.Filled.Rule,
|
||||
AssistantComponentType.PROVIDER_SELECTION => MudBlazor.Icons.Material.Filled.Memory,
|
||||
AssistantComponentType.PROFILE_SELECTION => MudBlazor.Icons.Material.Filled.Badge,
|
||||
AssistantComponentType.SWITCH => MudBlazor.Icons.Material.Filled.ToggleOn,
|
||||
AssistantComponentType.HEADING => MudBlazor.Icons.Material.Filled.Title,
|
||||
AssistantComponentType.TEXT => MudBlazor.Icons.Material.Filled.TextFields,
|
||||
AssistantComponentType.TEXT_AREA => MudBlazor.Icons.Material.Filled.Wysiwyg,
|
||||
AssistantComponentType.LIST => MudBlazor.Icons.Material.Filled.List,
|
||||
AssistantComponentType.WEB_CONTENT_READER => MudBlazor.Icons.Material.Filled.Public,
|
||||
AssistantComponentType.FILE_CONTENT_READER => MudBlazor.Icons.Material.Filled.AttachFile,
|
||||
AssistantComponentType.IMAGE => MudBlazor.Icons.Material.Filled.Image,
|
||||
AssistantComponentType.COLOR_PICKER => MudBlazor.Icons.Material.Filled.Palette,
|
||||
AssistantComponentType.DATE_PICKER => MudBlazor.Icons.Material.Filled.CalendarMonth,
|
||||
AssistantComponentType.DATE_RANGE_PICKER => MudBlazor.Icons.Material.Filled.DateRange,
|
||||
AssistantComponentType.TIME_PICKER => MudBlazor.Icons.Material.Filled.Schedule,
|
||||
AssistantComponentType.LAYOUT_ITEM => MudBlazor.Icons.Material.Filled.DashboardCustomize,
|
||||
AssistantComponentType.LAYOUT_GRID => MudBlazor.Icons.Material.Filled.GridView,
|
||||
AssistantComponentType.LAYOUT_PAPER => MudBlazor.Icons.Material.Filled.Inbox,
|
||||
AssistantComponentType.LAYOUT_STACK => MudBlazor.Icons.Material.Filled.Layers,
|
||||
AssistantComponentType.LAYOUT_ACCORDION => MudBlazor.Icons.Material.Filled.CalendarViewDay,
|
||||
AssistantComponentType.LAYOUT_ACCORDION_SECTION => MudBlazor.Icons.Material.Filled.HorizontalSplit,
|
||||
AssistantComponentType.FORM => MudBlazor.Icons.Material.Filled.AccountTree,
|
||||
_ => MudBlazor.Icons.Material.Filled.AccountTree,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using System.Collections.Immutable;
|
||||
using AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||
using AIStudio.Tools.PluginSystem.Assistants.DataModel.Layout;
|
||||
using Lua;
|
||||
@ -29,6 +30,7 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
|
||||
public AssistantForm? RootComponent { get; private set; }
|
||||
public string AssistantTitle { get; private set; } = string.Empty;
|
||||
public string AssistantDescription { get; private set; } = string.Empty;
|
||||
public string RawSystemPrompt { get; private set; } = string.Empty;
|
||||
public string SystemPrompt { get; private set; } = string.Empty;
|
||||
public string SubmitText { get; private set; } = string.Empty;
|
||||
public bool AllowProfiles { get; private set; } = true;
|
||||
@ -112,9 +114,12 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
|
||||
message = TB("ASSISTANT.BuildPrompt exists but is not a Lua function or has invalid syntax.");
|
||||
}
|
||||
|
||||
var rawSystemPrompt = assistantSystemPrompt.Trim();
|
||||
|
||||
this.AssistantTitle = assistantTitle;
|
||||
this.AssistantDescription = assistantDescription;
|
||||
this.SystemPrompt = BuildSecureSystemPrompt(assistantSystemPrompt);
|
||||
this.RawSystemPrompt = rawSystemPrompt;
|
||||
this.SystemPrompt = BuildSecureSystemPrompt(rawSystemPrompt);
|
||||
this.SubmitText = assistantSubmitText;
|
||||
this.AllowProfiles = assistantAllowProfiles;
|
||||
|
||||
@ -189,19 +194,52 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
|
||||
return builder.ToString().TrimEnd();
|
||||
}
|
||||
|
||||
public string ReadManifestCode()
|
||||
public ImmutableDictionary<string, string> ReadAllLuaFiles()
|
||||
{
|
||||
var manifestPath = Path.Combine(this.PluginPath, "plugin.lua");
|
||||
return File.Exists(manifestPath) ? File.ReadAllText(manifestPath) : string.Empty;
|
||||
if (!Directory.Exists(this.PluginPath))
|
||||
return ImmutableDictionary.Create<string, string>();
|
||||
|
||||
var fileMap = ImmutableDictionary.CreateBuilder<string, string>(StringComparer.Ordinal);
|
||||
|
||||
foreach (var filePath in Directory.EnumerateFiles(this.PluginPath, "*.lua", SearchOption.AllDirectories).OrderBy(path => path, StringComparer.Ordinal))
|
||||
{
|
||||
var relativePath = Path.GetRelativePath(this.PluginPath, filePath);
|
||||
fileMap[relativePath] = File.ReadAllText(filePath);
|
||||
}
|
||||
|
||||
return fileMap.ToImmutable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes a stable audit hash across all Lua files by hashing a canonical
|
||||
/// sequence of relative path length, relative path, content length, and content
|
||||
/// for each file in ordinal path order.
|
||||
/// </summary>
|
||||
public string ComputeAuditHash()
|
||||
{
|
||||
var manifestCode = this.ReadManifestCode();
|
||||
if (string.IsNullOrWhiteSpace(manifestCode))
|
||||
var luaFiles = this.ReadAllLuaFiles();
|
||||
|
||||
if (luaFiles.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(manifestCode));
|
||||
using var stream = new MemoryStream();
|
||||
using var writer = new BinaryWriter(stream, Encoding.UTF8, leaveOpen: true);
|
||||
|
||||
foreach (var (relativePath, content) in luaFiles.OrderBy(pair => pair.Key, StringComparer.Ordinal))
|
||||
{
|
||||
var normalizedPath = relativePath.Replace('\\', '/');
|
||||
var pathBytes = Encoding.UTF8.GetBytes(normalizedPath);
|
||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||
|
||||
writer.Write(pathBytes.Length);
|
||||
writer.Write(pathBytes);
|
||||
writer.Write(contentBytes.Length);
|
||||
writer.Write(contentBytes);
|
||||
}
|
||||
|
||||
writer.Flush();
|
||||
|
||||
var bytes = SHA256.HashData(stream.ToArray());
|
||||
return Convert.ToHexString(bytes);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user