2025-03-16 13:03:43 +00:00
using AIStudio.Dialogs.Settings ;
2026-09-09 16:43:37 +00:00
using AIStudio.Provider ;
2025-02-15 14:41:12 +00:00
using AIStudio.Settings ;
using AIStudio.Settings.DataModel ;
using AIStudio.Tools.Services ;
2026-09-27 14:26:52 +00:00
using AIStudio.Tools.ToolCallingSystem ;
2025-02-15 14:41:12 +00:00
using Microsoft.AspNetCore.Components ;
2025-03-16 13:03:43 +00:00
using DialogOptions = AIStudio . Dialogs . DialogOptions ;
2025-02-15 14:41:12 +00:00
namespace AIStudio.Components ;
2025-04-27 14:13:15 +00:00
public partial class DataSourceSelection : MSGComponentBase
2025-02-15 14:41:12 +00:00
{
[Parameter]
public DataSourceSelectionMode SelectionMode { get ; set ; } = DataSourceSelectionMode . SELECTION_MODE ;
[Parameter]
public PopoverTriggerMode PopoverTriggerMode { get ; set ; } = PopoverTriggerMode . BUTTON ;
[Parameter]
public string PopoverButtonClasses { get ; set ; } = string . Empty ;
[Parameter]
public required AIStudio . Settings . Provider LLMProvider { get ; set ; }
[Parameter]
public required DataSourceOptions DataSourceOptions { get ; set ; }
[Parameter]
public EventCallback < DataSourceOptions > DataSourceOptionsChanged { get ; set ; }
2025-02-17 11:33:34 +00:00
[Parameter]
public IReadOnlyList < DataSourceAgentSelected > DataSourcesAISelected { get ; set ; } = [ ] ;
2025-02-15 14:41:12 +00:00
[Parameter]
public string ConfigurationHeaderMessage { get ; set ; } = string . Empty ;
[Parameter]
public bool AutoSaveAppSettings { get ; set ; }
2026-09-22 14:39:17 +00:00
/// <summary>
/// Shows the options without letting the user change them.
/// </summary>
/// <remarks>
/// For options somebody else decided on, such as those of a chat template an organization
/// rolled out. Seeing which data such a chat will search is the point; changing it here is not.
/// </remarks>
[Parameter]
public bool ReadOnly { get ; set ; }
/// <summary>
/// Whether the options edited here are the data source defaults of the chat.
/// </summary>
/// <remarks>
/// Those defaults can be locked by a configuration plugin, and this component reads the locks
/// from the chat settings. Wherever the same options belong to something else — to a chat
/// template, say — the locks of the chat defaults have nothing to say about them.
/// </remarks>
[Parameter]
public bool ConfiguresChatDefaults { get ; set ; } = true ;
2025-02-15 14:41:12 +00:00
[Inject]
private DataSourceService DataSourceService { get ; init ; } = null ! ;
2026-09-27 14:26:52 +00:00
[Inject]
private ToolRegistry ToolRegistry { get ; init ; } = null ! ;
2025-02-15 14:41:12 +00:00
[Inject]
2025-03-16 13:03:43 +00:00
private IDialogService DialogService { get ; init ; } = null ! ;
2025-02-15 14:41:12 +00:00
private bool internalChange ;
private bool showDataSourceSelection ;
private bool waitingForDataSources = true ;
private IReadOnlyList < IDataSource > availableDataSources = [ ] ;
2026-09-17 07:48:00 +00:00
private IReadOnlyList < IDataSource > dataSourcesAwaitingReindex = [ ] ;
private HashSet < string > dataSourceIdsAwaitingReindex = new ( StringComparer . Ordinal ) ;
2026-09-18 12:48:02 +00:00
private IReadOnlyList < IDataSource > dataSourcesNeedingRepair = [ ] ;
private HashSet < string > dataSourceIdsNeedingRepair = new ( StringComparer . Ordinal ) ;
2025-02-15 14:41:12 +00:00
private IReadOnlyCollection < IDataSource > selectedDataSources = [ ] ;
private bool aiBasedSourceSelection ;
private bool aiBasedValidation ;
private bool areDataSourcesEnabled ;
2026-09-27 14:26:52 +00:00
private DataSourceRetrievalMode retrievalMode ;
private EffectiveRetrievalMode effectiveRetrievalMode ;
2026-07-05 12:46:31 +00:00
private uint loadAndApplyFiltersGeneration ;
2025-02-15 14:41:12 +00:00
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync ( )
{
2025-04-27 14:13:15 +00:00
this . ApplyFilters ( [ ] , [ Event . RAG_AUTO_DATA_SOURCES_SELECTED ] ) ;
2025-02-15 14:41:12 +00:00
//
// Load the settings:
//
this . aiBasedSourceSelection = this . DataSourceOptions . AutomaticDataSourceSelection ;
this . aiBasedValidation = this . DataSourceOptions . AutomaticValidation ;
this . areDataSourcesEnabled = ! this . DataSourceOptions . DisableDataSources ;
2026-09-27 14:26:52 +00:00
this . retrievalMode = this . DataSourceOptions . RetrievalMode ;
2025-12-18 18:36:44 +00:00
this . waitingForDataSources = this . areDataSourcesEnabled & & this . SelectionMode is not DataSourceSelectionMode . CONFIGURATION_MODE ;
2025-02-15 14:41:12 +00:00
//
// Preselect the data sources. Right now, we cannot filter
// the data sources. Later, when the component is shown, we
// will filter the data sources.
//
// Right before the preselection would be used to kick off the
// RAG process, we will filter the data sources as well.
//
2026-07-05 12:46:31 +00:00
this . selectedDataSources = this . GetDataSourcesFromConfiguredIds ( ) ;
2025-02-15 14:41:12 +00:00
await base . OnInitializedAsync ( ) ;
}
protected override async Task OnParametersSetAsync ( )
{
if ( ! this . internalChange )
{
this . aiBasedSourceSelection = this . DataSourceOptions . AutomaticDataSourceSelection ;
this . aiBasedValidation = this . DataSourceOptions . AutomaticValidation ;
this . areDataSourcesEnabled = ! this . DataSourceOptions . DisableDataSources ;
2026-09-27 14:26:52 +00:00
this . retrievalMode = this . DataSourceOptions . RetrievalMode ;
2026-07-05 12:46:31 +00:00
this . selectedDataSources = this . GetDataSourcesFromConfiguredIds ( ) ;
2025-02-15 14:41:12 +00:00
}
switch ( this . SelectionMode )
{
//
// In selection mode, we have to load & filter the data sources
// when the component is shown:
//
case DataSourceSelectionMode . SELECTION_MODE :
//
// For external changes, we have to reload & filter
// the data sources:
//
if ( this . showDataSourceSelection & & ! this . internalChange )
await this . LoadAndApplyFilters ( ) ;
else
this . internalChange = false ;
break ;
//
// In configuration mode, we have to load all data sources:
//
case DataSourceSelectionMode . CONFIGURATION_MODE :
2026-07-05 12:46:31 +00:00
this . availableDataSources = this . GetConfiguredDataSourcesSnapshot ( ) ;
2025-02-15 14:41:12 +00:00
break ;
}
await base . OnParametersSetAsync ( ) ;
}
#endregion
2025-03-16 13:03:43 +00:00
private async Task OpenSettingsDialog ( )
{
this . showDataSourceSelection = false ;
this . StateHasChanged ( ) ;
var dialogParameters = new DialogParameters ( ) ;
var dialogReference = await this . DialogService . ShowAsync < SettingsDialogDataSources > ( null , dialogParameters , DialogOptions . FULLSCREEN ) ;
await dialogReference . Result ;
await this . LoadAndApplyFilters ( ) ;
this . showDataSourceSelection = true ;
this . StateHasChanged ( ) ;
}
2025-02-15 14:41:12 +00:00
2025-02-17 11:33:34 +00:00
private SelectionMode GetListSelectionMode ( ) = > this . aiBasedSourceSelection ? MudBlazor . SelectionMode . SingleSelection : MudBlazor . SelectionMode . MultiSelection ;
private IReadOnlyCollection < DataSourceAgentSelected > GetSelectedDataSourcesWithAI ( ) = > this . DataSourcesAISelected . Where ( n = > n . Selected ) . ToList ( ) ;
private string GetAIReasoning ( DataSourceAgentSelected source ) = > $"AI reasoning (confidence {source.AIDecision.Confidence:P0}): {source.AIDecision.Reason}" ;
2026-09-09 16:43:37 +00:00
private string GetConfidenceIconStyle ( IInternalDataSource source ) = > $"{source.ConfidenceLevel.SetColorStyle(this.SettingsManager)} flex-shrink: 0;" ;
2025-02-17 11:33:34 +00:00
public void ChangeOptionWithoutSaving ( DataSourceOptions options , IReadOnlyList < DataSourceAgentSelected > ? aiSelectedDataSources = null )
2025-02-15 14:41:12 +00:00
{
this . DataSourceOptions = options ;
2025-02-17 11:33:34 +00:00
this . DataSourcesAISelected = aiSelectedDataSources ? ? [ ] ;
2025-02-15 14:41:12 +00:00
this . aiBasedSourceSelection = this . DataSourceOptions . AutomaticDataSourceSelection ;
this . aiBasedValidation = this . DataSourceOptions . AutomaticValidation ;
this . areDataSourcesEnabled = ! this . DataSourceOptions . DisableDataSources ;
2026-09-27 14:26:52 +00:00
this . retrievalMode = this . DataSourceOptions . RetrievalMode ;
2026-07-05 12:46:31 +00:00
this . selectedDataSources = this . GetDataSourcesFromConfiguredIds ( ) ;
2025-02-15 14:41:12 +00:00
this . waitingForDataSources = false ;
//
// Remark: We do not apply the filters here. This is done later
// when either the parameters are changed or just before the
// RAG process is started (outside of this component).
//
// In fact, when we apply the filters here, multiple calls
// to the filter method would be made. We would get conflicts.
//
}
public bool IsVisible = > this . showDataSourceSelection ;
public void Hide ( )
{
this . showDataSourceSelection = false ;
this . StateHasChanged ( ) ;
}
2026-07-05 12:46:31 +00:00
private IReadOnlyList < IDataSource > GetConfiguredDataSourcesSnapshot ( ) = > this . SettingsManager . ConfigurationData . DataSources . ToList ( ) ;
private IReadOnlyCollection < IDataSource > GetDataSourcesFromConfiguredIds ( )
{
var preselectedDataSourceIds = this . DataSourceOptions . PreselectedDataSourceIds . ToHashSet ( StringComparer . Ordinal ) ;
return this . GetConfiguredDataSourcesSnapshot ( ) . Where ( ds = > preselectedDataSourceIds . Contains ( ds . Id ) ) . ToList ( ) ;
}
2026-09-14 14:30:17 +00:00
/// <summary>
/// Collects the preselected data sources which the filters removed.
/// </summary>
/// <remarks>
/// The list of available sources shows what survived the filters, while the preselection keeps
/// what the user asked for. Without this, a preselected source which cannot be used right now
/// is simply missing from that list, and nothing says so. Preselected ids without a configured
/// source are left out: that source is gone, not unavailable.
/// </remarks>
/// <returns>The unusable preselected data sources, or an empty list when there are none.</returns>
private IReadOnlyList < IDataSource > GetUnavailablePreselectedDataSources ( )
{
var availableDataSourceIds = this . availableDataSources . Select ( ds = > ds . Id ) . ToHashSet ( StringComparer . Ordinal ) ;
return this . GetDataSourcesFromConfiguredIds ( ) . Where ( ds = > ! availableDataSourceIds . Contains ( ds . Id ) ) . ToList ( ) ;
}
2025-02-15 14:41:12 +00:00
private async Task LoadAndApplyFilters ( )
{
if ( this . DataSourceOptions . DisableDataSources )
2026-07-05 12:46:31 +00:00
{
this . loadAndApplyFiltersGeneration + + ;
2025-02-15 14:41:12 +00:00
return ;
2026-07-05 12:46:31 +00:00
}
2025-12-18 18:36:44 +00:00
if ( this . SelectionMode is DataSourceSelectionMode . CONFIGURATION_MODE )
2026-07-05 12:46:31 +00:00
{
this . loadAndApplyFiltersGeneration + + ;
2025-12-18 18:36:44 +00:00
return ;
2026-07-05 12:46:31 +00:00
}
2025-12-18 18:36:44 +00:00
2026-07-05 12:46:31 +00:00
var generation = + + this . loadAndApplyFiltersGeneration ;
2025-02-15 14:41:12 +00:00
this . waitingForDataSources = true ;
this . StateHasChanged ( ) ;
2026-09-14 14:30:17 +00:00
//
// Load the data sources. We ask with the preselection rather than with the field below:
// that field holds what was usable the last time we looked, so a source filtered out once
// would never come back, while the RAG process keeps reading it from the preselection.
//
2026-09-27 14:26:52 +00:00
// How the chat searches decides whether the agents of the RAG process see the data, and
// with that which data sources the provider of the chat may use at all. This component
// only ever selects for a chat:
//
var effectiveMode = await this . ToolRegistry . GetEffectiveRetrievalModeAsync ( this . DataSourceOptions , this . LLMProvider , Tools . Components . CHAT ) ;
var sources = await this . DataSourceService . GetDataSources ( this . LLMProvider , this . DataSourceOptions , effectiveMode . Mode , this . GetDataSourcesFromConfiguredIds ( ) ) ;
2026-07-05 12:46:31 +00:00
if ( generation ! = this . loadAndApplyFiltersGeneration )
return ;
2026-09-27 14:26:52 +00:00
this . effectiveRetrievalMode = effectiveMode ;
2025-02-15 14:41:12 +00:00
this . availableDataSources = sources . AllowedDataSources ;
2026-09-17 07:48:00 +00:00
this . dataSourcesAwaitingReindex = sources . DataSourcesAwaitingReindex ;
this . dataSourceIdsAwaitingReindex = sources . DataSourcesAwaitingReindex . Select ( source = > source . Id ) . ToHashSet ( StringComparer . Ordinal ) ;
2026-09-18 12:48:02 +00:00
this . dataSourcesNeedingRepair = sources . DataSourcesNeedingRepair ;
this . dataSourceIdsNeedingRepair = sources . DataSourcesNeedingRepair . Select ( source = > source . Id ) . ToHashSet ( StringComparer . Ordinal ) ;
2025-02-15 14:41:12 +00:00
this . selectedDataSources = sources . SelectedDataSources ;
this . waitingForDataSources = false ;
this . StateHasChanged ( ) ;
}
2026-09-17 07:48:00 +00:00
2026-09-18 12:48:02 +00:00
/// <summary>
/// Why a data source is listed but cannot be picked, if it cannot.
/// </summary>
/// <remarks>
/// The repair is asked about first. The service hands a data source to one of the two lists
/// only, but should that ever change, the reason the user can act on is the one worth showing.
/// </remarks>
private DataSourceBlockReason GetBlockReason ( IDataSource dataSource )
{
if ( this . dataSourceIdsNeedingRepair . Contains ( dataSource . Id ) )
return DataSourceBlockReason . NEEDS_REPAIR ;
if ( this . dataSourceIdsAwaitingReindex . Contains ( dataSource . Id ) )
return DataSourceBlockReason . AWAITING_REINDEX ;
return DataSourceBlockReason . NONE ;
}
2026-09-17 07:48:00 +00:00
/// <summary>
2026-09-18 12:48:02 +00:00
/// The data sources the list shows: the usable ones, plus the ones which cannot be searched.
2026-09-17 07:48:00 +00:00
/// </summary>
/// <remarks>
/// Kept in the order the data sources were configured in, rather than usable ones first. A row
/// which jumps to another place the moment its data source starts being re-indexed is a row the
/// user has to find again.
/// </remarks>
private IReadOnlyList < IDataSource > GetListedDataSources ( )
{
2026-09-18 12:48:02 +00:00
if ( this . dataSourcesAwaitingReindex . Count = = 0 & & this . dataSourcesNeedingRepair . Count = = 0 )
2026-09-17 07:48:00 +00:00
return this . availableDataSources ;
var listedIds = this . availableDataSources . Select ( source = > source . Id ) . ToHashSet ( StringComparer . Ordinal ) ;
listedIds . UnionWith ( this . dataSourceIdsAwaitingReindex ) ;
2026-09-18 12:48:02 +00:00
listedIds . UnionWith ( this . dataSourceIdsNeedingRepair ) ;
2026-09-17 07:48:00 +00:00
return this . GetConfiguredDataSourcesSnapshot ( ) . Where ( source = > listedIds . Contains ( source . Id ) ) . ToList ( ) ;
}
/// <summary>
/// The preselected but unusable data sources the warning box lists.
/// </summary>
/// <remarks>
2026-09-18 12:48:02 +00:00
/// The ones which are only blocked are left out: they have a row of their own in the list
2026-09-17 07:48:00 +00:00
/// above, which says the same thing in the place the user is already looking.
/// </remarks>
private IReadOnlyList < IDataSource > GetUnavailablePreselectedDataSourcesToList ( ) = >
2026-09-18 12:48:02 +00:00
this . GetUnavailablePreselectedDataSources ( ) . Where ( source = > this . GetBlockReason ( source ) is DataSourceBlockReason . NONE ) . ToList ( ) ;
2025-02-15 14:41:12 +00:00
private async Task EnabledChanged ( bool state )
{
this . areDataSourcesEnabled = state ;
this . DataSourceOptions . DisableDataSources = ! this . areDataSourcesEnabled ;
await this . LoadAndApplyFilters ( ) ;
await this . OptionsChanged ( ) ;
this . StateHasChanged ( ) ;
}
private async Task AutoModeChanged ( bool state )
{
this . aiBasedSourceSelection = state ;
this . DataSourceOptions . AutomaticDataSourceSelection = this . aiBasedSourceSelection ;
2026-09-09 16:43:37 +00:00
await this . LoadAndApplyFilters ( ) ;
2025-02-15 14:41:12 +00:00
await this . OptionsChanged ( ) ;
}
2026-09-27 14:26:52 +00:00
private async Task SemanticSearchChanged ( bool state )
{
this . retrievalMode = state ? DataSourceRetrievalMode . SEMANTIC_SEARCH : DataSourceRetrievalMode . EVERY_MESSAGE ;
this . DataSourceOptions . RetrievalMode = this . retrievalMode ;
// Which data sources the provider may use depends on it, see LoadAndApplyFilters:
await this . LoadAndApplyFilters ( ) ;
await this . OptionsChanged ( ) ;
}
private bool IsSemanticSearchPreferred = > this . retrievalMode is DataSourceRetrievalMode . SEMANTIC_SEARCH ;
/// <summary>
/// Whether the model of the chat searches the data sources itself.
/// </summary>
/// <remarks>
/// Only the selection mode can tell, since only it knows the provider of a chat. The effective
/// mode is found out while loading the data sources; asking the preference as well keeps a
/// switch to every message from showing the other way until that loading is done.
/// </remarks>
private bool IsSemanticSearchEffective = > this . IsSemanticSearchPreferred & & this . effectiveRetrievalMode . Mode is DataSourceRetrievalMode . SEMANTIC_SEARCH ;
/// <summary>
/// Whether Semantic Search cannot be used in this chat, whatever the user prefers.
/// </summary>
/// <remarks>
/// Then there is nothing to choose: classic RAG searches the data sources. The choice is left
/// out rather than shown as one which changes nothing, and the preference stays as it is, so it
/// is back the moment the chat gets a model which can search itself.
/// </remarks>
private bool IsSemanticSearchUnavailable = > this . effectiveRetrievalMode . SemanticSearchBlockReason is not ToolOfferBlockReason . NONE ;
private string GetSemanticSearchUnavailableMessage ( ) = > this . effectiveRetrievalMode . SemanticSearchBlockReason switch
{
ToolOfferBlockReason . TOOLS_SWITCHED_OFF = > T ( "Your organization has switched tools off, so AI Studio uses classic RAG instead and searches your data sources with every message." ) ,
ToolOfferBlockReason . MODEL_CANNOT_USE_TOOLS = > T ( "The selected model cannot use tools, so AI Studio uses classic RAG instead and searches your data sources with every message." ) ,
ToolOfferBlockReason . TOOL_SWITCHED_OFF = > T ( "Your organization has switched Semantic Search off, so AI Studio uses classic RAG instead and searches your data sources with every message." ) ,
ToolOfferBlockReason . PROVIDER_CONFIDENCE_TOO_LOW = > T ( "The selected provider is not trusted enough for Semantic Search, so AI Studio uses classic RAG instead and searches your data sources with every message." ) ,
_ = > T ( "Semantic Search cannot be used here, so AI Studio uses classic RAG instead and searches your data sources with every message." ) ,
} ;
2025-02-15 14:41:12 +00:00
private async Task ValidationModeChanged ( bool state )
{
this . aiBasedValidation = state ;
this . DataSourceOptions . AutomaticValidation = this . aiBasedValidation ;
2026-09-09 16:43:37 +00:00
await this . LoadAndApplyFilters ( ) ;
2025-02-15 14:41:12 +00:00
await this . OptionsChanged ( ) ;
}
private async Task SelectionChanged ( IReadOnlyCollection < IDataSource > ? chosenDataSources )
{
this . selectedDataSources = chosenDataSources ? ? [ ] ;
2026-09-14 14:30:17 +00:00
//
// The list offers only the data sources which survived the filters, so what the user picks
// there says nothing about the preselected ones it could not show. Those are kept: dropping
// them would undo a choice the user never revisited, and it is these ids -- not this list --
// which the RAG process reads when an answer is created. The query has to run before the
// assignment, because it reads what we are about to replace.
//
var keptDataSourceIds = this . GetUnavailablePreselectedDataSources ( ) . Select ( ds = > ds . Id ) . ToList ( ) ;
this . DataSourceOptions . PreselectedDataSourceIds = [ . . keptDataSourceIds , . . this . selectedDataSources . Select ( ds = > ds . Id ) ] ;
2025-02-15 14:41:12 +00:00
await this . OptionsChanged ( ) ;
}
2026-07-05 12:46:31 +00:00
private bool IsPreselectedDataSourcesDisabledLocked ( )
{
return this . SelectionMode is DataSourceSelectionMode . CONFIGURATION_MODE
2026-09-22 14:39:17 +00:00
& & this . ConfiguresChatDefaults
2026-07-05 12:46:31 +00:00
& & ManagedConfiguration . TryGet ( x = > x . Chat , x = > x . PreselectedDataSourcesDisabled , out var meta )
& & meta . IsLocked ;
}
2026-09-27 14:26:52 +00:00
private bool IsPreselectedDataSourcesRetrievalModeLocked ( )
{
return this . SelectionMode is DataSourceSelectionMode . CONFIGURATION_MODE
& & this . ConfiguresChatDefaults
& & ManagedConfiguration . TryGet ( x = > x . Chat , x = > x . PreselectedDataSourcesRetrievalMode , out var meta )
& & meta . IsLocked ;
}
2026-07-05 12:46:31 +00:00
private bool IsPreselectedDataSourcesAutomaticSelectionLocked ( )
{
return this . SelectionMode is DataSourceSelectionMode . CONFIGURATION_MODE
2026-09-22 14:39:17 +00:00
& & this . ConfiguresChatDefaults
2026-07-05 12:46:31 +00:00
& & ManagedConfiguration . TryGet ( x = > x . Chat , x = > x . PreselectedDataSourcesAutomaticSelection , out var meta )
& & meta . IsLocked ;
}
private bool IsPreselectedDataSourcesAutomaticValidationLocked ( )
{
return this . SelectionMode is DataSourceSelectionMode . CONFIGURATION_MODE
2026-09-22 14:39:17 +00:00
& & this . ConfiguresChatDefaults
2026-07-05 12:46:31 +00:00
& & ManagedConfiguration . TryGet ( x = > x . Chat , x = > x . PreselectedDataSourcesAutomaticValidation , out var meta )
& & meta . IsLocked ;
}
private bool IsPreselectedDataSourceIdsLocked ( )
{
return this . SelectionMode is DataSourceSelectionMode . CONFIGURATION_MODE
2026-09-22 14:39:17 +00:00
& & this . ConfiguresChatDefaults
2026-07-05 12:46:31 +00:00
& & ManagedConfiguration . TryGet ( x = > x . Chat , x = > x . PreselectedDataSourceIds , out var meta )
& & meta . IsLocked ;
}
2025-02-15 14:41:12 +00:00
private async Task OptionsChanged ( )
{
this . internalChange = true ;
2026-07-05 12:46:31 +00:00
this . loadAndApplyFiltersGeneration + + ;
2025-02-15 14:41:12 +00:00
await this . DataSourceOptionsChanged . InvokeAsync ( this . DataSourceOptions ) ;
if ( this . AutoSaveAppSettings )
await this . SettingsManager . StoreSettings ( ) ;
}
private async Task ToggleDataSourceSelection ( )
{
this . showDataSourceSelection = ! this . showDataSourceSelection ;
if ( this . showDataSourceSelection )
await this . LoadAndApplyFilters ( ) ;
}
private void HideDataSourceSelection ( ) = > this . showDataSourceSelection = false ;
2025-04-27 14:13:15 +00:00
#region Overrides of MSGComponentBase
2025-02-15 14:41:12 +00:00
2025-04-27 14:13:15 +00:00
protected override Task ProcessIncomingMessage < T > ( ComponentBase ? sendingComponent , Event triggeredEvent , T ? data ) where T : default
2025-02-15 14:41:12 +00:00
{
switch ( triggeredEvent )
{
2025-02-17 11:33:34 +00:00
case Event . RAG_AUTO_DATA_SOURCES_SELECTED :
if ( data is IReadOnlyList < DataSourceAgentSelected > aiSelectedDataSources )
this . DataSourcesAISelected = aiSelectedDataSources ;
this . StateHasChanged ( ) ;
break ;
2025-02-15 14:41:12 +00:00
}
2025-04-27 14:13:15 +00:00
return Task . CompletedTask ;
2025-02-15 14:41:12 +00:00
}
#endregion
2026-09-09 16:43:37 +00:00
}