2025-04-24 13:50:14 +02:00
using AIStudio.Components ;
2026-04-09 10:01:24 +02:00
using AIStudio.Agents.AssistantAudit ;
using AIStudio.Tools.PluginSystem ;
using AIStudio.Tools.PluginSystem.Assistants ;
2026-08-27 16:19:35 +02:00
using AIStudio.Tools.Services ;
2026-04-09 10:01:24 +02:00
using Microsoft.AspNetCore.Components ;
2024-08-21 08:30:01 +02:00
namespace AIStudio.Pages ;
2026-04-09 10:01:24 +02:00
public partial class Assistants : MSGComponentBase
{
private bool isAutoAuditing ;
[Inject]
private AssistantPluginAuditService AssistantPluginAuditService { get ; init ; } = null !;
2026-07-05 15:20:29 +02:00
[Inject]
private NavigationManager NavigationManager { get ; init ; } = null !;
[Inject]
2026-08-27 16:19:35 +02:00
private DirectChatService DirectChatService { get ; init ; } = null !;
2026-04-09 10:01:24 +02:00
protected override async Task OnInitializedAsync ()
{
this . ApplyFilters ([], [ Event . CONFIGURATION_CHANGED , Event . PLUGINS_RELOADED ]);
await base . OnInitializedAsync ();
}
protected override async Task OnAfterRenderAsync ( bool firstRender )
{
if ( firstRender )
await this . TryAutoAuditAssistantsAsync ();
}
private IReadOnlyCollection < PluginAssistants > AssistantPlugins =>
PluginFactory . RunningPlugins . OfType < PluginAssistants >()
. Where ( plugin => this . SettingsManager . IsPluginEnabled ( plugin ))
. ToList ();
private async Task TryAutoAuditAssistantsAsync ()
{
if ( this . isAutoAuditing || ! this . SettingsManager . ConfigurationData . AssistantPluginAudit . AutomaticallyAuditAssistants )
return ;
this . isAutoAuditing = true ;
try
{
var wasConfigurationChanged = false ;
var assistantPlugins = PluginFactory . RunningPlugins . OfType < PluginAssistants >(). ToList ();
foreach ( var assistantPlugin in assistantPlugins )
{
var securityState = PluginAssistantSecurityResolver . Resolve ( this . SettingsManager , assistantPlugin );
if (! securityState . RequiresAudit )
continue ;
var audit = await this . AssistantPluginAuditService . RunAuditAsync ( assistantPlugin );
if ( audit . Level is AssistantAuditLevel . UNKNOWN )
{
await MessageBus . INSTANCE . SendError ( new ( Icons . Material . Filled . SettingsSuggest , string . Format ( this . T ( "The automatic security audit for the assistant plugin '{0}' failed. Please run it manually from the plugins page." ), assistantPlugin . Name )));
continue ;
}
this . UpsertAuditCard ( audit );
wasConfigurationChanged = true ;
}
if (! wasConfigurationChanged )
return ;
await this . SettingsManager . StoreSettings ();
await this . MessageBus . SendMessage < bool >( this , Event . CONFIGURATION_CHANGED );
}
finally
{
this . isAutoAuditing = false ;
await this . InvokeAsync ( this . StateHasChanged );
}
}
private void UpsertAuditCard ( PluginAssistantAudit audit )
{
var audits = this . SettingsManager . ConfigurationData . AssistantPluginAudits ;
var existingIndex = audits . FindIndex ( x => x . PluginId == audit . PluginId );
if ( existingIndex >= 0 )
audits [ existingIndex ] = audit ;
else
audits . Add ( audit );
}
2026-07-05 15:20:29 +02:00
private async Task StartAssistantPluginAsync ( PluginAssistants assistantPlugin )
{
var securityState = PluginAssistantSecurityResolver . Resolve ( this . SettingsManager , assistantPlugin );
if (! securityState . CanStartAssistant )
return ;
if (! assistantPlugin . StartsChatDirectly )
{
this . NavigationManager . NavigateTo ( $"{Routes.ASSISTANT_DYNAMIC}?assistantId={assistantPlugin.Id}" );
return ;
}
2026-08-27 16:19:35 +02:00
var result = await this . DirectChatService . TryCreateAssistantChatAsync ( assistantPlugin );
if ( result . Request is null )
2026-07-05 15:20:29 +02:00
{
2026-08-27 16:19:35 +02:00
await this . MessageBus . SendError ( new ( Icons . Material . Filled . ReportProblem , result . ErrorMessage ));
return ;
2026-07-05 15:20:29 +02:00
}
2026-08-27 16:19:35 +02:00
MessageBus . INSTANCE . DeferMessage ( this , Event . SEND_TO_CHAT , result . Request );
this . NavigationManager . NavigateTo ( Routes . CHAT );
2026-07-05 15:20:29 +02:00
}
2026-04-09 10:01:24 +02:00
protected override async Task ProcessIncomingMessage < T >( ComponentBase ? sendingComponent , Event triggeredEvent , T ? data ) where T : default
{
if ( triggeredEvent is Event . PLUGINS_RELOADED )
await this . TryAutoAuditAssistantsAsync ();
if ( triggeredEvent is Event . CONFIGURATION_CHANGED or Event . PLUGINS_RELOADED )
await this . InvokeAsync ( this . StateHasChanged );
}
}