mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-18 05:18:00 +00:00
Fix document analysis provider selection freezes
This commit is contained in:
1 parent
6e735523c6
commit
894c509f4d
7 files changed
+69
-23
No files matched your search
@@ -184,7 +184,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
|||||||
this.formChangeTimer.Elapsed += (_, _) =>
|
this.formChangeTimer.Elapsed += (_, _) =>
|
||||||
{
|
{
|
||||||
this.formChangeTimer.Stop();
|
this.formChangeTimer.Stop();
|
||||||
this.OnFormChange().Observe($"{nameof(AssistantBase<TSettings>)}: handling a form change");
|
this.InvokeAsync(this.OnFormChange).Observe($"{nameof(AssistantBase<TSettings>)}: handling a form change");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.MightPreselectValues();
|
this.MightPreselectValues();
|
||||||
|
|||||||
@@ -104,13 +104,13 @@ else
|
|||||||
@T("Note: This setting only takes effect when this policy is exported and distributed via a configuration plugin to other users. When enabled, users will only see the document selection interface and cannot view or modify the policy details. This setting does NOT affect your local view - you will always see the full policy definition for policies you create.")
|
@T("Note: This setting only takes effect when this policy is exported and distributed via a configuration plugin to other users. When enabled, users will only see the document selection interface and cannot view or modify the policy details. This setting does NOT affect your local view - you will always see the full policy definition for policies you create.")
|
||||||
</MudJustifiedText>
|
</MudJustifiedText>
|
||||||
|
|
||||||
<ConfigurationMinConfidenceSelection Disabled="@(() => this.IsNoPolicySelectedOrProtected)" RestrictToGlobalMinimumConfidence="true" SelectedValue="@(() => this.policyMinimumProviderConfidence)" SelectionUpdateAsync="@(async level => await this.PolicyMinimumConfidenceWasChangedAsync(level))" />
|
<ConfigurationMinConfidenceSelection Disabled="@(() => this.IsNoPolicySelectedOrProtected)" RestrictToGlobalMinimumConfidence="true" SelectedValue="@(() => this.policyMinimumProviderConfidence)" SelectionUpdate="@this.PolicyMinimumConfidenceWasChanged" />
|
||||||
|
|
||||||
<ToolSelectionField Component="@this.Component" SelectedToolIds="@this.policyAllowedToolIds" SelectedToolIdsChanged="@this.PolicyAllowedToolsWasChangedAsync" Disabled="@this.IsNoPolicySelectedOrProtected" Label="@T("Tools this policy permits")" Help="@T("Only the tools selected here can be used by the AI for an analysis with this policy. Every tool still has to meet the confidence requirements of the selected provider, so a tool may remain unavailable even when this policy permits it.")"/>
|
<ToolSelectionField Component="@this.Component" SelectedToolIds="@this.policyAllowedToolIds" SelectedToolIdsChanged="@this.PolicyAllowedToolsWasChanged" Disabled="@this.IsNoPolicySelectedOrProtected" Label="@T("Tools this policy permits")" Help="@T("Only the tools selected here can be used by the AI for an analysis with this policy. Every tool still has to meet the confidence requirements of the selected provider, so a tool may remain unavailable even when this policy permits it.")"/>
|
||||||
|
|
||||||
<ConfigurationProviderSelection Component="Components.DOCUMENT_ANALYSIS_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => this.IsNoPolicySelectedOrProtected)" SelectedValue="@(() => this.policyPreselectedProviderId)" SelectionUpdate="@this.PolicyPreselectedProviderWasChanged" ExplicitMinimumConfidence="@this.GetPolicyMinimumConfidenceLevel()"/>
|
<ConfigurationProviderSelection Component="Components.DOCUMENT_ANALYSIS_ASSISTANT" Data="@this.availableLLMProviders" Disabled="@(() => this.IsNoPolicySelectedOrProtected)" SelectedValue="@(() => this.policyPreselectedProviderId)" SelectionUpdate="@this.PolicyPreselectedProviderWasChanged" ExplicitMinimumConfidence="@this.GetPolicyMinimumConfidenceLevel()"/>
|
||||||
|
|
||||||
<ConfigurationSelect OptionDescription="@T("Preselect a profile")" Disabled="@(() => this.IsNoPolicySelected)" SelectedValue="@(() => this.policyPreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetComponentProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdateAsync="@(async selection => await this.PolicyPreselectedProfileWasChangedAsync(selection))" OptionHelp="@T("Choose whether the policy should use the app default profile, no profile, or a specific profile.")"/>
|
<ConfigurationSelect OptionDescription="@T("Preselect a profile")" Disabled="@(() => this.IsNoPolicySelected)" SelectedValue="@(() => this.policyPreselectedProfile)" Data="@ConfigurationSelectDataFactory.GetComponentProfilesData(this.SettingsManager.ConfigurationData.Profiles)" SelectionUpdate="@this.PolicyPreselectedProfileWasChanged" OptionHelp="@T("Choose whether the policy should use the app default profile, no profile, or a specific profile.")"/>
|
||||||
|
|
||||||
<MudTextSwitch Disabled="@(this.IsNoPolicySelected || (this.selectedPolicy?.IsEnterpriseConfiguration ?? true))" Label="@T("Would you like to protect this policy so that you cannot accidentally edit or delete it?")" Value="@this.policyIsProtected" ValueChanged="async state => await this.PolicyProtectionWasChanged(state)" LabelOn="@T("Yes, protect this policy")" LabelOff="@T("No, the policy can be edited")" />
|
<MudTextSwitch Disabled="@(this.IsNoPolicySelected || (this.selectedPolicy?.IsEnterpriseConfiguration ?? true))" Label="@T("Would you like to protect this policy so that you cannot accidentally edit or delete it?")" Value="@this.policyIsProtected" ValueChanged="async state => await this.PolicyProtectionWasChanged(state)" LabelOn="@T("Yes, protect this policy")" LabelOff="@T("No, the policy can be edited")" />
|
||||||
|
|
||||||
|
|||||||
+27
-8
@@ -180,6 +180,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
protected override void ResetForm()
|
protected override void ResetForm()
|
||||||
{
|
{
|
||||||
this.loadedDocumentPaths.Clear();
|
this.loadedDocumentPaths.Clear();
|
||||||
|
this.policyNameWasEdited = false;
|
||||||
if (!this.MightPreselectValues())
|
if (!this.MightPreselectValues())
|
||||||
{
|
{
|
||||||
this.policyName = string.Empty;
|
this.policyName = string.Empty;
|
||||||
@@ -220,6 +221,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
this.policyAllowedToolIds = [..this.selectedPolicy.AllowedToolIds];
|
this.policyAllowedToolIds = [..this.selectedPolicy.AllowedToolIds];
|
||||||
this.policyPreselectedProviderId = this.selectedPolicy.PreselectedProvider;
|
this.policyPreselectedProviderId = this.selectedPolicy.PreselectedProvider;
|
||||||
this.policyPreselectedProfile = ProfilePreselection.FromStoredValue(this.selectedPolicy.PreselectedProfile);
|
this.policyPreselectedProfile = ProfilePreselection.FromStoredValue(this.selectedPolicy.PreselectedProfile);
|
||||||
|
this.policyNameWasEdited = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -259,6 +261,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// The preselected profile is always user-adjustable, even for protected policies and enterprise configurations:
|
// The preselected profile is always user-adjustable, even for protected policies and enterprise configurations:
|
||||||
|
var hasChanges = this.selectedPolicy.PreselectedProfile != this.policyPreselectedProfile;
|
||||||
this.selectedPolicy.PreselectedProfile = this.policyPreselectedProfile;
|
this.selectedPolicy.PreselectedProfile = this.policyPreselectedProfile;
|
||||||
|
|
||||||
// Enterprise configurations cannot be modified at all:
|
// Enterprise configurations cannot be modified at all:
|
||||||
@@ -268,6 +271,17 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
var canEditProtectedFields = force || (!this.selectedPolicy.IsProtected && !this.policyIsProtected);
|
var canEditProtectedFields = force || (!this.selectedPolicy.IsProtected && !this.policyIsProtected);
|
||||||
if (canEditProtectedFields)
|
if (canEditProtectedFields)
|
||||||
{
|
{
|
||||||
|
hasChanges = hasChanges
|
||||||
|
|| this.policyNameWasEdited
|
||||||
|
|| this.selectedPolicy.PreselectedProvider != this.policyPreselectedProviderId
|
||||||
|
|| this.selectedPolicy.PolicyDescription != this.policyDescription
|
||||||
|
|| this.selectedPolicy.IsProtected != this.policyIsProtected
|
||||||
|
|| this.selectedPolicy.HidePolicyDefinition != this.policyHidePolicyDefinition
|
||||||
|
|| this.selectedPolicy.AnalysisRules != this.policyAnalysisRules
|
||||||
|
|| this.selectedPolicy.OutputRules != this.policyOutputRules
|
||||||
|
|| this.selectedPolicy.MinimumProviderConfidence != this.policyMinimumProviderConfidence
|
||||||
|
|| !this.selectedPolicy.AllowedToolIds.SetEquals(this.policyAllowedToolIds);
|
||||||
|
|
||||||
this.selectedPolicy.PreselectedProvider = this.policyPreselectedProviderId;
|
this.selectedPolicy.PreselectedProvider = this.policyPreselectedProviderId;
|
||||||
this.selectedPolicy.PolicyName = this.policyName;
|
this.selectedPolicy.PolicyName = this.policyName;
|
||||||
this.selectedPolicy.PolicyDescription = this.policyDescription;
|
this.selectedPolicy.PolicyDescription = this.policyDescription;
|
||||||
@@ -279,7 +293,11 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
this.selectedPolicy.AllowedToolIds = [..this.policyAllowedToolIds];
|
this.selectedPolicy.AllowedToolIds = [..this.policyAllowedToolIds];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!hasChanges)
|
||||||
|
return;
|
||||||
|
|
||||||
await this.SettingsManager.StoreSettings();
|
await this.SettingsManager.StoreSettings();
|
||||||
|
this.policyNameWasEdited = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataDocumentAnalysisPolicy? selectedPolicy;
|
private DataDocumentAnalysisPolicy? selectedPolicy;
|
||||||
@@ -298,6 +316,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
private bool documentSelectionExpanded;
|
private bool documentSelectionExpanded;
|
||||||
private string policyName = string.Empty;
|
private string policyName = string.Empty;
|
||||||
|
private bool policyNameWasEdited;
|
||||||
private string policyDescription = string.Empty;
|
private string policyDescription = string.Empty;
|
||||||
private string policyAnalysisRules = string.Empty;
|
private string policyAnalysisRules = string.Empty;
|
||||||
private string policyOutputRules = string.Empty;
|
private string policyOutputRules = string.Empty;
|
||||||
@@ -477,6 +496,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this.selectedPolicy.PolicyName = this.policyName;
|
this.selectedPolicy.PolicyName = this.policyName;
|
||||||
|
this.policyNameWasEdited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PolicyProtectionWasChanged(bool state)
|
private async Task PolicyProtectionWasChanged(bool state)
|
||||||
@@ -488,7 +508,6 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this.policyIsProtected = state;
|
this.policyIsProtected = state;
|
||||||
this.selectedPolicy.IsProtected = state;
|
|
||||||
this.policyDefinitionExpanded = !state;
|
this.policyDefinitionExpanded = !state;
|
||||||
this.documentSelectionExpanded = state;
|
this.documentSelectionExpanded = state;
|
||||||
await this.AutoSave(true);
|
await this.AutoSave(true);
|
||||||
@@ -503,7 +522,6 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this.policyHidePolicyDefinition = state;
|
this.policyHidePolicyDefinition = state;
|
||||||
this.selectedPolicy.HidePolicyDefinition = state;
|
|
||||||
await this.AutoSave(true);
|
await this.AutoSave(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,16 +598,18 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Takes over the tools this policy permits.
|
/// Takes over the tools this policy permits.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task PolicyAllowedToolsWasChangedAsync(HashSet<string> allowedToolIds)
|
private void PolicyAllowedToolsWasChanged(HashSet<string> allowedToolIds)
|
||||||
{
|
{
|
||||||
this.policyAllowedToolIds = allowedToolIds;
|
this.policyAllowedToolIds = allowedToolIds;
|
||||||
await this.AutoSave();
|
if (this.selectedPolicy is not null)
|
||||||
|
this.selectedPolicy.AllowedToolIds = [..allowedToolIds];
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PolicyMinimumConfidenceWasChangedAsync(ConfidenceLevel level)
|
private void PolicyMinimumConfidenceWasChanged(ConfidenceLevel level)
|
||||||
{
|
{
|
||||||
this.policyMinimumProviderConfidence = level;
|
this.policyMinimumProviderConfidence = level;
|
||||||
await this.AutoSave();
|
if (this.selectedPolicy is not null)
|
||||||
|
this.selectedPolicy.MinimumProviderConfidence = level;
|
||||||
|
|
||||||
this.ApplyPolicyPreselection();
|
this.ApplyPolicyPreselection();
|
||||||
}
|
}
|
||||||
@@ -605,14 +625,13 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
|||||||
this.ApplyPolicyPreselection();
|
this.ApplyPolicyPreselection();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task PolicyPreselectedProfileWasChangedAsync(ProfilePreselection selection)
|
private void PolicyPreselectedProfileWasChanged(ProfilePreselection selection)
|
||||||
{
|
{
|
||||||
this.policyPreselectedProfile = selection;
|
this.policyPreselectedProfile = selection;
|
||||||
if (this.selectedPolicy is not null)
|
if (this.selectedPolicy is not null)
|
||||||
this.selectedPolicy.PreselectedProfile = this.policyPreselectedProfile;
|
this.selectedPolicy.PreselectedProfile = this.policyPreselectedProfile;
|
||||||
|
|
||||||
this.CurrentProfile = this.ResolveProfileSelection();
|
this.CurrentProfile = this.ResolveProfileSelection();
|
||||||
await this.AutoSave();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Overrides of MSGComponentBase
|
#region Overrides of MSGComponentBase
|
||||||
|
|||||||
@@ -4213,6 +4213,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T3654011106"] = "Open P
|
|||||||
-- You can switch between your profiles here
|
-- You can switch between your profiles here
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can switch between your profiles here"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can switch between your profiles here"
|
||||||
|
|
||||||
|
-- No LLM providers meet the confidence requirements. Configure an eligible provider in the app settings.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T1220991024"] = "No LLM providers meet the confidence requirements. Configure an eligible provider in the app settings."
|
||||||
|
|
||||||
-- Audio input possible
|
-- Audio input possible
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T1742581112"] = "Audio input possible"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T1742581112"] = "Audio input possible"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
@using AIStudio.Settings
|
@using AIStudio.Settings
|
||||||
@inherits MSGComponentBase
|
@inherits MSGComponentBase
|
||||||
|
@{
|
||||||
|
var availableProviderItems = this.GetAvailableProviderSelectionItems().ToList();
|
||||||
|
}
|
||||||
<MudSelect T="Provider" Value="@this.ProviderSettings" ValueChanged="@this.SelectionChanged" Validation="@this.ValidateProvider" Margin="Margin.Dense" Label="@T("Provider")" Class="mb-3 rounded-lg" OuterClass="flex-grow-0" Variant="Variant.Outlined" Disabled="@this.Disabled">
|
<MudSelect T="Provider" Value="@this.ProviderSettings" ValueChanged="@this.SelectionChanged" Validation="@this.ValidateProvider" Margin="Margin.Dense" Label="@T("Provider")" Class="mb-3 rounded-lg" OuterClass="flex-grow-0" Variant="Variant.Outlined" Disabled="@this.Disabled">
|
||||||
@foreach (var providerItem in this.GetAvailableProviderSelectionItems())
|
@foreach (var providerItem in availableProviderItems)
|
||||||
{
|
{
|
||||||
<MudSelectItem Value="@providerItem.Provider">
|
<MudSelectItem Value="@providerItem.Provider">
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Class="w-100" Wrap="Wrap.NoWrap">
|
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Class="w-100" Wrap="Wrap.NoWrap">
|
||||||
@@ -21,3 +24,9 @@
|
|||||||
</MudSelectItem>
|
</MudSelectItem>
|
||||||
}
|
}
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
|
@if (availableProviderItems.Count is 0)
|
||||||
|
{
|
||||||
|
<MudText Typo="Typo.body2" Color="Color.Error" Class="mb-3">
|
||||||
|
@T("No LLM providers meet the confidence requirements. Configure an eligible provider in the app settings.")
|
||||||
|
</MudText>
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ public sealed class SettingsManager
|
|||||||
|
|
||||||
private readonly ILogger<SettingsManager> logger;
|
private readonly ILogger<SettingsManager> logger;
|
||||||
private readonly RustService rustService;
|
private readonly RustService rustService;
|
||||||
|
private readonly SemaphoreSlim settingsWriteSemaphore = new(1, 1);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The settings manager.
|
/// The settings manager.
|
||||||
@@ -293,6 +294,9 @@ public sealed class SettingsManager
|
|||||||
/// Stores the settings to the file system.
|
/// Stores the settings to the file system.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task StoreSettings()
|
public async Task StoreSettings()
|
||||||
|
{
|
||||||
|
await this.settingsWriteSemaphore.WaitAsync();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if(!this.IsSetUp)
|
if(!this.IsSetUp)
|
||||||
{
|
{
|
||||||
@@ -306,29 +310,41 @@ public sealed class SettingsManager
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var settingsJson = JsonSerializer.Serialize(this.ConfigurationData, JSON_OPTIONS);
|
||||||
var settingsPath = Path.Combine(ConfigDirectory!, SETTINGS_FILENAME);
|
var settingsPath = Path.Combine(ConfigDirectory!, SETTINGS_FILENAME);
|
||||||
await this.StoreSettingsSnapshot(this.ConfigurationData, settingsPath);
|
await this.StoreSettingsSnapshot(settingsJson, settingsPath);
|
||||||
await this.StoreCurrentVersionBackup(this.ConfigurationData);
|
await this.StoreCurrentVersionBackup(this.ConfigurationData.Version, settingsJson);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.settingsWriteSemaphore.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetBackupSettingsFilename(Version version) => $"settings.{version.ToString().ToLowerInvariant()}.json";
|
private static string GetBackupSettingsFilename(Version version) => $"settings.{version.ToString().ToLowerInvariant()}.json";
|
||||||
|
|
||||||
private static string GetBackupSettingsPath(Version version) => Path.Combine(ConfigDirectory!, GetBackupSettingsFilename(version));
|
private static string GetBackupSettingsPath(Version version) => Path.Combine(ConfigDirectory!, GetBackupSettingsFilename(version));
|
||||||
|
|
||||||
private async Task StoreCurrentVersionBackup(Data settingsData)
|
private Task StoreCurrentVersionBackup(Data settingsData) =>
|
||||||
|
this.StoreCurrentVersionBackup(settingsData.Version, JsonSerializer.Serialize(settingsData, JSON_OPTIONS));
|
||||||
|
|
||||||
|
private async Task StoreCurrentVersionBackup(Version settingsVersion, string settingsJson)
|
||||||
{
|
{
|
||||||
if(settingsData.Version != CURRENT_SETTINGS_VERSION)
|
if(settingsVersion != CURRENT_SETTINGS_VERSION)
|
||||||
{
|
{
|
||||||
this.logger.LogWarning($"Skipping settings backup because the settings version '{settingsData.Version}' is not the current version '{CURRENT_SETTINGS_VERSION}'.");
|
this.logger.LogWarning($"Skipping settings backup because the settings version '{settingsVersion}' is not the current version '{CURRENT_SETTINGS_VERSION}'.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var backupSettingsPath = GetBackupSettingsPath(CURRENT_SETTINGS_VERSION);
|
var backupSettingsPath = GetBackupSettingsPath(CURRENT_SETTINGS_VERSION);
|
||||||
await this.StoreSettingsSnapshot(settingsData, backupSettingsPath);
|
await this.StoreSettingsSnapshot(settingsJson, backupSettingsPath);
|
||||||
this.logger.LogInformation($"Stored the settings backup file '{backupSettingsPath}'.");
|
this.logger.LogInformation($"Stored the settings backup file '{backupSettingsPath}'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StoreSettingsSnapshot(Data settingsData, string settingsPath)
|
private Task StoreSettingsSnapshot(Data settingsData, string settingsPath) =>
|
||||||
|
this.StoreSettingsSnapshot(JsonSerializer.Serialize(settingsData, JSON_OPTIONS), settingsPath);
|
||||||
|
|
||||||
|
private async Task StoreSettingsSnapshot(string settingsJson, string settingsPath)
|
||||||
{
|
{
|
||||||
if(!Directory.Exists(ConfigDirectory))
|
if(!Directory.Exists(ConfigDirectory))
|
||||||
{
|
{
|
||||||
@@ -336,8 +352,6 @@ public sealed class SettingsManager
|
|||||||
Directory.CreateDirectory(ConfigDirectory!);
|
Directory.CreateDirectory(ConfigDirectory!);
|
||||||
}
|
}
|
||||||
|
|
||||||
var settingsJson = JsonSerializer.Serialize(settingsData, JSON_OPTIONS);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// We write the new settings next to the previous ones and replace them afterwards, so that
|
// We write the new settings next to the previous ones and replace them afterwards, so that
|
||||||
// no crash can leave a half-written settings file behind. The temporary file has to live in
|
// no crash can leave a half-written settings file behind. The temporary file has to live in
|
||||||
@@ -349,7 +363,7 @@ public sealed class SettingsManager
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await File.WriteAllTextAsync(tempFile, settingsJson);
|
await File.WriteAllTextAsync(tempFile, settingsJson);
|
||||||
File.Move(tempFile, settingsPath, true);
|
await Task.Run(() => File.Move(tempFile, settingsPath, true));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
- Improved the list of your attached files: every file now appears under the folder it came from, and each folder is named only once, no matter in which order you attached your files.
|
- Improved the list of your attached files: every file now appears under the folder it came from, and each folder is named only once, no matter in which order you attached your files.
|
||||||
- Changed how provider trust and provider confidence work together. Marking a provider as trustworthy in a configuration no longer also satisfies a required confidence level: one says who runs the provider, the other how confidential it is. Organizations raise a provider's level in their own confidence scheme instead. This applies beyond local data sources, for example, when a model reads a page from your intranet.
|
- Changed how provider trust and provider confidence work together. Marking a provider as trustworthy in a configuration no longer also satisfies a required confidence level: one says who runs the provider, the other how confidential it is. Organizations raise a provider's level in their own confidence scheme instead. This applies beyond local data sources, for example, when a model reads a page from your intranet.
|
||||||
- Fixed the abilities AI Studio assumed for many models. We checked the families against their documentation: some models gained image input, reasoning, or tool calling, others lost an ability they never had.
|
- Fixed the abilities AI Studio assumed for many models. We checked the families against their documentation: some models gained image input, reasoning, or tool calling, others lost an ability they never had.
|
||||||
|
- Fixed the Document Analysis assistant becoming unresponsive when choosing an LLM provider.
|
||||||
- Fixed model names that a provider writes in its own way not being recognized at all, such as the colon Ollama puts before the variant. Those models were treated as plain text models and lost every other ability.
|
- Fixed model names that a provider writes in its own way not being recognized at all, such as the colon Ollama puts before the variant. Those models were treated as plain text models and lost every other ability.
|
||||||
- Fixed a model resold under a plain name not getting the abilities it really has.
|
- Fixed a model resold under a plain name not getting the abilities it really has.
|
||||||
- Fixed image and video generation models showing up among the chat models.
|
- Fixed image and video generation models showing up among the chat models.
|
||||||
|
|||||||
Reference in new issue
Block a user