Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
125 commits
Select commit Hold shift + click to select a range
b9a9f2d
WIP: Working out a data model and an example lua file to turn it into…
nilskruthoff Jul 21, 2025
04c3060
WIP: changed to correct namespaces
nilskruthoff Jul 21, 2025
f5c475f
Added a component factory and refactored Dropdowns; reformat getters
nilskruthoff Jul 21, 2025
cef643c
WIP: Implementing a parser for the lua data structure
nilskruthoff Jul 22, 2025
aba61ff
Merge branch 'refs/heads/main' into 29-add-an-assistant-builder
nilskruthoff Sep 23, 2025
7b60c5f
changing the lua file to become a more generic usage example
nilskruthoff Sep 29, 2025
c12fa64
removing assistant from the PluginCategory enum
nilskruthoff Sep 29, 2025
b42ee50
included the assistant plugin to load during plugin initialization
nilskruthoff Sep 29, 2025
5a6c91f
included valid assistant plugins into the running plugins
nilskruthoff Sep 30, 2025
3d5831f
added a settings dialog for dynamic assistants
nilskruthoff Sep 30, 2025
aa31fa7
included the installed plugin assistants to the assistants page
nilskruthoff Sep 30, 2025
09b187d
started with the rendering of dynamic assistants
nilskruthoff Sep 30, 2025
488747b
included allowProfiles and system prompt properties to the lua parser
nilskruthoff Sep 30, 2025
d37c3f2
fixed dropdown parsing
nilskruthoff Sep 30, 2025
2afc8c6
added DynamicAssistantDropdown to accomodate lua structure; included …
nilskruthoff Nov 10, 2025
5a3e49d
increased functionality for text area by adding optional properties
nilskruthoff Nov 11, 2025
4fd21ad
fixed bug in dropdown that prevented values from changing; finished i…
nilskruthoff Nov 11, 2025
0775b03
added a switch component for boolean user inputs
nilskruthoff Nov 11, 2025
9374b56
updated example plugin.lua for dynamic assistants
nilskruthoff Nov 11, 2025
bc50b37
Added new descriptive heading and text components
nilskruthoff Feb 10, 2026
de1cf65
added a descriptive list component
nilskruthoff Feb 10, 2026
58c0348
added profile selection as a component for the assistant builder; min…
nilskruthoff Feb 23, 2026
6841a35
added a web content reader as a component for the assistant builder
nilskruthoff Feb 23, 2026
4f6bdec
added a file content reader as a component for the assistant builder
nilskruthoff Feb 23, 2026
4819b93
included a README to document the assistant builder to plugin authors
nilskruthoff Feb 23, 2026
93e0fb4
set up handling of asset files from the plugin directory
nilskruthoff Feb 24, 2026
49746a2
added images as a descriptive component for the assistant builder
nilskruthoff Feb 24, 2026
b4702b1
renamed AssistantComponentType.cs because of a typo
nilskruthoff Feb 24, 2026
12881e3
respect dynamic assistant plugins instead of hardcoding GUID
nilskruthoff Feb 24, 2026
003c97f
moved installed assistants into own section on assistant overview page
nilskruthoff Feb 24, 2026
9c07584
translation
nilskruthoff Feb 24, 2026
a58922d
improved and adapted the fallback
nilskruthoff Feb 24, 2026
c541d26
translation
nilskruthoff Feb 24, 2026
a5cbe87
Applied a filter to remove deactivated plugins from rendering
nilskruthoff Feb 24, 2026
024fb58
translated again because of updated keys
nilskruthoff Feb 24, 2026
6ad7aba
added class and style properties to every component
nilskruthoff Feb 24, 2026
9ae3fca
wrapped used internal components without Class and Style properties w…
nilskruthoff Feb 24, 2026
4eb0cc6
added advanced prompt building option by creating a new lua function …
nilskruthoff Mar 2, 2026
cbd74f4
translated new texts
nilskruthoff Mar 2, 2026
8c1ba3a
added helper functions like simple structured logging and date time u…
nilskruthoff Mar 2, 2026
4c92fe8
changed settings dialog to point to the empty dynamic settings dialog
nilskruthoff Mar 3, 2026
379940c
minor improvements (removed unused using directives; make private set…
nilskruthoff Mar 3, 2026
ee94d85
fixed inheritance flaws
nilskruthoff Mar 3, 2026
127b518
merge `main` into `29-add-an-assistant-builder`
nilskruthoff Mar 3, 2026
fc3b46a
documented included lua libs
nilskruthoff Mar 3, 2026
a5149e4
added a new color picker component to the lua parsing
nilskruthoff Mar 9, 2026
96d0b9e
make component dictionaries readonly
nilskruthoff Mar 9, 2026
867890a
generalized getters and setters for ints and bools
nilskruthoff Mar 9, 2026
9dba7f4
overhauled the textarea component to be as feature complete as possible
nilskruthoff Mar 9, 2026
b221d08
added a source generator that maps MudIcons to their svg strings.
nilskruthoff Mar 9, 2026
25eb0cf
overhauled switch component
nilskruthoff Mar 10, 2026
ec357d7
improved doc for switch
nilskruthoff Mar 10, 2026
a32a535
added class and style attrs to switch
nilskruthoff Mar 10, 2026
2ccb72c
buttons now support lua functions as actions, allowing plugin devs to…
nilskruthoff Mar 10, 2026
dbdcdef
Adding a ButtonGroup component to group button children together
nilskruthoff Mar 10, 2026
4f836e2
encapsulated render logic into a function to be able to call it recur…
nilskruthoff Mar 10, 2026
5106800
advanced layout: added MudItem, MudPaper, MudStack and MudGrid as new…
nilskruthoff Mar 10, 2026
edc717c
advanced layout: included the layout option in the rendering and docu…
nilskruthoff Mar 10, 2026
e68a839
improved documentation
nilskruthoff Mar 11, 2026
4a905cf
added a toc to the docs
nilskruthoff Mar 12, 2026
9aa028a
added a table of components as a quick reference
nilskruthoff Mar 12, 2026
a182cc4
improved dropdown component and fixed some bugs with it
nilskruthoff Mar 13, 2026
133be5b
WIP: Multiselection support
nilskruthoff Mar 13, 2026
41126be
fixed final bugs
nilskruthoff Mar 13, 2026
271279a
included a dropdown reference in the documentation
nilskruthoff Mar 13, 2026
5d8fee9
changed access to internal
nilskruthoff Mar 13, 2026
dea9c9e
added accordions as new layout components - resembles MudExpansionPanels
nilskruthoff Mar 13, 2026
d05dd35
removed uneccessary method
nilskruthoff Mar 14, 2026
0d57f18
Button now supports IconButton; Switch supports OnChange hook now
nilskruthoff Mar 16, 2026
5894147
minor fixes
nilskruthoff Mar 16, 2026
c4ec107
WIP: implementing time, date and date range pickers
nilskruthoff Mar 16, 2026
9440f13
added missing properties
nilskruthoff Mar 16, 2026
2117df5
fixed diverse little issues that occured while testing
nilskruthoff Mar 17, 2026
30d6b64
WIP: changing from parallel dictionaries to an encapsulated and centr…
nilskruthoff Mar 19, 2026
79c92bb
centralized conversion methods to reduce repetition
nilskruthoff Mar 21, 2026
82099a0
trim @ from icon strings
nilskruthoff Mar 21, 2026
d1ece55
renewed callback contract and made live value updates from all writea…
nilskruthoff Mar 21, 2026
5e683d0
moved helper functions into corrisponding data classes
nilskruthoff Mar 22, 2026
f9de20c
Merge branch 'refs/heads/main' into 29-add-an-assistant-builder
nilskruthoff Mar 23, 2026
4ef2df0
make ButtonGroup a named component
nilskruthoff Mar 23, 2026
37a6e66
changed textarea to use static helper for icon resolution
nilskruthoff Mar 23, 2026
ec67ac9
fixed text field bug where its rendered clutched
nilskruthoff Mar 23, 2026
7380250
WIP: added new data class for assistant security audits
nilskruthoff Mar 24, 2026
5053790
WIP: added managed settings for an audit agent
nilskruthoff Mar 24, 2026
aa94fe2
WIP: included settings panel to the settings page
nilskruthoff Mar 24, 2026
02e075d
WIP: included the new Assistant Audit Agent
nilskruthoff Mar 24, 2026
e11d45b
WIP: Register the agent in the DI container as transient
nilskruthoff Mar 24, 2026
2553953
WIP: Added a Audit Dialog to present results to the user
nilskruthoff Mar 24, 2026
b511ea5
WIP: Add dedicated settings integration for assistant plugin audit pr…
nilskruthoff Mar 24, 2026
69ae243
WIP: remove settings if the configuration plugin was removed
nilskruthoff Mar 24, 2026
ff63928
Add a warning to the dynamic assistant
nilskruthoff Mar 24, 2026
7021340
translation updated
nilskruthoff Mar 24, 2026
edfe6aa
fixed translation key
nilskruthoff Mar 24, 2026
dbe4ece
finished audit dialog
nilskruthoff Mar 26, 2026
63dd8da
moving display name of assistant component type to own class. Only th…
nilskruthoff Mar 26, 2026
c4f65a4
rebuild Userprompt into a more human readable and more structured blo…
nilskruthoff Mar 26, 2026
6933a19
included the BuildPrompt method into the Audit dialog
nilskruthoff Mar 27, 2026
d094f38
added skeletens to indicate running audit
nilskruthoff Mar 27, 2026
a59e10e
removed replaced and therefor unused methods
nilskruthoff Mar 27, 2026
22b8bdd
added common function to derive CultureInfo for formatting from the a…
nilskruthoff Mar 31, 2026
75407a8
added state and resolver logic for the plugin status state machine
nilskruthoff Mar 31, 2026
5f94428
security card component that shows all information of the current sav…
nilskruthoff Mar 31, 2026
f897ff3
fine tuned agents system prompt to be more consistent and scan for ja…
nilskruthoff Mar 31, 2026
b579129
useful xml docstrings
nilskruthoff Mar 31, 2026
09d13e6
integrating the security rules and badge to the assistant page and block
nilskruthoff Mar 31, 2026
3f2d763
integrating the security rules and badge to the plugin overview page
nilskruthoff Mar 31, 2026
92267b1
small ui fixes
nilskruthoff Mar 31, 2026
d2981a3
translation
nilskruthoff Mar 31, 2026
96c2e88
minor syntax styling fixes
nilskruthoff Apr 7, 2026
955a82e
making AssistantAuditResult.cs a record
nilskruthoff Apr 7, 2026
171e7c9
removed empty settings panel to use the built in no panel option
nilskruthoff Apr 7, 2026
3fe8300
adjusted the audit system prompt to include audit of available Lua ru…
nilskruthoff Apr 7, 2026
b6a1749
encapulated the audit logic into a service to reuse it
nilskruthoff Apr 7, 2026
67d3955
skip dialog and audit automatically if this is what the settings demand
nilskruthoff Apr 7, 2026
536d543
translation
nilskruthoff Apr 7, 2026
054481a
fixing bug leading to missing translation keys
nilskruthoff Apr 7, 2026
820c9e2
making the audit fully automatic
nilskruthoff Apr 7, 2026
7b0dd0e
Merge branch 'main' into 29-add-an-assistant-builder
nilskruthoff Apr 7, 2026
63f6bc0
making the security card findings scrollable and the technical detail…
nilskruthoff Apr 7, 2026
7714c12
Merge branch 'main' into 29-add-an-assistant-builder
SommerEngineering Apr 9, 2026
14c1be8
Updated naming rule
SommerEngineering Apr 9, 2026
ee6d241
Applied optimizations
SommerEngineering Apr 9, 2026
c284104
Updated
SommerEngineering Apr 9, 2026
a927fb7
Resolved warnings
SommerEngineering Apr 9, 2026
9f2bb8f
Updated changelog
SommerEngineering Apr 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/MindWork AI Studio.sln
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Build Script", "Build\Build
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedTools", "SharedTools\SharedTools.csproj", "{969C74DF-7678-4CD5-B269-D03E1ECA3D2A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGeneratedMappings", "SourceGeneratedMappings\SourceGeneratedMappings.csproj", "{4D7141D5-9C22-4D85-B748-290D15FF484C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -30,6 +32,10 @@ Global
{969C74DF-7678-4CD5-B269-D03E1ECA3D2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{969C74DF-7678-4CD5-B269-D03E1ECA3D2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{969C74DF-7678-4CD5-B269-D03E1ECA3D2A}.Release|Any CPU.Build.0 = Release|Any CPU
{4D7141D5-9C22-4D85-B748-290D15FF484C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4D7141D5-9C22-4D85-B748-290D15FF484C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4D7141D5-9C22-4D85-B748-290D15FF484C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4D7141D5-9C22-4D85-B748-290D15FF484C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
Expand Down
2 changes: 2 additions & 0 deletions app/MindWork AI Studio.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=URL/@EntryIndexedValue">URL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=I18N/@EntryIndexedValue">I18N</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=53eecf85_002Dd821_002D40e8_002Dac97_002Dfdb734542b84/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb_AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CustomTools/CustomToolsData/@EntryValue"></s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=agentic/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=eri/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=groq/@EntryIndexedValue">True</s:Boolean>
Expand Down
349 changes: 349 additions & 0 deletions app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Text.Json.Serialization;

namespace AIStudio.Agents.AssistantAudit;

/// <summary>
/// Represents a single structured security finding produced by the assistant audit agent.
/// </summary>
public sealed class AssistantAuditFinding
{
#pragma warning disable MWAIS0005
/// <summary>
/// Gets the normalized internal severity level derived from <see cref="SeverityText"/>.
/// </summary>
#pragma warning restore MWAIS0005
[JsonIgnore]
public AssistantAuditLevel Severity { get; private init; } = AssistantAuditLevel.UNKNOWN;


/// <summary>
/// Gets or initializes the JSON-facing severity label used by the audit model response.
/// </summary>
[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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace AIStudio.Agents.AssistantAudit;

/// <summary>
/// Defines the normalized outcome levels used for assistant plugin security audits.
/// </summary>
public enum AssistantAuditLevel
{
UNKNOWN = 0,
DANGEROUS = 100,
CAUTION = 200,
SAFE = 300,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using AIStudio.Tools.PluginSystem;

namespace AIStudio.Agents.AssistantAudit;

public static class AssistantAuditLevelExtensions
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(AssistantAuditLevelExtensions).Namespace, nameof(AssistantAuditLevelExtensions));

public static string GetName(this AssistantAuditLevel level) => level switch
{
AssistantAuditLevel.DANGEROUS => TB("Dangerous"),
AssistantAuditLevel.CAUTION => TB("Concerning"),
AssistantAuditLevel.SAFE => TB("Safe"),
_ => TB("Unknown"),
};

public static Severity GetSeverity(this AssistantAuditLevel level) => level switch
{
AssistantAuditLevel.DANGEROUS => Severity.Error,
AssistantAuditLevel.CAUTION => Severity.Warning,
AssistantAuditLevel.SAFE => Severity.Success,
_ => Severity.Info,
};

public static Color GetColor(this AssistantAuditLevel level) => level switch
{
AssistantAuditLevel.DANGEROUS => Color.Error,
AssistantAuditLevel.CAUTION => Color.Warning,
AssistantAuditLevel.SAFE => Color.Success,
_ => Color.Default,
};

public static string GetIcon(this AssistantAuditLevel level) => level switch
{
AssistantAuditLevel.DANGEROUS => Icons.Material.Filled.Dangerous,
AssistantAuditLevel.CAUTION => Icons.Material.Filled.Warning,
AssistantAuditLevel.SAFE => Icons.Material.Filled.Verified,
_ => Icons.Material.Filled.HelpOutline,
};

/// <summary>
/// Parses an audit level string and falls back to <see cref="AssistantAuditLevel.UNKNOWN"/> when parsing fails.
/// </summary>
/// <param name="value">The audit level text to parse.</param>
/// <returns>The parsed audit level, or <see cref="AssistantAuditLevel.UNKNOWN"/> for null, empty, or invalid values.</returns>
public static AssistantAuditLevel Parse(string? value) => Enum.TryParse<AssistantAuditLevel>(value, true, out var level) ? level : AssistantAuditLevel.UNKNOWN;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace AIStudio.Agents.AssistantAudit;

/// <summary>
/// Represents the normalized result returned by the assistant plugin security audit flow.
/// </summary>
public sealed record AssistantAuditResult
{
/// <summary>
/// Gets the serialized audit level returned by the model before callers normalize it to <see cref="AssistantAuditLevel"/>.
/// </summary>
public string Level { get; init; } = string.Empty;
public string Summary { get; init; } = string.Empty;
public float Confidence { get; init; }
public List<AssistantAuditFinding> Findings { get; init; } = [];
}
6 changes: 3 additions & 3 deletions app/MindWork AI Studio/Assistants/AssistantBase.razor
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,16 @@
<div id="@BEFORE_RESULT_DIV_ID" class="mt-3">
</div>

@if (this.ShowResult && !this.ShowEntireChatThread && this.resultingContentBlock is not null)
@if (this.ShowResult && !this.ShowEntireChatThread && this.resultingContentBlock is not null && this.resultingContentBlock.Content is not null)
{
<ContentBlockComponent Role="@(this.resultingContentBlock.Role)" Type="@(this.resultingContentBlock.ContentType)" Time="@(this.resultingContentBlock.Time)" Content="@(this.resultingContentBlock.Content)"/>
<ContentBlockComponent Role="@(this.resultingContentBlock.Role)" Type="@(this.resultingContentBlock.ContentType)" Time="@(this.resultingContentBlock.Time)" Content="@this.resultingContentBlock.Content"/>
}

@if(this.ShowResult && this.ShowEntireChatThread && this.chatThread is not null)
{
foreach (var block in this.chatThread.Blocks.OrderBy(n => n.Time))
{
@if (!block.HideFromUser)
@if (block is { HideFromUser: false, Content: not null })
{
<ContentBlockComponent Role="@block.Role" Type="@block.ContentType" Time="@block.Time" Content="@block.Content"/>
}
Expand Down
Loading