mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-17 14:18:00 +00:00
Merge branch 'main' into chunk-data
Resolved 29 conflicting files. The notable decisions: Confidence: main's tool-calling gate (RequiredProviderConfidence) and this branch's local-RAG gate (DataConfidenceLevel) turned out to be the same rule on the same axis, so they are now one field. Both tool results and data sources raise it through RequireProviderConfidence(). The gate checks the level strictly and no longer exempts providers trusted by configuration: TrustedProviderIds is documented as applying to data-source security checks only, and organizations set confidence through DataConfidence .CustomConfidenceScheme instead. The security axis (DataSecurity, ERI, IsTrustedForDataSourceSecurityChecks) is unchanged. Provider creation: main's CreateProvider signature won (hfEndpointKind, capabilityOverrides, no model parameter); tokenizerPath was added to it and is set for every provider, including the new Hetzner, IONOS and LiteLLM. Provider and EmbeddingProvider combine the record parameters, Lua parsing and Lua serialization of both sides. File types: main's hierarchy (ODT leaf, WORD parent, PowerPoint without the legacy .ppt, TABULAR instead of DELIMITED_TABLE) plus this branch's SPREADSHEET parent with ODS and the xlsm/xlsb/xla/xlam extensions, which the runtime already reads. Both sides had added a conflicting HTML filter; the reading family keeps the name, and the export path uses a narrow HTML_DOCUMENT, following the existing LATEX/TEX split. Runtime: main's file_data.rs is the base, including the prompt-injection sanitizer and the extraction routes. Token counting and chunk segmentation moved into take_released, so they act on the text the filter has released rather than on text it is still holding. A failed count is logged and left out instead of ending the extraction, because the app counts such a segment itself. Data sources: the participating-provider checks of this branch are kept, and main's GetAllowedDataSources overload now builds on them. DirectChatService resolves the launched chat's data source options before the check, so filter and chat see the same options. .NET and Rust both build clean; I18N regenerated to 4060 keys.
This commit is contained in:
640 files changed
+45059
-4952
No files matched your search
@@ -6,6 +6,7 @@ using AIStudio.Tools.AIJobs;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
using AIStudio.Tools.Media;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.Security;
|
||||
using AIStudio.Tools.Rust;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
@@ -57,6 +58,9 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
|
||||
[Inject]
|
||||
private DataSourceEmbeddingService DataSourceEmbeddingService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private CircuitStateService CircuitState { get; init; } = null!;
|
||||
|
||||
private ILanguagePlugin Lang { get; set; } = PluginFactory.BaseLanguage;
|
||||
|
||||
@@ -75,6 +79,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
private bool startupCompleted;
|
||||
private bool settingsWriteProtectionWarningShown;
|
||||
private readonly SemaphoreSlim mandatoryInfoDialogSemaphore = new(1, 1);
|
||||
private readonly SemaphoreSlim promptInjectionDialogSemaphore = new(1, 1);
|
||||
|
||||
private DataSourceEmbeddingOverview embeddingOverview = new(false, DataSourceEmbeddingState.COMPLETED, 0, 0, 0);
|
||||
private IReadOnlyCollection<NavBarItem> navItems = [];
|
||||
@@ -116,11 +121,11 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
await this.DataSourceEmbeddingService.QueueAllInternalDataSourcesIfAutomaticRefreshAsync();
|
||||
|
||||
// Register this component with the message bus:
|
||||
this.MessageBus.RegisterComponent(this);
|
||||
this.MessageBus.RegisterComponent(this, this.CircuitState);
|
||||
this.MessageBus.ApplyFilters(this, [],
|
||||
[
|
||||
Event.UPDATE_AVAILABLE, Event.CONFIGURATION_CHANGED, Event.COLOR_THEME_CHANGED, Event.SHOW_ERROR,
|
||||
Event.SHOW_WARNING, Event.SHOW_SUCCESS, Event.SHOW_INFO, Event.STARTUP_PLUGIN_SYSTEM, Event.PLUGINS_RELOADED,
|
||||
Event.SHOW_WARNING, Event.SHOW_SUCCESS, Event.SHOW_INFO, Event.SHOW_PROMPT_INJECTION_ALERT, Event.STARTUP_PLUGIN_SYSTEM, Event.PLUGINS_RELOADED,
|
||||
Event.INSTALL_UPDATE, Event.STARTUP_COMPLETED, Event.AI_JOB_CHANGED, Event.AI_JOB_FINISHED,
|
||||
Event.CHAT_GENERATION_CHANGED, Event.RAG_EMBEDDING_STATUS_CHANGED,Event.ASSISTANT_SESSION_CHANGED,
|
||||
Event.ASSISTANT_SESSION_FINISHED,
|
||||
@@ -243,7 +248,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
this.LoadEmbeddingItem();
|
||||
this.StateHasChanged();
|
||||
if (this.startupCompleted)
|
||||
_ = this.EnsureMandatoryInfosAcceptedAsync();
|
||||
this.EnsureMandatoryInfosAcceptedAsync().Observe($"{nameof(MainLayout)}: mandatory infos after a configuration change");
|
||||
break;
|
||||
|
||||
case Event.COLOR_THEME_CHANGED:
|
||||
@@ -265,6 +270,12 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
|
||||
break;
|
||||
|
||||
case Event.SHOW_PROMPT_INJECTION_ALERT:
|
||||
if (data is PromptInjectionAlertMessage promptInjectionAlert)
|
||||
await this.ShowPromptInjectionAlertAsync(promptInjectionAlert);
|
||||
|
||||
break;
|
||||
|
||||
case Event.SHOW_ERROR:
|
||||
if (data is DataErrorMessage error)
|
||||
error.Show(this.Snackbar);
|
||||
@@ -284,7 +295,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
break;
|
||||
|
||||
case Event.STARTUP_PLUGIN_SYSTEM:
|
||||
_ = Task.Run(async () =>
|
||||
Task.Run(async () =>
|
||||
{
|
||||
// Set up the plugin system:
|
||||
if (PluginFactory.Setup())
|
||||
@@ -295,8 +306,10 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
//
|
||||
// Check if there is an enterprise configuration plugin to download:
|
||||
//
|
||||
// Every deferred environment matters here: each one is a configuration
|
||||
// to download, so this is the one place which uses all of them.
|
||||
var enterpriseEnvironments = this.MessageBus
|
||||
.CheckDeferredMessages<EnterpriseEnvironment>(Event.STARTUP_ENTERPRISE_ENVIRONMENT)
|
||||
.TakeDeferredMessages<EnterpriseEnvironment>(Event.STARTUP_ENTERPRISE_ENVIRONMENT)
|
||||
.Where(env => env != default)
|
||||
.ToList();
|
||||
|
||||
@@ -337,7 +350,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
PluginFactory.SetUpHotReloading();
|
||||
await this.MessageBus.SendMessage<bool>(this, Event.STARTUP_COMPLETED);
|
||||
}
|
||||
});
|
||||
}).Observe($"{nameof(MainLayout)}: setting up the plugin system");
|
||||
break;
|
||||
|
||||
case Event.PLUGINS_RELOADED:
|
||||
@@ -349,12 +362,12 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
|
||||
await this.InvokeAsync(this.StateHasChanged);
|
||||
if (this.startupCompleted)
|
||||
_ = this.EnsureMandatoryInfosAcceptedAsync();
|
||||
this.EnsureMandatoryInfosAcceptedAsync().Observe($"{nameof(MainLayout)}: mandatory infos after a plugin reload");
|
||||
break;
|
||||
|
||||
case Event.STARTUP_COMPLETED:
|
||||
this.startupCompleted = true;
|
||||
_ = this.EnsureMandatoryInfosAcceptedAsync();
|
||||
this.EnsureMandatoryInfosAcceptedAsync().Observe($"{nameof(MainLayout)}: mandatory infos after the startup");
|
||||
break;
|
||||
|
||||
case Event.RAG_EMBEDDING_STATUS_CHANGED:
|
||||
@@ -366,6 +379,32 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
});
|
||||
}
|
||||
|
||||
private async Task ShowPromptInjectionAlertAsync(PromptInjectionAlertMessage alert)
|
||||
{
|
||||
await this.promptInjectionDialogSemaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (!this.SettingsManager.ConfigurationData.App.ShowPromptInjectionAlert)
|
||||
return;
|
||||
|
||||
var dialogParameters = new DialogParameters<PromptInjectionAlertDialog>
|
||||
{
|
||||
{ x => x.Alert, alert },
|
||||
};
|
||||
|
||||
var dialogReference = await this.DialogService.ShowAsync<PromptInjectionAlertDialog>(
|
||||
T("Security notice"),
|
||||
dialogParameters,
|
||||
DialogOptions.FULLSCREEN);
|
||||
|
||||
await dialogReference.Result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.promptInjectionDialogSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public Task<TResult?> ProcessMessageWithResult<TPayload, TResult>(ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data)
|
||||
{
|
||||
return Task.FromResult<TResult?>(default);
|
||||
@@ -381,11 +420,11 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
|
||||
/// <summary>Refreshes navigation activity colors when a media import changes state.</summary>
|
||||
private void OnMediaImportStateChanged(MediaImportOwner owner)
|
||||
{
|
||||
_ = this.InvokeAsync(() =>
|
||||
this.InvokeAsync(() =>
|
||||
{
|
||||
this.LoadNavItems();
|
||||
this.StateHasChanged();
|
||||
});
|
||||
}).Observe($"{nameof(MainLayout)}: refreshing the navigation after a media import change");
|
||||
}
|
||||
|
||||
private IEnumerable<NavBarItem> GetNavItems()
|
||||
|
||||
Reference in new issue
Block a user