diff --git a/app/MindWork AI Studio.sln b/app/MindWork AI Studio.sln
index ef02b51..37871ac 100644
--- a/app/MindWork AI Studio.sln
+++ b/app/MindWork AI Studio.sln
@@ -2,6 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MindWork AI Studio", "MindWork AI Studio\MindWork AI Studio.csproj", "{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceCodeRules", "SourceCodeRules\SourceCodeRules\SourceCodeRules.csproj", "{0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -12,6 +14,10 @@ Global
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
diff --git a/app/MindWork AI Studio.sln.DotSettings b/app/MindWork AI Studio.sln.DotSettings
index 4038c0a..431ff5c 100644
--- a/app/MindWork AI Studio.sln.DotSettings
+++ b/app/MindWork AI Studio.sln.DotSettings
@@ -9,5 +9,6 @@
UI
True
True
+ True
True
True
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Agents/AgentDataSourceSelection.cs b/app/MindWork AI Studio/Agents/AgentDataSourceSelection.cs
index 6b1410c..7435713 100644
--- a/app/MindWork AI Studio/Agents/AgentDataSourceSelection.cs
+++ b/app/MindWork AI Studio/Agents/AgentDataSourceSelection.cs
@@ -140,17 +140,7 @@ public sealed class AgentDataSourceSelection (ILogger
//
// We start with the provider currently selected by the user:
- var agentProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == provider.Id);
-
- // If the user preselected an agent provider, we try to use this one:
- if (this.SettingsManager.ConfigurationData.AgentDataSourceSelection.PreselectAgentOptions)
- {
- var configuredAgentProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.AgentDataSourceSelection.PreselectedAgentProvider);
-
- // If the configured agent provider is available, we use it:
- if (configuredAgentProvider != default)
- agentProvider = configuredAgentProvider;
- }
+ var agentProvider = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_DATA_SOURCE_SELECTION, provider.Id, true);
// Assign the provider settings to the agent:
logger.LogInformation($"The agent for the data source selection uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.ToName()}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()}).");
diff --git a/app/MindWork AI Studio/Agents/AgentRetrievalContextValidation.cs b/app/MindWork AI Studio/Agents/AgentRetrievalContextValidation.cs
index ae54de5..3f4bf4c 100644
--- a/app/MindWork AI Studio/Agents/AgentRetrievalContextValidation.cs
+++ b/app/MindWork AI Studio/Agents/AgentRetrievalContextValidation.cs
@@ -132,18 +132,8 @@ public sealed class AgentRetrievalContextValidation (ILogger x.Id == provider.Id);
-
- // If the user preselected an agent provider, we try to use this one:
- if (this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectAgentOptions)
- {
- var configuredAgentProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectedAgentProvider);
-
- // If the configured agent provider is available, we use it:
- if (configuredAgentProvider != default)
- agentProvider = configuredAgentProvider;
- }
-
+ var agentProvider = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION, provider.Id, true);
+
// Assign the provider settings to the agent:
logger.LogInformation($"The agent for the retrieval context validation uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.ToName()}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()}).");
this.ProviderSettings = agentProvider;
@@ -163,11 +153,16 @@ public sealed class AgentRetrievalContextValidation (ILogger>(retrievalContexts.Count);
// Read the number of parallel validations:
- var numParallelValidations = this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.NumParallelValidations;
+ var numParallelValidations = 3;
+ if(this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectAgentOptions)
+ numParallelValidations = this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.NumParallelValidations;
+
numParallelValidations = Math.Max(1, numParallelValidations);
// Use a semaphore to limit the number of parallel validations:
diff --git a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs
index e9a9f9b..a1e60c8 100644
--- a/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs
+++ b/app/MindWork AI Studio/Components/ConfigurationProviderSelection.razor.cs
@@ -1,3 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+
using AIStudio.Provider;
using AIStudio.Settings;
@@ -47,6 +49,7 @@ public partial class ConfigurationProviderSelection : ComponentBase, IMessageBus
#endregion
+ [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private IEnumerable> FilteredData()
{
if(this.Component is not Tools.Components.NONE and not Tools.Components.APP_SETTINGS)
diff --git a/app/MindWork AI Studio/Components/DataSourceSelection.razor b/app/MindWork AI Studio/Components/DataSourceSelection.razor
index 0816044..6b29979 100644
--- a/app/MindWork AI Studio/Components/DataSourceSelection.razor
+++ b/app/MindWork AI Studio/Components/DataSourceSelection.razor
@@ -37,8 +37,12 @@
@if (this.areDataSourcesEnabled)
{
-
+ @if (this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation)
+ {
+
+ }
+
@if (this.aiBasedSourceSelection is false || this.DataSourcesAISelected.Count == 0)
{
diff --git a/app/MindWork AI Studio/Components/ProviderSelection.razor.cs b/app/MindWork AI Studio/Components/ProviderSelection.razor.cs
index 927c1d6..c5a0e3b 100644
--- a/app/MindWork AI Studio/Components/ProviderSelection.razor.cs
+++ b/app/MindWork AI Studio/Components/ProviderSelection.razor.cs
@@ -1,3 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+
using AIStudio.Assistants;
using AIStudio.Provider;
using AIStudio.Settings;
@@ -29,6 +31,7 @@ public partial class ProviderSelection : ComponentBase
await this.ProviderSettingsChanged.InvokeAsync(provider);
}
+ [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private IEnumerable GetAvailableProviders()
{
var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(this.AssistantBase?.Component ?? Tools.Components.NONE);
diff --git a/app/MindWork AI Studio/Components/ReadWebContent.razor.cs b/app/MindWork AI Studio/Components/ReadWebContent.razor.cs
index aebe7ef..6cf4070 100644
--- a/app/MindWork AI Studio/Components/ReadWebContent.razor.cs
+++ b/app/MindWork AI Studio/Components/ReadWebContent.razor.cs
@@ -59,11 +59,7 @@ public partial class ReadWebContent : ComponentBase
if(this.PreselectContentCleanerAgent)
this.useContentCleanerAgent = true;
- if (this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)
- this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider);
- else
- this.providerSettings = this.ProviderSettings;
-
+ this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_TEXT_CONTENT_CLEANER, this.ProviderSettings.Id, true);
await base.OnInitializedAsync();
}
diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs
index e2c434f..0aa3afd 100644
--- a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs
+++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor.cs
@@ -1,3 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+
using AIStudio.Dialogs;
using AIStudio.Provider;
using AIStudio.Settings;
@@ -26,6 +28,7 @@ public partial class SettingsPanelProviders : SettingsPanelBase
#endregion
+ [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private async Task AddLLMProvider()
{
var dialogParameters = new DialogParameters
@@ -48,6 +51,7 @@ public partial class SettingsPanelProviders : SettingsPanelBase
await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED);
}
+ [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private async Task EditLLMProvider(AIStudio.Settings.Provider provider)
{
var dialogParameters = new DialogParameters
@@ -82,6 +86,7 @@ public partial class SettingsPanelProviders : SettingsPanelBase
await this.MessageBus.SendMessage(this, Event.CONFIGURATION_CHANGED);
}
+ [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private async Task DeleteLLMProvider(AIStudio.Settings.Provider provider)
{
var dialogParameters = new DialogParameters
@@ -112,6 +117,7 @@ public partial class SettingsPanelProviders : SettingsPanelBase
return modelName.Length > MAX_LENGTH ? "[...] " + modelName[^Math.Min(MAX_LENGTH, modelName.Length)..] : modelName;
}
+ [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private async Task UpdateProviders()
{
this.AvailableLLMProviders.Clear();
diff --git a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs
index a721b95..4e76b47 100644
--- a/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs
+++ b/app/MindWork AI Studio/Dialogs/ProviderDialog.razor.cs
@@ -137,7 +137,9 @@ public partial class ProviderDialog : ComponentBase, ISecretId
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
// Load the used instance names:
+ #pragma warning disable MWAIS0001
this.UsedInstanceNames = this.SettingsManager.ConfigurationData.Providers.Select(x => x.InstanceName.ToLowerInvariant()).ToList();
+ #pragma warning restore MWAIS0001
// When editing, we need to load the data:
if(this.IsEditing)
diff --git a/app/MindWork AI Studio/MindWork AI Studio.csproj b/app/MindWork AI Studio/MindWork AI Studio.csproj
index 4caca35..c2d7649 100644
--- a/app/MindWork AI Studio/MindWork AI Studio.csproj
+++ b/app/MindWork AI Studio/MindWork AI Studio.csproj
@@ -53,6 +53,10 @@
+
+
+
+
diff --git a/app/MindWork AI Studio/Settings/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs
index 0fa3e18..29e9439 100644
--- a/app/MindWork AI Studio/Settings/SettingsManager.cs
+++ b/app/MindWork AI Studio/Settings/SettingsManager.cs
@@ -1,3 +1,4 @@
+using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -141,7 +142,8 @@ public sealed class SettingsManager(ILogger logger)
return minimumLevel;
}
- public Provider GetPreselectedProvider(Tools.Components component, string? chatProviderId = null)
+ [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
+ public Provider GetPreselectedProvider(Tools.Components component, string? currentProviderId = null, bool usePreselectionBeforeCurrentProvider = false)
{
var minimumLevel = this.GetMinimumConfidenceLevel(component);
@@ -149,17 +151,43 @@ public sealed class SettingsManager(ILogger logger)
if (this.ConfigurationData.Providers.Count == 1 && this.ConfigurationData.Providers[0].UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
return this.ConfigurationData.Providers[0];
- // When there is a chat provider, and it has a confidence level that is high enough, we return it:
- if (chatProviderId is not null && !string.IsNullOrWhiteSpace(chatProviderId))
+ // Is there a current provider with a sufficiently high confidence level?
+ Provider currentProvider = default;
+ if (currentProviderId is not null && !string.IsNullOrWhiteSpace(currentProviderId))
{
- var chatProvider = this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == chatProviderId);
- if (chatProvider.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
- return chatProvider;
+ var currentProviderProbe = this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == currentProviderId);
+ if (currentProviderProbe.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
+ currentProvider = currentProviderProbe;
}
- // When there is a component-preselected provider, and it has a confidence level that is high enough, we return it:
- var preselectedProvider = component.PreselectedProvider(this);
- if(preselectedProvider != default && preselectedProvider.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
+ // Is there a component-preselected provider with a sufficiently high confidence level?
+ Provider preselectedProvider = default;
+ var preselectedProviderProbe = component.PreselectedProvider(this);
+ if(preselectedProviderProbe != default && preselectedProviderProbe.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
+ preselectedProvider = preselectedProviderProbe;
+
+ //
+ // Case: The preselected provider should be used before the current provider,
+ // and the preselected provider is available and has a confidence level
+ // that is high enough.
+ //
+ if(usePreselectionBeforeCurrentProvider && preselectedProvider != default)
+ return preselectedProvider;
+
+ //
+ // Case: The current provider is available and has a confidence level that is
+ // high enough.
+ //
+ if(currentProvider != default)
+ return currentProvider;
+
+ //
+ // Case: The current provider should be used before the preselected provider,
+ // but the current provider is not available or does not have a confidence
+ // level that is high enough. The preselected provider is available and
+ // has a confidence level that is high enough.
+ //
+ if(preselectedProvider != default)
return preselectedProvider;
// When there is an app-wide preselected provider, and it has a confidence level that is high enough, we return it:
diff --git a/app/MindWork AI Studio/Tools/Components.cs b/app/MindWork AI Studio/Tools/Components.cs
index 4faa55a..d65a5c5 100644
--- a/app/MindWork AI Studio/Tools/Components.cs
+++ b/app/MindWork AI Studio/Tools/Components.cs
@@ -21,4 +21,8 @@ public enum Components
CHAT,
APP_SETTINGS,
+
+ AGENT_TEXT_CONTENT_CLEANER,
+ AGENT_DATA_SOURCE_SELECTION,
+ AGENT_RETRIEVAL_CONTEXT_VALIDATION,
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs
index e0fdfd4..6112deb 100644
--- a/app/MindWork AI Studio/Tools/ComponentsExtensions.cs
+++ b/app/MindWork AI Studio/Tools/ComponentsExtensions.cs
@@ -1,3 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+
using AIStudio.Provider;
using AIStudio.Settings;
@@ -12,6 +14,10 @@ public static class ComponentsExtensions
Components.BIAS_DAY_ASSISTANT => false,
Components.APP_SETTINGS => false,
+ Components.AGENT_TEXT_CONTENT_CLEANER => false,
+ Components.AGENT_DATA_SOURCE_SELECTION => false,
+ Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION => false,
+
_ => true,
};
@@ -76,6 +82,7 @@ public static class ComponentsExtensions
_ => default,
};
+ [SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
public static AIStudio.Settings.Provider PreselectedProvider(this Components component, SettingsManager settingsManager) => component switch
{
Components.GRAMMAR_SPELLING_ASSISTANT => settingsManager.ConfigurationData.GrammarSpelling.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider) : default,
@@ -95,6 +102,10 @@ public static class ComponentsExtensions
Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Chat.PreselectedProvider) : default,
+ Components.AGENT_TEXT_CONTENT_CLEANER => settingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider) : default,
+ Components.AGENT_DATA_SOURCE_SELECTION => settingsManager.ConfigurationData.AgentDataSourceSelection.PreselectAgentOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.AgentDataSourceSelection.PreselectedAgentProvider) : default,
+ Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION => settingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectAgentOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectedAgentProvider) : default,
+
_ => default,
};
diff --git a/app/MindWork AI Studio/Tools/RAG/AugmentationProcesses/AugmentationOne.cs b/app/MindWork AI Studio/Tools/RAG/AugmentationProcesses/AugmentationOne.cs
index e5a2b93..fd6e30a 100644
--- a/app/MindWork AI Studio/Tools/RAG/AugmentationProcesses/AugmentationOne.cs
+++ b/app/MindWork AI Studio/Tools/RAG/AugmentationProcesses/AugmentationOne.cs
@@ -35,7 +35,7 @@ public sealed class AugmentationOne : IAugmentationProcess
var numTotalRetrievalContexts = retrievalContexts.Count;
// Want the user to validate all retrieval contexts?
- if (settings.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation)
+ if (settings.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation && chatThread.DataSourceOptions.AutomaticValidation)
{
// Let's get the validation agent & set up its provider:
var validationAgent = Program.SERVICE_PROVIDER.GetService()!;
diff --git a/app/MindWork AI Studio/packages.lock.json b/app/MindWork AI Studio/packages.lock.json
index d070220..2ae5081 100644
--- a/app/MindWork AI Studio/packages.lock.json
+++ b/app/MindWork AI Studio/packages.lock.json
@@ -77,6 +77,11 @@
"resolved": "31.0.3",
"contentHash": "ygck8DR4mG/VDA/LgIVVGpEtXXPDVaaNZNJGrOAJ4pckVw4MbAQ3n/u6YFDv3bwlQhlxTmPhCyk5E4hxe96Crg=="
},
+ "Humanizer.Core": {
+ "type": "Transitive",
+ "resolved": "2.14.1",
+ "contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw=="
+ },
"Markdig": {
"type": "Transitive",
"resolved": "0.37.0",
@@ -132,6 +137,56 @@
"resolved": "8.0.11",
"contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A=="
},
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg=="
+ },
+ "Microsoft.CodeAnalysis.Common": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Hhaw6DKZHiR+vgOdIqvndfUntJhmDR7MjylUJ55EvWtDyJFLDf2eij8r9tcwXP35FLD+bVNNCO0+KIYuvJjNnA==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Analyzers": "3.3.3",
+ "System.Collections.Immutable": "6.0.0",
+ "System.Memory": "4.5.4",
+ "System.Reflection.Metadata": "5.0.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0",
+ "System.Text.Encoding.CodePages": "6.0.0",
+ "System.Threading.Tasks.Extensions": "4.5.4"
+ }
+ },
+ "Microsoft.CodeAnalysis.CSharp": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "0PU4a2h7L6N9SlF/oNHwj2A/+n0LK/7n6PEGvXyIZq8hc7r/TztB+47mhVLvapT6bWSV7nMT78cNxbQuC6tk6g==",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.Common": "[4.3.0]"
+ }
+ },
+ "Microsoft.CodeAnalysis.CSharp.Workspaces": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "CH2kezeYUD9/+nGs7QZ6xpOqD6OH6000YkAyU8LbhqLp7W65Xb+HerBzDX9yfprmRwArlF887QhZd8nW6enHIg==",
+ "dependencies": {
+ "Humanizer.Core": "2.14.1",
+ "Microsoft.CodeAnalysis.CSharp": "[4.3.0]",
+ "Microsoft.CodeAnalysis.Common": "[4.3.0]",
+ "Microsoft.CodeAnalysis.Workspaces.Common": "[4.3.0]"
+ }
+ },
+ "Microsoft.CodeAnalysis.Workspaces.Common": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "oFF7lU3dQIeEbAVF6Qq/YEA4jvys3oQKkDezP8NcQTFgD8uRUiIA4NimRxANaWxK2n2PT4DAQspIOtrAE2hSdA==",
+ "dependencies": {
+ "Humanizer.Core": "2.14.1",
+ "Microsoft.Bcl.AsyncInterfaces": "6.0.0",
+ "Microsoft.CodeAnalysis.Common": "[4.3.0]",
+ "System.Composition": "6.0.0",
+ "System.IO.Pipelines": "6.0.3"
+ }
+ },
"Microsoft.Extensions.DependencyInjection": {
"type": "Transitive",
"resolved": "8.0.1",
@@ -196,17 +251,117 @@
"resolved": "8.0.11",
"contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw=="
},
+ "System.Collections.Immutable": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Composition": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "d7wMuKQtfsxUa7S13tITC8n1cQzewuhD5iDjZtK2prwFfKVzdYtgrTHgjaV03Zq7feGQ5gkP85tJJntXwInsJA==",
+ "dependencies": {
+ "System.Composition.AttributedModel": "6.0.0",
+ "System.Composition.Convention": "6.0.0",
+ "System.Composition.Hosting": "6.0.0",
+ "System.Composition.Runtime": "6.0.0",
+ "System.Composition.TypedParts": "6.0.0"
+ }
+ },
+ "System.Composition.AttributedModel": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "WK1nSDLByK/4VoC7fkNiFuTVEiperuCN/Hyn+VN30R+W2ijO1d0Z2Qm0ScEl9xkSn1G2MyapJi8xpf4R8WRa/w=="
+ },
+ "System.Composition.Convention": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "XYi4lPRdu5bM4JVJ3/UIHAiG6V6lWWUlkhB9ab4IOq0FrRsp0F4wTyV4Dj+Ds+efoXJ3qbLqlvaUozDO7OLeXA==",
+ "dependencies": {
+ "System.Composition.AttributedModel": "6.0.0"
+ }
+ },
+ "System.Composition.Hosting": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "w/wXjj7kvxuHPLdzZ0PAUt++qJl03t7lENmb2Oev0n3zbxyNULbWBlnd5J5WUMMv15kg5o+/TCZFb6lSwfaUUQ==",
+ "dependencies": {
+ "System.Composition.Runtime": "6.0.0"
+ }
+ },
+ "System.Composition.Runtime": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "qkRH/YBaMPTnzxrS5RDk1juvqed4A6HOD/CwRcDGyPpYps1J27waBddiiq1y93jk2ZZ9wuA/kynM+NO0kb3PKg=="
+ },
+ "System.Composition.TypedParts": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "iUR1eHrL8Cwd82neQCJ00MpwNIBs4NZgXzrPqx8NJf/k4+mwBO0XCRmHYJT4OLSwDDqh5nBLJWkz5cROnrGhRA==",
+ "dependencies": {
+ "System.Composition.AttributedModel": "6.0.0",
+ "System.Composition.Hosting": "6.0.0",
+ "System.Composition.Runtime": "6.0.0"
+ }
+ },
"System.IO.Pipelines": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA=="
},
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.5.4",
+ "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw=="
+ },
+ "System.Reflection.Metadata": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ=="
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ },
+ "System.Text.Encoding.CodePages": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "System.Threading.Tasks.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.5.4",
+ "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg=="
+ },
"ZXing.Net": {
"type": "Transitive",
"resolved": "0.16.9",
"contentHash": "7WaVMHklpT3Ye2ragqRIwlFRsb6kOk63BOGADV0fan3ulVfGLUYkDi5yNUsZS/7FVNkWbtHAlDLmu4WnHGfqvQ=="
+ },
+ "sourcecoderules": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.CodeAnalysis.CSharp": "[4.3.0, )",
+ "Microsoft.CodeAnalysis.CSharp.Workspaces": "[4.3.0, )"
+ }
}
},
- "net8.0/osx-arm64": {}
+ "net8.0/osx-arm64": {
+ "System.Text.Encoding.CodePages": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
+ "dependencies": {
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.29.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.29.md
index c903787..468beec 100644
--- a/app/MindWork AI Studio/wwwroot/changelog/v0.9.29.md
+++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.29.md
@@ -6,4 +6,5 @@
- Added an agent to validate whether a retrieval context makes sense for the given prompt. This preview feature is hidden behind the RAG feature flag.
- Added a generic RAG process to integrate possibly any data in your chats. Although the generic RAG process is now implemented, the retrieval part is working only with external data sources using the ERI interface. That means that you could integrate your company's data from the corporate network by now. The retrieval process for your local data is still under development and will take several weeks to be released. In order to use data through ERI, you (or your company) have to develop an ERI server. You might use the ERI server assistant within AI Studio to do so. This preview feature is hidden behind the RAG feature flag.
- Improved confidence card for small spaces.
+- Improved data security by enforcing provider filtering based on the chosen confidence level. To ensure this in the future, source code analyzers have been added to warn developers about insecure code.
- Fixed a bug in which 'APP_SETTINGS' appeared as a valid destination in the "send to" menu.
\ No newline at end of file
diff --git a/app/SourceCodeRules/SourceCodeRules/AnalyzerReleases.Shipped.md b/app/SourceCodeRules/SourceCodeRules/AnalyzerReleases.Shipped.md
new file mode 100644
index 0000000..6b73c82
--- /dev/null
+++ b/app/SourceCodeRules/SourceCodeRules/AnalyzerReleases.Shipped.md
@@ -0,0 +1,7 @@
+## Release 1.0
+
+### New Rules
+
+ Rule ID | Category | Severity | Notes
+-----------|----------|----------|------------------------
+ MWAIS0001 | Usage | Error | ProviderAccessAnalyzer
\ No newline at end of file
diff --git a/app/SourceCodeRules/SourceCodeRules/AnalyzerReleases.Unshipped.md b/app/SourceCodeRules/SourceCodeRules/AnalyzerReleases.Unshipped.md
new file mode 100644
index 0000000..5ae74b3
--- /dev/null
+++ b/app/SourceCodeRules/SourceCodeRules/AnalyzerReleases.Unshipped.md
@@ -0,0 +1,10 @@
+### New Rules
+
+ Rule ID | Category | Severity | Notes
+---------|----------|----------|-------
+
+
+### Changed Rules
+
+ Rule ID | New Category | New Severity | Old Category | Old Severity | Notes
+---------|--------------|--------------|--------------|--------------|-------
diff --git a/app/SourceCodeRules/SourceCodeRules/ProviderAccessAnalyzer.cs b/app/SourceCodeRules/SourceCodeRules/ProviderAccessAnalyzer.cs
new file mode 100644
index 0000000..a28d7e0
--- /dev/null
+++ b/app/SourceCodeRules/SourceCodeRules/ProviderAccessAnalyzer.cs
@@ -0,0 +1,71 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+
+namespace SourceCodeRules;
+
+#pragma warning disable RS1038
+[DiagnosticAnalyzer(LanguageNames.CSharp)]
+#pragma warning restore RS1038
+public class ProviderAccessAnalyzer : DiagnosticAnalyzer
+{
+ private const string DIAGNOSTIC_ID = $"{Tools.ID_PREFIX}0001";
+
+ private static readonly string TITLE = "Direct access to `Providers` is not allowed";
+
+ private static readonly string MESSAGE_FORMAT = "Direct access to `SettingsManager.ConfigurationData.Providers` is not allowed. Instead, use APIs like `SettingsManager.GetPreselectedProvider`, etc.";
+
+ private static readonly string DESCRIPTION = MESSAGE_FORMAT;
+
+ private const string CATEGORY = "Usage";
+
+ private static readonly DiagnosticDescriptor RULE = new(DIAGNOSTIC_ID, TITLE, MESSAGE_FORMAT, CATEGORY, DiagnosticSeverity.Error, isEnabledByDefault: true, description: DESCRIPTION);
+
+ public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(RULE);
+
+ public override void Initialize(AnalysisContext context)
+ {
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+ context.EnableConcurrentExecution();
+ context.RegisterSyntaxNodeAction(this.AnalyzeMemberAccess, SyntaxKind.SimpleMemberAccessExpression);
+ }
+
+ private void AnalyzeMemberAccess(SyntaxNodeAnalysisContext context)
+ {
+ var memberAccess = (MemberAccessExpressionSyntax)context.Node;
+
+ // Prüfen, ob wir eine Kette von Zugriffen haben, die auf "Providers" endet
+ if (memberAccess.Name.Identifier.Text != "Providers")
+ return;
+
+ // Den kompletten Zugriffspfad aufbauen
+ var fullPath = this.GetFullMemberAccessPath(memberAccess);
+
+ // Prüfen, ob der Pfad unserem verbotenen Muster entspricht
+ if (fullPath.EndsWith("ConfigurationData.Providers"))
+ {
+ var diagnostic = Diagnostic.Create(RULE, memberAccess.GetLocation());
+ context.ReportDiagnostic(diagnostic);
+ }
+ }
+
+ private string GetFullMemberAccessPath(ExpressionSyntax expression)
+ {
+ var parts = new List();
+ while (expression is MemberAccessExpressionSyntax memberAccess)
+ {
+ parts.Add(memberAccess.Name.Identifier.Text);
+ expression = memberAccess.Expression;
+ }
+
+ if (expression is IdentifierNameSyntax identifier)
+ parts.Add(identifier.Identifier.Text);
+
+ parts.Reverse();
+ return string.Join(".", parts);
+ }
+}
\ No newline at end of file
diff --git a/app/SourceCodeRules/SourceCodeRules/SourceCodeRules.csproj b/app/SourceCodeRules/SourceCodeRules/SourceCodeRules.csproj
new file mode 100644
index 0000000..8cf49a2
--- /dev/null
+++ b/app/SourceCodeRules/SourceCodeRules/SourceCodeRules.csproj
@@ -0,0 +1,26 @@
+
+
+
+ netstandard2.0
+ false
+ enable
+ latest
+
+ true
+ true
+
+ SourceCodeRules
+ SourceCodeRules
+ 1.0.0
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
diff --git a/app/SourceCodeRules/SourceCodeRules/Tools.cs b/app/SourceCodeRules/SourceCodeRules/Tools.cs
new file mode 100644
index 0000000..aa83af8
--- /dev/null
+++ b/app/SourceCodeRules/SourceCodeRules/Tools.cs
@@ -0,0 +1,6 @@
+namespace SourceCodeRules;
+
+public static class Tools
+{
+ public const string ID_PREFIX = "MWAIS";
+}
\ No newline at end of file