From 7f389fa3532cd12c031fe86479d3da047066bff3 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 14:48:31 +0200 Subject: [PATCH 01/11] Add tool configuration export infrastructure --- .../ToolCallingSystem/ExportableSettings.cs | 9 ++ .../ToolCallingSystem/IToolImplementation.cs | 23 +++ .../ToolSettingsExportMode.cs | 7 + .../ToolSettingsExportOptions.cs | 15 ++ .../ToolSettingsExportResult.cs | 9 ++ .../ToolSettingsService.Export.cs | 132 ++++++++++++++++++ .../ToolCallingSystem/ToolSettingsService.cs | 2 +- 7 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 app/MindWork AI Studio/Tools/ToolCallingSystem/ExportableSettings.cs create mode 100644 app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportMode.cs create mode 100644 app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportOptions.cs create mode 100644 app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportResult.cs create mode 100644 app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ExportableSettings.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ExportableSettings.cs new file mode 100644 index 000000000..921f8f314 --- /dev/null +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ExportableSettings.cs @@ -0,0 +1,9 @@ +namespace AIStudio.Tools.ToolCallingSystem; + +/// +/// One independently selectable area of a tool's configuration export. +/// +/// A stable ID, independent of the translated label. The empty ID denotes ungrouped settings. +/// The translated name shown to the administrator. +/// Settings schema field names, without the tool ID prefix. +public sealed record ExportableSettings(string Id, string Label, IReadOnlyList FieldNames); \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/IToolImplementation.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/IToolImplementation.cs index 2a4ff3349..16f5990fe 100644 --- a/app/MindWork AI Studio/Tools/ToolCallingSystem/IToolImplementation.cs +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/IToolImplementation.cs @@ -64,6 +64,29 @@ public string GetSettingsFieldDescription(string fieldName, ToolSettingsFieldDef /// public IReadOnlyList GetSettingsGroupLinks(string groupKey) => []; + /// + /// Independently selectable areas of this tool's configuration export. + /// + /// + /// By default, each settings group is one area, including an area for ungrouped fields. + /// Override this when the export needs a different partition. IDs must be unique and stable; + /// labels must be translated. Areas contain schema field names, never values or secrets. + /// Selecting an area does not implicitly include general settings or other areas, and a + /// field hidden in the settings dialog is still exportable. + /// + public IReadOnlyList GetExportableSettings(ToolDefinition definition) => definition.SettingsSchema.Properties + .GroupBy(property => property.Value.Group, StringComparer.Ordinal) + .Select(group => + { + var label = this.GetSettingsGroupLabel(group.Key); + return new ExportableSettings( + group.Key, + string.IsNullOrEmpty(label) ? TB("General") : label, + group.Select(property => property.Key).ToList() + ); + }) + .ToList(); + /// /// Whether one settings field is worth showing, given what is filled in at the moment. /// diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportMode.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportMode.cs new file mode 100644 index 000000000..a5fe8e15d --- /dev/null +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportMode.cs @@ -0,0 +1,7 @@ +namespace AIStudio.Tools.ToolCallingSystem; + +public enum ToolSettingsExportMode +{ + LOCKED, + DEFAULT, +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportOptions.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportOptions.cs new file mode 100644 index 000000000..e635d74d3 --- /dev/null +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportOptions.cs @@ -0,0 +1,15 @@ +namespace AIStudio.Tools.ToolCallingSystem; + +/// +/// The administrator's choices for one export. The dialog initially selects every available area. +/// +public sealed record ToolSettingsExportOptions +{ + public IReadOnlySet SelectedAreaIds { get; init; } = new HashSet(StringComparer.Ordinal); + + public ToolSettingsExportMode Mode { get; init; } = ToolSettingsExportMode.LOCKED; + + public bool IncludeSecrets { get; init; } + + public bool IncludeMinimumProviderConfidence { get; init; } = true; +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportResult.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportResult.cs new file mode 100644 index 000000000..d7cb882dd --- /dev/null +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportResult.cs @@ -0,0 +1,9 @@ +namespace AIStudio.Tools.ToolCallingSystem; + +/// +/// Lua to copy, or an explanation of why the export failed. An empty successful export has nothing to copy. +/// +public sealed record ToolSettingsExportResult(string LuaCode = "", string ErrorMessage = "") +{ + public bool Success => string.IsNullOrEmpty(this.ErrorMessage); +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs new file mode 100644 index 000000000..d5c0c7041 --- /dev/null +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs @@ -0,0 +1,132 @@ +using System.Text; + +using AIStudio.Provider; +using AIStudio.Tools.PluginSystem; + +using SharedTools; + +namespace AIStudio.Tools.ToolCallingSystem; + +public sealed partial class ToolSettingsService +{ + private const string LOCKED_SETTINGS = "DataTools.LockedToolSettings"; + private const string DEFAULT_SETTINGS = "DataTools.DefaultToolSettings"; + private const string MINIMUM_CONFIDENCE = "DataTools.MinimumProviderConfidenceByToolId"; + + private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ToolSettingsService).Namespace, nameof(ToolSettingsService)); + + /// + /// Reads the saved, effective configuration and exports the selected areas. Incomplete tools + /// may be exported too: administrators can finish the configuration in their Lua plugin. + /// + /// + /// Uses the same organization overrides and keyring values as tool execution, without saving + /// settings or writing to the keyring. The caller provides the admin-only UI and copies a + /// successful, nonempty result to the clipboard.

+ /// Only explicitly selected areas are included. Missing values stay absent, explicitly empty + /// non-secret values stay empty, and runtime defaults are not filled in. Secrets require + /// opt-in and enterprise encryption, and are always locked, even in a default-value export. + /// The optional minimum provider confidence is also always a fixed requirement. + ///
+ public async Task ExportAsync(ToolDefinition definition, IToolImplementation implementation, ToolSettingsExportOptions options) + { + var areas = implementation.GetExportableSettings(definition); + var values = await this.GetSettingsAsync(definition); + var confidence = settingsManager.GetMinimumProviderConfidenceForTool(definition.Id, definition.MinimumProviderConfidence); + return BuildConfigurationSection(definition, areas, values, options, confidence, PluginFactory.EnterpriseEncryption); + } + + /// + /// Resolves selected areas to known fields in schema order. Overlapping areas include a + /// field only once; unknown field names are ignored. Form visibility does not limit exports. + /// + private static IReadOnlyList GetSelectedFieldNames(ToolDefinition definition, IReadOnlyList areas, IReadOnlySet selectedAreaIds) + { + var selectedIds = new HashSet(selectedAreaIds, StringComparer.Ordinal); + var selectedFields = areas.Where(area => selectedIds.Contains(area.Id)) + .SelectMany(area => area.FieldNames) + .ToHashSet(StringComparer.Ordinal); + + return definition.SettingsSchema.Properties.Keys.Where(selectedFields.Contains).ToList(); + } + + /// + /// Builds a fragment from one snapshot. A failed encryption returns no Lua, even when other + /// fields have already been processed, so the caller cannot copy a partial export by accident. + /// + private static ToolSettingsExportResult BuildConfigurationSection(ToolDefinition definition, IReadOnlyList areas, IReadOnlyDictionary values, + ToolSettingsExportOptions options, ConfidenceLevel minimumProviderConfidence, EnterpriseEncryption? encryption) + { + if (!Enum.IsDefined(options.Mode)) + return new(ErrorMessage: TB("The selected tool configuration export mode is invalid.")); + + var lockedValues = new Dictionary(StringComparer.Ordinal); + var defaultValues = new Dictionary(StringComparer.Ordinal); + foreach (var fieldName in GetSelectedFieldNames(definition, areas, options.SelectedAreaIds)) + { + if (!values.TryGetValue(fieldName, out var value)) + continue; + + var key = ManagedSettingKey(definition.Id, fieldName); + if (definition.SettingsSchema.Properties[fieldName].Secret) + { + if (!options.IncludeSecrets || string.IsNullOrWhiteSpace(value)) + continue; + + if (encryption?.IsAvailable is not true) + return new(ErrorMessage: TB("Cannot export encrypted tool secrets: No enterprise encryption secret is configured.")); + + if (!encryption.TryEncrypt(value, out var encrypted)) + return new(ErrorMessage: TB("The tool secrets could not be encrypted. Nothing was exported.")); + + lockedValues[key] = encrypted; + } + else if (options.Mode is ToolSettingsExportMode.LOCKED) + lockedValues[key] = value; + else + defaultValues[key] = value; + } + + if (lockedValues.Count is 0 && defaultValues.Count is 0 && !options.IncludeMinimumProviderConfidence) + return new(); + + if (options.IncludeMinimumProviderConfidence && (!Enum.IsDefined(minimumProviderConfidence) || minimumProviderConfidence is ConfidenceLevel.UNKNOWN)) + return new(ErrorMessage: TB("The tool's minimum provider confidence level is invalid.")); + + var lua = new StringBuilder(); + lua.AppendLine("CONFIG = CONFIG or {}"); + lua.AppendLine("CONFIG[\"SETTINGS\"] = CONFIG[\"SETTINGS\"] or {}"); + AppendSettings(lua, LOCKED_SETTINGS, lockedValues); + AppendSettings(lua, DEFAULT_SETTINGS, defaultValues); + + if (options.IncludeMinimumProviderConfidence) + { + AppendSettings(lua, MINIMUM_CONFIDENCE, new Dictionary(StringComparer.Ordinal) + { + [definition.Id] = minimumProviderConfidence.ToString(), + }); + + // The existing plugin contract locks the entire confidence dictionary, not one entry: + lua.AppendLine($"CONFIG[\"SETTINGS\"][\"{MINIMUM_CONFIDENCE}.AllowUserOverride\"] = false"); + } + + return new(LuaCode: lua.ToString()); + } + + /// + /// Adds entries without replacing the table, so administrators can combine export fragments + /// in one plugin. Later assignments to the same key win. This does not merge dictionaries + /// across separate configuration plugins; those still follow managed-setting precedence. + /// + private static void AppendSettings(StringBuilder lua, string settingName, IReadOnlyDictionary values) + { + if (values.Count is 0) + return; + + var table = $"CONFIG[\"SETTINGS\"][\"{settingName}\"]"; + lua.AppendLine(); + lua.AppendLine($"{table} = {table} or {{}}"); + foreach (var (key, value) in values) + lua.AppendLine($"{table}[\"{LuaTools.EscapeLuaString(key)}\"] = \"{LuaTools.EscapeLuaString(value)}\""); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.cs index c05f1138b..875e88618 100644 --- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.cs +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.cs @@ -4,7 +4,7 @@ namespace AIStudio.Tools.ToolCallingSystem; -public sealed class ToolSettingsService(SettingsManager settingsManager, RustService rustService, ILogger logger) +public sealed partial class ToolSettingsService(SettingsManager settingsManager, RustService rustService, ILogger logger) { /// /// Builds the key under which an organization's configuration addresses one tool setting. From be2ca7748c5fa9868252ba20cbcbe649a298cdc7 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 15:04:50 +0200 Subject: [PATCH 02/11] Add admin dialog for tool configuration exports --- .../Assistants/I18N/allTexts.lua | 90 +++++++++ .../Settings/SettingsPanelTools.razor | 6 + .../Settings/SettingsPanelTools.razor.cs | 13 ++ .../Settings/ToolSettingsExportDialog.razor | 90 +++++++++ .../ToolSettingsExportDialog.razor.cs | 172 ++++++++++++++++++ .../ToolCallingSystem/ToolSettingsService.cs | 2 +- 6 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor create mode 100644 app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index a4774f3a7..e57378f42 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -4720,6 +4720,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3794167684 -- Status UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T6222351"] = "Status" +-- Export configuration +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T975426229"] = "Export configuration" + -- No transcription provider configured yet. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "No transcription provider configured yet." @@ -8218,6 +8221,78 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T403490413"] = -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T900713019"] = "Cancel" +-- The tool configuration could not be exported. Please try again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1064444653"] = "The tool configuration could not be exported. Please try again." + +-- Secrets are always exported as fixed settings. Recipients need the same enterprise encryption secret to use them. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1201799760"] = "Secrets are always exported as fixed settings. Recipients need the same enterprise encryption secret to use them." + +-- The selected areas contain no configured API keys or other secrets. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1362677286"] = "The selected areas contain no configured API keys or other secrets." + +-- This is always a fixed requirement for the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1477753889"] = "This is always a fixed requirement for the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table." + +-- Loading tool configuration... +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1750745869"] = "Loading tool configuration..." + +-- Select all +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1794248818"] = "Select all" + +-- Include minimum provider confidence +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1823629028"] = "Include minimum provider confidence" + +-- The selected areas contain no settings to export. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T197560416"] = "The selected areas contain no settings to export." + +-- Include encrypted API keys and other secrets +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1978141571"] = "Include encrypted API keys and other secrets" + +-- Settings to include +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2051465617"] = "Settings to include" + +-- Editable defaults +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2389486789"] = "Editable defaults" + +-- No minimum confidence level chosen +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2828607242"] = "No minimum confidence level chosen" + +-- The tool configuration could not be loaded. Please close this dialog and try again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3388093684"] = "The tool configuration could not be loaded. Please close this dialog and try again." + +-- Export tool configuration +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3758205437"] = "Export tool configuration" + +-- Export mode +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3810275878"] = "Export mode" + +-- The selected tool could not be loaded. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3907843187"] = "The selected tool could not be loaded." + +-- Each area is independent. Select general settings separately if you want to include them. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3911375461"] = "Each area is independent. Select general settings separately if you want to include them." + +-- This choice applies to settings other than secrets and the minimum provider confidence. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T4236004495"] = "This choice applies to settings other than secrets and the minimum provider confidence." + +-- Fixed settings +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T445289446"] = "Fixed settings" + +-- Export to clipboard +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T508399334"] = "Export to clipboard" + +-- No enterprise encryption secret is configured. API keys and other secrets cannot be exported. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T633982489"] = "No enterprise encryption secret is configured. API keys and other secrets cannot be exported." + +-- Export saved settings as Lua code for your configuration plugin. You can combine exports and adapt the code before deploying it. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T744840132"] = "Export saved settings as Lua code for your configuration plugin. You can combine exports and adapt the code before deploying it." + +-- Cancel +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T900713019"] = "Cancel" + +-- Current requirement: {0} +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T982466527"] = "Current requirement: {0}" + -- Save UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SHORTCUTDIALOG::T1294818664"] = "Save" @@ -11416,6 +11491,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::HARNESS::TOOLCALLINGMESSAGE -- The tool calling request failed with status code {0}. See the logs for details. UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::HARNESS::TOOLCALLINGMESSAGES::T3117779001"] = "The tool calling request failed with status code {0}. See the logs for details." +-- General +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::ITOOLIMPLEMENTATION::T1432485131"] = "General" + -- Tool UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::ITOOLIMPLEMENTATION::T3517012711"] = "Tool" @@ -11674,6 +11752,18 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES:: -- Any language UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T747012729"] = "Any language" +-- The selected tool configuration export mode is invalid. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T1327976665"] = "The selected tool configuration export mode is invalid." + +-- The tool's minimum provider confidence level is invalid. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T2093219126"] = "The tool's minimum provider confidence level is invalid." + +-- Cannot export encrypted tool secrets: No enterprise encryption secret is configured. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T3174877792"] = "Cannot export encrypted tool secrets: No enterprise encryption secret is configured." + +-- The tool secrets could not be encrypted. Nothing was exported. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T403101133"] = "The tool secrets could not be encrypted. Nothing was exported." + -- The file path is null or empty and the file therefore can not be loaded. UI_TEXT_CONTENT["AISTUDIO::TOOLS::USERFILE::T932243993"] = "The file path is null or empty and the file therefore can not be loaded." diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor index 88e91bf77..13d03d6f1 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor @@ -54,6 +54,12 @@ + @if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) + { + + + + } diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor.cs index 1fb0d667f..32850033b 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor.cs @@ -34,6 +34,19 @@ private async Task OpenSettings(string toolId) this.StateHasChanged(); } + private async Task OpenExport(string toolId) + { + if (!this.SettingsManager.ConfigurationData.App.ShowAdminSettings) + return; + + var parameters = new DialogParameters + { + { x => x.ToolId, toolId }, + }; + + await this.DialogService.ShowAsync(null, parameters, Dialogs.DialogOptions.FULLSCREEN); + } + private string GetConfigurationTooltip(ToolCatalogItem item) => item.ConfigurationState.MissingRequiredFields.Count switch { _ when !string.IsNullOrWhiteSpace(item.ConfigurationState.Message) => item.ConfigurationState.Message, diff --git a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor new file mode 100644 index 000000000..7c1d36775 --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor @@ -0,0 +1,90 @@ +@using AIStudio.Tools.ToolCallingSystem +@using AIStudio.Tools.PluginSystem +@inherits SettingsDialogBase + + + + + + @T("Export tool configuration") + + + + @if (this.IsAdmin) + { + @if (!string.IsNullOrWhiteSpace(this.message)) + { + @this.message + } + + @if (this.isLoading) + { + + @T("Loading tool configuration...") + } + else if (this.toolDefinition is null || this.implementation is null) + { + @if (string.IsNullOrWhiteSpace(this.message)) + { + @T("The selected tool could not be loaded.") + } + } + else + { + @this.implementation.GetDisplayName() + + @T("Export saved settings as Lua code for your configuration plugin. You can combine exports and adapt the code before deploying it.") + + + @if (this.areas.Count > 0) + { + + @T("Settings to include") + @if (this.areas.Count > 1) + { + + } + @foreach (var area in this.areas) + { + + } + @T("Each area is independent. Select general settings separately if you want to include them.") + + } + + + @T("Fixed settings") + @T("Editable defaults") + + + + + @if (PluginFactory.EnterpriseEncryption?.IsAvailable is not true) + { + @T("No enterprise encryption secret is configured. API keys and other secrets cannot be exported.") + } + else if (!this.HasSelectedSecrets) + { + @T("The selected areas contain no configured API keys or other secrets.") + } + else + { + @T("Secrets are always exported as fixed settings. Recipients need the same enterprise encryption secret to use them.") + } + + + + + @string.Format(T("Current requirement: {0}"), this.GetMinimumProviderConfidenceName()) + @T("This is always a fixed requirement for the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table.") + + } + } + + + @T("Cancel") + + @T("Export to clipboard") + + + \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs new file mode 100644 index 000000000..38e10eabd --- /dev/null +++ b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs @@ -0,0 +1,172 @@ +using AIStudio.Provider; +using AIStudio.Tools.PluginSystem; +using AIStudio.Tools.ToolCallingSystem; + +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Dialogs.Settings; + +public partial class ToolSettingsExportDialog : SettingsDialogBase +{ + [Parameter] + public string ToolId { get; set; } = string.Empty; + + [Inject] + private ToolRegistry ToolRegistry { get; init; } = null!; + + [Inject] + private ToolSettingsService ToolSettingsService { get; init; } = null!; + + private ToolDefinition? toolDefinition; + private IToolImplementation? implementation; + private IReadOnlyList areas = []; + private HashSet selectedAreaIds = new(StringComparer.Ordinal); + private HashSet configuredSecretFields = new(StringComparer.Ordinal); + private ToolSettingsExportMode mode = ToolSettingsExportMode.LOCKED; + private bool includeSecrets; + private bool includeMinimumProviderConfidence = true; + private bool isLoading = true; + private bool isExporting; + private bool isDisposed; + private string message = string.Empty; + private Severity messageSeverity = Severity.Error; + + private bool IsAdmin => this.SettingsManager.ConfigurationData.App.ShowAdminSettings; + + private bool AllAreasSelected => this.areas.Count > 0 && this.areas.All(area => this.selectedAreaIds.Contains(area.Id)); + + private bool HasSelectedSecrets => this.areas.Any(area => this.selectedAreaIds.Contains(area.Id) && area.FieldNames.Any(this.configuredSecretFields.Contains)); + + private bool CanIncludeSecrets => this.HasSelectedSecrets && PluginFactory.EnterpriseEncryption?.IsAvailable is true; + + private bool CanExport => this.IsAdmin && !this.isLoading && !this.isExporting && !this.isDisposed && + this.toolDefinition is not null && this.implementation is not null && (this.selectedAreaIds.Count > 0 || this.includeMinimumProviderConfidence); + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + if (!this.IsAdmin) + { + this.Close(); + return; + } + + try + { + this.toolDefinition = this.ToolRegistry.GetDefinition(this.ToolId); + if (this.toolDefinition is null) + return; + + this.implementation = this.ToolRegistry.GetImplementation(this.toolDefinition.ImplementationKey); + if (this.implementation is null) + return; + + this.areas = this.implementation.GetExportableSettings(this.toolDefinition); + this.selectedAreaIds = this.areas.Select(area => area.Id).ToHashSet(StringComparer.Ordinal); + + // Retain only the names of configured secret fields, not their plaintext values. + // ExportAsync reads effective settings again when the administrator exports. + var values = await this.ToolSettingsService.GetSettingsAsync(this.toolDefinition); + this.configuredSecretFields = this.toolDefinition.SettingsSchema.Properties + .Where(property => property.Value.Secret && values.TryGetValue(property.Key, out var value) && !string.IsNullOrWhiteSpace(value)) + .Select(property => property.Key) + .ToHashSet(StringComparer.Ordinal); + } + catch (Exception) + { + // A runtime error may contain secret data, so never display the exception text. + this.toolDefinition = null; + this.message = T("The tool configuration could not be loaded. Please close this dialog and try again."); + } + finally + { + this.isLoading = false; + } + } + + private void SelectArea(string areaId, bool selected) + { + if (selected) + this.selectedAreaIds.Add(areaId); + else + this.selectedAreaIds.Remove(areaId); + + this.SelectionChanged(); + } + + private void SelectAllAreas(bool selected) + { + this.selectedAreaIds = selected ? this.areas.Select(area => area.Id).ToHashSet(StringComparer.Ordinal) : new(StringComparer.Ordinal); + this.SelectionChanged(); + } + + private void SelectionChanged() + { + // A new selection must not keep an invisible opt-in to secrets it no longer contains. + if (!this.CanIncludeSecrets) + this.includeSecrets = false; + + this.message = string.Empty; + } + + private string GetMinimumProviderConfidenceName() + { + var confidence = this.toolDefinition is null ? ConfidenceLevel.NONE : this.ToolRegistry.GetMinimumProviderConfidence(this.toolDefinition); + return confidence is ConfidenceLevel.NONE ? T("No minimum confidence level chosen") : confidence.GetName(); + } + + private async Task Export() + { + if (!this.CanExport || this.toolDefinition is null || this.implementation is null) + return; + + this.isExporting = true; + this.message = string.Empty; + this.messageSeverity = Severity.Error; + try + { + var options = new ToolSettingsExportOptions + { + SelectedAreaIds = new HashSet(this.selectedAreaIds, StringComparer.Ordinal), + Mode = this.mode, + IncludeSecrets = this.includeSecrets, + IncludeMinimumProviderConfidence = this.includeMinimumProviderConfidence, + }; + + var result = await this.ToolSettingsService.ExportAsync(this.toolDefinition, this.implementation, options); + if (this.isDisposed || !this.IsAdmin) + return; + + if (!result.Success) + { + this.message = result.ErrorMessage; + return; + } + + if (string.IsNullOrWhiteSpace(result.LuaCode)) + { + this.messageSeverity = Severity.Info; + this.message = T("The selected areas contain no settings to export."); + return; + } + + // The runtime reports clipboard success or failure. Keep the dialog open so that + // administrators can retry or export another selection from the same tool. + await this.RustService.CopyText2Clipboard(result.LuaCode); + } + catch (Exception) + { + this.message = T("The tool configuration could not be exported. Please try again."); + } + finally + { + this.isExporting = false; + } + } + + protected override void DisposeResources() + { + this.isDisposed = true; + base.DisposeResources(); + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.cs index 875e88618..f58e3a649 100644 --- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.cs +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.cs @@ -202,4 +202,4 @@ private bool TryDecryptManagedSecret(string toolId, string fieldName, string? en secret = decryptedSecret; return true; } -} +} \ No newline at end of file From 677ba8072623b16da7af27d29ca069d7bce225d9 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 15:47:54 +0200 Subject: [PATCH 03/11] Unify admin export buttons and refine tool exports --- .../Assistants/I18N/allTexts.lua | 21 ++--------- .../Components/AdminExportButton.razor | 8 +++++ .../Components/AdminExportButton.razor.cs | 35 +++++++++++++++++++ .../Settings/SettingsPanelEmbeddings.razor | 7 +--- .../Settings/SettingsPanelProviders.razor | 7 +--- .../Settings/SettingsPanelTools.razor | 11 +++--- .../Settings/SettingsPanelTranscription.razor | 7 +--- .../Settings/SettingsDialogChatTemplate.razor | 35 ++++++++----------- .../Settings/SettingsDialogDataSources.razor | 6 ++-- .../Settings/SettingsDialogProfiles.razor | 13 +++---- .../ToolSettingsService.Export.cs | 5 ++- 11 files changed, 77 insertions(+), 78 deletions(-) create mode 100644 app/MindWork AI Studio/Components/AdminExportButton.razor create mode 100644 app/MindWork AI Studio/Components/AdminExportButton.razor.cs diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index e57378f42..4b7edcd79 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -3334,6 +3334,9 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T3219823625"] = "The lo -- The image at the URL is too large (>10 MB). Skipping the image. UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T349928509"] = "The image at the URL is too large (>10 MB). Skipping the image." +-- Export configuration +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ADMINEXPORTBUTTON::T975426229"] = "Export configuration" + -- Open Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Settings" @@ -4606,9 +4609,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T80509 -- Example text to embed UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T816748904"] = "Example text to embed" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T975426229"] = "Export configuration" - -- Cannot export the encrypted API key: No enterprise encryption secret is configured. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T1832230847"] = "Cannot export the encrypted API key: No enterprise encryption secret is configured." @@ -4681,9 +4681,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T579100 -- Open Dashboard UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T78223861"] = "Open Dashboard" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T975426229"] = "Export configuration" - -- Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T1258653480"] = "Settings" @@ -4720,9 +4717,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3794167684 -- Status UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T6222351"] = "Status" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T975426229"] = "Export configuration" - -- No transcription provider configured yet. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T1079350363"] = "No transcription provider configured yet." @@ -4783,9 +4777,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T78 -- Are you sure you want to delete the transcription provider '{0}'? UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T789660305"] = "Are you sure you want to delete the transcription provider '{0}'?" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T975426229"] = "Export configuration" - -- Copy {0} to the clipboard UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Copy {0} to the clipboard" @@ -7465,9 +7456,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T782820 -- Local Directory UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T975426229"] = "Export configuration" - -- When enabled, you can preselect some ERI server options. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options." @@ -7759,9 +7747,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T55364659" -- Are you a project manager in a research facility? You might want to create a profile for your project management activities, one for your scientific work, and a profile for when you need to write program code. In these profiles, you can record how much experience you have or which methods you like or dislike using. Later, you can choose when and where you want to use each profile. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T56359901"] = "Are you a project manager in a research facility? You might want to create a profile for your project management activities, one for your scientific work, and a profile for when you need to write program code. In these profiles, you can record how much experience you have or which methods you like or dislike using. Later, you can choose when and where you want to use each profile." --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T975426229"] = "Export configuration" - -- Preselect the target language UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T1417990312"] = "Preselect the target language" diff --git a/app/MindWork AI Studio/Components/AdminExportButton.razor b/app/MindWork AI Studio/Components/AdminExportButton.razor new file mode 100644 index 000000000..6087b5e0a --- /dev/null +++ b/app/MindWork AI Studio/Components/AdminExportButton.razor @@ -0,0 +1,8 @@ +@inherits MSGComponentBase + +@if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) +{ + + + +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/AdminExportButton.razor.cs b/app/MindWork AI Studio/Components/AdminExportButton.razor.cs new file mode 100644 index 000000000..b44914893 --- /dev/null +++ b/app/MindWork AI Studio/Components/AdminExportButton.razor.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components; + +/// +/// The common admin-only configuration export action. Callers decide what is exported. +/// +public partial class AdminExportButton : MSGComponentBase +{ + [Parameter] + public EventCallback OnClick { get; set; } + + [Parameter] + public Variant Variant { get; set; } = Variant.Text; + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + this.ApplyFilters([], [ Event.CONFIGURATION_CHANGED ]); + } + + private async Task Export() + { + if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) + await this.OnClick.InvokeAsync(); + } + + protected override Task ProcessIncomingMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default + { + if (triggeredEvent is Event.CONFIGURATION_CHANGED) + this.StateHasChanged(); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor index 1de2dd17d..8fb93f73f 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelEmbeddings.razor @@ -73,12 +73,7 @@ - @if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) - { - - - - } + diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor index 595047302..26383ee2c 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviders.razor @@ -61,12 +61,7 @@ - @if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) - { - - - - } + diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor index 13d03d6f1..fc1c0e32d 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelTools.razor @@ -53,13 +53,12 @@ } - - @if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) - { - - + + + - } + + diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor index b0d51e9a9..67fbf7676 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelTranscription.razor @@ -66,12 +66,7 @@ - @if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) - { - - - - } + diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor index 694834936..305f25e54 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor @@ -48,27 +48,22 @@ - @if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) + @if (context.FileAttachments.Count == 0) { - @if (context.FileAttachments.Count == 0) - { - - - - } - else - { - - - - @T("Use shared attachment paths") - - - @T("Copy attachments into plugin") - - - - } + + } + else if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) + { + + + + @T("Use shared attachment paths") + + + @T("Copy attachments into plugin") + + + } diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor index 7755044d6..125759664 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor @@ -49,11 +49,9 @@ @T("Edit") - @if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings && context is DataSourceERI_V1) + @if (context is DataSourceERI_V1) { - - - + } @T("Delete") diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor index 1af4253ce..f84a170b4 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor @@ -37,7 +37,7 @@ - + } @@ -45,16 +45,11 @@ { - + - @if (this.SettingsManager.ConfigurationData.App.ShowAdminSettings) - { - - - - } + - + } diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs index d5c0c7041..d90cb5f68 100644 --- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs @@ -94,8 +94,6 @@ private static ToolSettingsExportResult BuildConfigurationSection(ToolDefinition return new(ErrorMessage: TB("The tool's minimum provider confidence level is invalid.")); var lua = new StringBuilder(); - lua.AppendLine("CONFIG = CONFIG or {}"); - lua.AppendLine("CONFIG[\"SETTINGS\"] = CONFIG[\"SETTINGS\"] or {}"); AppendSettings(lua, LOCKED_SETTINGS, lockedValues); AppendSettings(lua, DEFAULT_SETTINGS, defaultValues); @@ -124,7 +122,8 @@ private static void AppendSettings(StringBuilder lua, string settingName, IReadO return; var table = $"CONFIG[\"SETTINGS\"][\"{settingName}\"]"; - lua.AppendLine(); + if (lua.Length > 0) + lua.AppendLine(); lua.AppendLine($"{table} = {table} or {{}}"); foreach (var (key, value) in values) lua.AppendLine($"{table}[\"{LuaTools.EscapeLuaString(key)}\"] = \"{LuaTools.EscapeLuaString(value)}\""); From b96d441352c00f77b55310384b327eaf95fb533b Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 16:09:20 +0200 Subject: [PATCH 04/11] Updated I18N --- .../Assistants/I18N/allTexts.lua | 18 +-- .../Settings/ToolSettingsExportDialog.razor | 6 +- .../plugin.lua | 109 +++++++++++++++--- .../plugin.lua | 105 ++++++++++++++--- 4 files changed, 194 insertions(+), 44 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 4b7edcd79..29540822c 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -8209,15 +8209,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T900713019"] = -- The tool configuration could not be exported. Please try again. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1064444653"] = "The tool configuration could not be exported. Please try again." --- Secrets are always exported as fixed settings. Recipients need the same enterprise encryption secret to use them. -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1201799760"] = "Secrets are always exported as fixed settings. Recipients need the same enterprise encryption secret to use them." - -- The selected areas contain no configured API keys or other secrets. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1362677286"] = "The selected areas contain no configured API keys or other secrets." --- This is always a fixed requirement for the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table. -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1477753889"] = "This is always a fixed requirement for the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table." - -- Loading tool configuration... UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1750745869"] = "Loading tool configuration..." @@ -8242,6 +8236,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2389486 -- No minimum confidence level chosen UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2828607242"] = "No minimum confidence level chosen" +-- Secrets are always exported as locked settings. Recipients need the same enterprise encryption secret to use them. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3001812876"] = "Secrets are always exported as locked settings. Recipients need the same enterprise encryption secret to use them." + -- The tool configuration could not be loaded. Please close this dialog and try again. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3388093684"] = "The tool configuration could not be loaded. Please close this dialog and try again." @@ -8260,18 +8257,21 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3911375 -- This choice applies to settings other than secrets and the minimum provider confidence. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T4236004495"] = "This choice applies to settings other than secrets and the minimum provider confidence." --- Fixed settings -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T445289446"] = "Fixed settings" - -- Export to clipboard UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T508399334"] = "Export to clipboard" -- No enterprise encryption secret is configured. API keys and other secrets cannot be exported. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T633982489"] = "No enterprise encryption secret is configured. API keys and other secrets cannot be exported." +-- Locked settings +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T651584564"] = "Locked settings" + -- Export saved settings as Lua code for your configuration plugin. You can combine exports and adapt the code before deploying it. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T744840132"] = "Export saved settings as Lua code for your configuration plugin. You can combine exports and adapt the code before deploying it." +-- This setting is always locked and applies to the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T857922074"] = "This setting is always locked and applies to the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table." + -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T900713019"] = "Cancel" diff --git a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor index 7c1d36775..288cc7a62 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor +++ b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor @@ -53,7 +53,7 @@ } - @T("Fixed settings") + @T("Locked settings") @T("Editable defaults") @@ -69,14 +69,14 @@ } else { - @T("Secrets are always exported as fixed settings. Recipients need the same enterprise encryption secret to use them.") + @T("Secrets are always exported as locked settings. Recipients need the same enterprise encryption secret to use them.") } @string.Format(T("Current requirement: {0}"), this.GetMinimumProviderConfidenceName()) - @T("This is always a fixed requirement for the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table.") + @T("This setting is always locked and applies to the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table.") } } diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index 67faee578..b5ae05005 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -568,7 +568,7 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T3769421748"] = "fehlgeschlagen" -- Tools used -UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T3809968257"] = "Verwendete Tools" +UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T3809968257"] = "Verwendete Werkzeuge" -- Cancel the batch run UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::BATCHPROCESSING::ASSISTANTBATCHPROCESSING::T3830551741"] = "Stapellauf abbrechen" @@ -3336,6 +3336,9 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T3219823625"] = "Die lo -- The image at the URL is too large (>10 MB). Skipping the image. UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T349928509"] = "Das Bild unter der URL ist zu groß (>10 MB). Das Bild wird übersprungen." +-- Export configuration +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ADMINEXPORTBUTTON::T975426229"] = "Konfiguration exportieren" + -- Open Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Einstellungen öffnen" @@ -4608,9 +4611,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T80509 -- Example text to embed UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T816748904"] = "Beispieltext zum Einbetten" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T975426229"] = "Konfiguration exportieren" - -- Cannot export the encrypted API key: No enterprise encryption secret is configured. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T1832230847"] = "Der verschlüsselte API-Schlüssel kann nicht exportiert werden: Es ist kein Geheimnis für die Verschlüsselung konfiguriert." @@ -4683,9 +4683,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T579100 -- Open Dashboard UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T78223861"] = "Dashboard öffnen" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T975426229"] = "Konfiguration exportieren" - -- Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T1258653480"] = "Einstellungen" @@ -4708,7 +4705,7 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T266367750" UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T2828607242"] = "Kein Mindestvertrauensniveau ausgewählt" -- Minimum provider confidence -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3461070436"] = "Minimale Anbieterzuverlässigkeit" +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3461070436"] = "Minimales Vertrauensniveau für Anbieter" -- Configure global settings for each tool. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3728248397"] = "Konfiguriere globale Einstellungen für jedes Werkzeug." @@ -4782,9 +4779,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T78 -- Are you sure you want to delete the transcription provider '{0}'? UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T789660305"] = "Möchten Sie den Anbieter für Transkriptionen „{0}“ wirklich löschen?" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T975426229"] = "Konfiguration exportieren" - -- Copy {0} to the clipboard UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Kopiere {0} in die Zwischenablage" @@ -7464,9 +7458,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T782820 -- Local Directory UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Lokaler Ordner" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T975426229"] = "Konfiguration exportieren" - -- When enabled, you can preselect some ERI server options. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "Wenn aktiviert, können Sie einige ERI-Serveroptionen vorauswählen." @@ -7758,9 +7749,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T55364659" -- Are you a project manager in a research facility? You might want to create a profile for your project management activities, one for your scientific work, and a profile for when you need to write program code. In these profiles, you can record how much experience you have or which methods you like or dislike using. Later, you can choose when and where you want to use each profile. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T56359901"] = "Sind Sie Projektleiter in einer Forschungseinrichtung? Dann möchten Sie vielleicht ein Profil für ihre Projektmanagement-Aktivitäten anlegen, eines für ihre wissenschaftliche Arbeit und ein weiteres Profil, wenn Sie Programmcode schreiben müssen. In diesen Profilen können Sie festhalten, wie viel Erfahrung Sie haben oder welche Methoden Sie bevorzugen oder nicht gerne verwenden. Später können Sie dann auswählen, wann und wo Sie jedes Profil nutzen möchten." --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T975426229"] = "Konfiguration exportieren" - -- Preselect the target language UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T1417990312"] = "Zielsprache vorwählen" @@ -8220,6 +8208,78 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T403490413"] = -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T900713019"] = "Abbrechen" +-- The tool configuration could not be exported. Please try again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1064444653"] = "Die Werkzeugkonfiguration konnte nicht exportiert werden. Bitte versuchen Sie es erneut." + +-- The selected areas contain no configured API keys or other secrets. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1362677286"] = "Die ausgewählten Bereiche enthalten keine konfigurierten API-Schlüssel oder sonstigen Geheimnisse." + +-- Loading tool configuration... +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1750745869"] = "Werkzeugkonfiguration wird geladen …" + +-- Select all +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1794248818"] = "Alle auswählen" + +-- Include minimum provider confidence +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1823629028"] = "Minimales Vertrauensniveau für Anbieter einbeziehen" + +-- The selected areas contain no settings to export. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T197560416"] = "Die ausgewählten Bereiche enthalten keine Einstellungen zum Exportieren." + +-- Include encrypted API keys and other secrets +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1978141571"] = "Verschlüsselte API-Schlüssel und andere Geheimnisse einbeziehen" + +-- Settings to include +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2051465617"] = "Einzubeziehende Einstellungen" + +-- Editable defaults +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2389486789"] = "Bearbeitbare Standardwerte" + +-- No minimum confidence level chosen +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2828607242"] = "Kein Mindestvertrauensniveau ausgewählt" + +-- Secrets are always exported as locked settings. Recipients need the same enterprise encryption secret to use them. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3001812876"] = "Geheimnisse werden immer als gesperrte Einstellungen exportiert. Empfänger benötigen dasselbe Geheimnis für die Verschlüsselung, um sie verwenden zu können." + +-- The tool configuration could not be loaded. Please close this dialog and try again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3388093684"] = "Die Werkzeugkonfiguration konnte nicht geladen werden. Bitte schließen Sie diesen Dialog und versuchen Sie es erneut." + +-- Export tool configuration +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3758205437"] = "Werkzeugkonfiguration exportieren" + +-- Export mode +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3810275878"] = "Exportmodus" + +-- The selected tool could not be loaded. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3907843187"] = "Das ausgewählte Werkzeug konnte nicht geladen werden." + +-- Each area is independent. Select general settings separately if you want to include them. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3911375461"] = "Jeder Bereich ist unabhängig. Wählen Sie die allgemeinen Einstellungen separat aus, wenn Sie sie einbeziehen möchten." + +-- This choice applies to settings other than secrets and the minimum provider confidence. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T4236004495"] = "Diese Auswahl gilt für Einstellungen mit Ausnahme von Geheimnissen und dem minimalen Vertrauensniveau für Anbieter." + +-- Export to clipboard +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T508399334"] = "In die Zwischenablage exportieren" + +-- No enterprise encryption secret is configured. API keys and other secrets cannot be exported. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T633982489"] = "Es ist kein Geheimnis für die Verschlüsselung konfiguriert. API-Schlüssel und andere Geheimnisse können nicht exportiert werden." + +-- Locked settings +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T651584564"] = "Gesperrte Einstellungen" + +-- Export saved settings as Lua code for your configuration plugin. You can combine exports and adapt the code before deploying it. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T744840132"] = "Exportieren Sie gespeicherte Einstellungen als Lua-Code für Ihr Konfigurations-Plugin. Sie können Exporte kombinieren und den Code vor dem Einsatz anpassen." + +-- This setting is always locked and applies to the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T857922074"] = "Diese Einstellung ist immer gesperrt und gilt für das gesamte Werkzeug. Das Konfigurations-Plugin sperrt die minimalen Vertrauensniveaus für Anbieter gemeinsam für alle Werkzeuge in seiner Tabelle." + +-- Cancel +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T900713019"] = "Abbrechen" + +-- Current requirement: {0} +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T982466527"] = "Aktuelle Anforderung: {0}" + -- Save UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SHORTCUTDIALOG::T1294818664"] = "Speichern" @@ -11418,6 +11478,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::HARNESS::TOOLCALLINGMESSAGE -- The tool calling request failed with status code {0}. See the logs for details. UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::HARNESS::TOOLCALLINGMESSAGES::T3117779001"] = "Die Anfrage zum Aufruf des Werkzeugs ist mit dem Statuscode {0} fehlgeschlagen. Weitere Details finden Sie in den Protokollen." +-- General +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::ITOOLIMPLEMENTATION::T1432485131"] = "Allgemein" + -- Tool UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::ITOOLIMPLEMENTATION::T3517012711"] = "Werkzeug" @@ -11676,6 +11739,18 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES:: -- Any language UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T747012729"] = "Beliebige Sprache" +-- The selected tool configuration export mode is invalid. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T1327976665"] = "Der ausgewählte Exportmodus für die Werkzeugkonfiguration ist ungültig." + +-- The tool's minimum provider confidence level is invalid. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T2093219126"] = "Das minimale Vertrauensniveau für Anbieter dieses Werkzeugs ist ungültig." + +-- Cannot export encrypted tool secrets: No enterprise encryption secret is configured. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T3174877792"] = "Verschlüsselte Geheimnisse des Werkzeugs können nicht exportiert werden: Es ist kein Geheimnis für die Verschlüsselung konfiguriert." + +-- The tool secrets could not be encrypted. Nothing was exported. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T403101133"] = "Die Geheimnisse des Werkzeugs konnten nicht verschlüsselt werden. Es wurde nichts exportiert." + -- The file path is null or empty and the file therefore can not be loaded. UI_TEXT_CONTENT["AISTUDIO::TOOLS::USERFILE::T932243993"] = "Der Dateipfad ist leer, daher kann die Datei nicht geladen werden." diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index 814b0b95f..6465765a0 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -3336,6 +3336,9 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T3219823625"] = "The lo -- The image at the URL is too large (>10 MB). Skipping the image. UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T349928509"] = "The image at the URL is too large (>10 MB). Skipping the image." +-- Export configuration +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ADMINEXPORTBUTTON::T975426229"] = "Export configuration" + -- Open Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Settings" @@ -4608,9 +4611,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T80509 -- Example text to embed UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T816748904"] = "Example text to embed" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELEMBEDDINGS::T975426229"] = "Export configuration" - -- Cannot export the encrypted API key: No enterprise encryption secret is configured. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERBASE::T1832230847"] = "Cannot export the encrypted API key: No enterprise encryption secret is configured." @@ -4683,9 +4683,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T579100 -- Open Dashboard UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T78223861"] = "Open Dashboard" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELPROVIDERS::T975426229"] = "Export configuration" - -- Settings UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T1258653480"] = "Settings" @@ -4782,9 +4779,6 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T78 -- Are you sure you want to delete the transcription provider '{0}'? UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T789660305"] = "Are you sure you want to delete the transcription provider '{0}'?" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTRANSCRIPTION::T975426229"] = "Export configuration" - -- Copy {0} to the clipboard UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TEXTINFOLINE::T2206391442"] = "Copy {0} to the clipboard" @@ -7464,9 +7458,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T782820 -- Local Directory UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T926703547"] = "Local Directory" --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGDATASOURCES::T975426229"] = "Export configuration" - -- When enabled, you can preselect some ERI server options. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGERISERVER::T1280666275"] = "When enabled, you can preselect some ERI server options." @@ -7758,9 +7749,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T55364659" -- Are you a project manager in a research facility? You might want to create a profile for your project management activities, one for your scientific work, and a profile for when you need to write program code. In these profiles, you can record how much experience you have or which methods you like or dislike using. Later, you can choose when and where you want to use each profile. UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T56359901"] = "Are you a project manager in a research facility? You might want to create a profile for your project management activities, one for your scientific work, and a profile for when you need to write program code. In these profiles, you can record how much experience you have or which methods you like or dislike using. Later, you can choose when and where you want to use each profile." --- Export configuration -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROFILES::T975426229"] = "Export configuration" - -- Preselect the target language UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGPROMPTOPTIMIZER::T1417990312"] = "Preselect the target language" @@ -8220,6 +8208,78 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T403490413"] = -- Cancel UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T900713019"] = "Cancel" +-- The tool configuration could not be exported. Please try again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1064444653"] = "The tool configuration could not be exported. Please try again." + +-- The selected areas contain no configured API keys or other secrets. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1362677286"] = "The selected areas contain no configured API keys or other secrets." + +-- Loading tool configuration... +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1750745869"] = "Loading tool configuration..." + +-- Select all +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1794248818"] = "Select all" + +-- Include minimum provider confidence +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1823629028"] = "Include minimum provider confidence" + +-- The selected areas contain no settings to export. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T197560416"] = "The selected areas contain no settings to export." + +-- Include encrypted API keys and other secrets +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T1978141571"] = "Include encrypted API keys and other secrets" + +-- Settings to include +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2051465617"] = "Settings to include" + +-- Editable defaults +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2389486789"] = "Editable defaults" + +-- No minimum confidence level chosen +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2828607242"] = "No minimum confidence level chosen" + +-- Secrets are always exported as locked settings. Recipients need the same enterprise encryption secret to use them. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3001812876"] = "Secrets are always exported as locked settings. Recipients need the same enterprise encryption secret to use them." + +-- The tool configuration could not be loaded. Please close this dialog and try again. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3388093684"] = "The tool configuration could not be loaded. Please close this dialog and try again." + +-- Export tool configuration +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3758205437"] = "Export tool configuration" + +-- Export mode +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3810275878"] = "Export mode" + +-- The selected tool could not be loaded. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3907843187"] = "The selected tool could not be loaded." + +-- Each area is independent. Select general settings separately if you want to include them. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T3911375461"] = "Each area is independent. Select general settings separately if you want to include them." + +-- This choice applies to settings other than secrets and the minimum provider confidence. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T4236004495"] = "This choice applies to settings other than secrets and the minimum provider confidence." + +-- Export to clipboard +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T508399334"] = "Export to clipboard" + +-- No enterprise encryption secret is configured. API keys and other secrets cannot be exported. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T633982489"] = "No enterprise encryption secret is configured. API keys and other secrets cannot be exported." + +-- Locked settings +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T651584564"] = "Locked settings" + +-- Export saved settings as Lua code for your configuration plugin. You can combine exports and adapt the code before deploying it. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T744840132"] = "Export saved settings as Lua code for your configuration plugin. You can combine exports and adapt the code before deploying it." + +-- This setting is always locked and applies to the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T857922074"] = "This setting is always locked and applies to the entire tool. The configuration plugin locks minimum provider confidence levels together for all tools in its confidence table." + +-- Cancel +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T900713019"] = "Cancel" + +-- Current requirement: {0} +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T982466527"] = "Current requirement: {0}" + -- Save UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SHORTCUTDIALOG::T1294818664"] = "Save" @@ -11418,6 +11478,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::HARNESS::TOOLCALLINGMESSAGE -- The tool calling request failed with status code {0}. See the logs for details. UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::HARNESS::TOOLCALLINGMESSAGES::T3117779001"] = "The tool calling request failed with status code {0}. See the logs for details." +-- General +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::ITOOLIMPLEMENTATION::T1432485131"] = "General" + -- Tool UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::ITOOLIMPLEMENTATION::T3517012711"] = "Tool" @@ -11676,6 +11739,18 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES:: -- Any language UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T747012729"] = "Any language" +-- The selected tool configuration export mode is invalid. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T1327976665"] = "The selected tool configuration export mode is invalid." + +-- The tool's minimum provider confidence level is invalid. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T2093219126"] = "The tool's minimum provider confidence level is invalid." + +-- Cannot export encrypted tool secrets: No enterprise encryption secret is configured. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T3174877792"] = "Cannot export encrypted tool secrets: No enterprise encryption secret is configured." + +-- The tool secrets could not be encrypted. Nothing was exported. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T403101133"] = "The tool secrets could not be encrypted. Nothing was exported." + -- The file path is null or empty and the file therefore can not be loaded. UI_TEXT_CONTENT["AISTUDIO::TOOLS::USERFILE::T932243993"] = "The file path is null or empty and the file therefore can not be loaded." From caeab3ac0a73c23e7b84641809ed06e9b44513e8 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 18:10:28 +0200 Subject: [PATCH 05/11] Document tool configuration exports --- documentation/Enterprise IT.md | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/documentation/Enterprise IT.md b/documentation/Enterprise IT.md index 6d15aff36..3d3e992da 100644 --- a/documentation/Enterprise IT.md +++ b/documentation/Enterprise IT.md @@ -425,6 +425,7 @@ Currently, you can configure the following things: - Any number of transcription providers for voice-to-text functionality - Any number of embedding providers for RAG - Enterprise hash approvals for assistant plugins +- Tool settings, encrypted tool API keys, and minimum provider confidence requirements - The update behavior of AI Studio - Various UI and feature settings (see the example configuration for details) @@ -640,6 +641,50 @@ CONFIG["LLM_PROVIDERS"][#CONFIG["LLM_PROVIDERS"]+1] = { The API key will be automatically decrypted when the configuration is loaded and stored securely in the operating system's credential store (Windows Credential Manager / macOS Keychain). +## Exporting tool configurations + +Start from the [example configuration plugin](../app/MindWork%20AI%20Studio/Plugins/configuration/plugin.lua). The export produces a Lua fragment to insert into that file; it assumes `CONFIG` and `CONFIG["SETTINGS"]` already exist. + +1. Enable **Show administration settings** in the app settings. In **Tool Settings**, configure the tool and save your changes, then click its **Export configuration** button next to the settings button. +2. Select the areas to export. All areas start selected. For Web Search, SearXNG, Staan, Tavily, and General are independent: selecting only Tavily does not include the search language, strategy, or preferred backend. Select General separately when you need those settings. +3. Choose **Locked settings** or **Editable defaults**. Locked settings go into `DataTools.LockedToolSettings` and cannot be changed by users. Editable defaults go into `DataTools.DefaultToolSettings`; a user's saved value takes precedence over them. +4. Optionally select **Include encrypted API keys and other secrets**, which starts off. The option is available only when the selected areas contain configured secrets and this machine has a valid enterprise encryption secret. Deploy the same secret to recipients as described in [Setting Up Encrypted API Keys](#setting-up-encrypted-api-keys). Secrets always go into `LockedToolSettings`, including when you choose editable defaults for the other fields. Managed tool secrets are used from the configuration without replacing the user's own keyring entries; removing the managed secret makes the user's own key available again. +5. Review **Include minimum provider confidence**, which starts on. The exported requirement applies to the whole tool and is always locked. The accompanying `DataTools.MinimumProviderConfidenceByToolId.AllowUserOverride = false` locks the entire confidence table in the plugin, including entries for other tools. Deselect this option if your fragment should not configure provider confidence. +6. Click **Export to clipboard**, then paste the fragment into your plugin after its `CONFIG["SETTINGS"] = {}` initialization and after any assignments that replace the tables you want to extend. Review the code and test the plugin using [Local staging and testing](#local-staging-and-testing) before rollout. The export dialog stays open so you can produce another selection. + +The export reads saved, effective settings, including organization-managed values. It does not save settings or change the keyring. Missing values are omitted, explicitly empty non-secret values are preserved, and implicit runtime defaults are not added. Incomplete configurations can be exported so that you can finish them in Lua. If encryption fails, no partial fragment is copied; an empty export also leaves the clipboard unchanged. + +### Complete tool export + +For example, save a timeout of `30`, a content limit of `12000`, and an empty private-host list for **Read Web Page**. Select its General area, **Locked settings**, and **Include minimum provider confidence**. With its default confidence requirement of `VERY_LOW`, the export is: + +```lua +CONFIG["SETTINGS"]["DataTools.LockedToolSettings"] = CONFIG["SETTINGS"]["DataTools.LockedToolSettings"] or {} +CONFIG["SETTINGS"]["DataTools.LockedToolSettings"]["read_web_page.timeoutSeconds"] = "30" +CONFIG["SETTINGS"]["DataTools.LockedToolSettings"]["read_web_page.maxContentCharacters"] = "12000" +CONFIG["SETTINGS"]["DataTools.LockedToolSettings"]["read_web_page.allowedPrivateHosts"] = "" + +CONFIG["SETTINGS"]["DataTools.MinimumProviderConfidenceByToolId"] = CONFIG["SETTINGS"]["DataTools.MinimumProviderConfidenceByToolId"] or {} +CONFIG["SETTINGS"]["DataTools.MinimumProviderConfidenceByToolId"]["read_web_page"] = "VERY_LOW" +CONFIG["SETTINGS"]["DataTools.MinimumProviderConfidenceByToolId.AllowUserOverride"] = false +``` + +### Exporting only one search backend + +For **Web Search**, select only Tavily, choose **Editable defaults**, enable encrypted secrets, and deselect **Include minimum provider confidence**. With a saved search depth of `basic` and an API key, the fragment has this form. The ciphertext below is a placeholder; use the encrypted value generated by your export. + +```lua +CONFIG["SETTINGS"]["DataTools.LockedToolSettings"] = CONFIG["SETTINGS"]["DataTools.LockedToolSettings"] or {} +CONFIG["SETTINGS"]["DataTools.LockedToolSettings"]["web_search.tavily.apiKey"] = "ENC:v1:" + +CONFIG["SETTINGS"]["DataTools.DefaultToolSettings"] = CONFIG["SETTINGS"]["DataTools.DefaultToolSettings"] or {} +CONFIG["SETTINGS"]["DataTools.DefaultToolSettings"]["web_search.tavily.searchDepth"] = "basic" +``` + +This does not change the SearXNG or Staan settings, the general Web Search settings, or its confidence requirement. Web Search still needs a configured `defaultLanguage`; include it through a separate General-area export, add it manually, or let the user configure it. A backend-only export does not restrict the tool to that backend. + +You can combine both fragments in the same plugin: their table initializations preserve earlier entries, and only a later assignment to an identical key replaces its value. A later whole-table assignment such as `CONFIG["SETTINGS"]["DataTools.LockedToolSettings"] = { ... }` replaces those entries, so place exports after it or merge them manually. This behavior applies within one plugin; across separate configuration plugins, the winning plugin replaces the whole managed table as described in [Settings that hold a list or a table](#settings-that-hold-a-list-or-a-table). + ## Letting users provide their own API key Sometimes you want to hand out a preconfigured provider -- a fixed host, model, and instance name From 8bd7b6f7a9bae17937c7943c70de751a3e66a5ff Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 18:50:39 +0200 Subject: [PATCH 06/11] Warn before exporting empty locked tool settings --- .../Assistants/I18N/allTexts.lua | 3 ++ .../Settings/ToolSettingsExportDialog.razor | 7 +++++ .../ToolSettingsExportDialog.razor.cs | 30 +++++++++++++++++-- .../plugin.lua | 3 ++ .../plugin.lua | 3 ++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 29540822c..6e791cbac 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -8233,6 +8233,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2051465 -- Editable defaults UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2389486789"] = "Editable defaults" +-- {0} of the selected settings are empty and are exported as empty locked values. Users cannot change a locked setting, so an empty required one leaves the tool unusable. Deselect the areas you have not configured, or export them as editable defaults. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2555293033"] = "{0} of the selected settings are empty and are exported as empty locked values. Users cannot change a locked setting, so an empty required one leaves the tool unusable. Deselect the areas you have not configured, or export them as editable defaults." + -- No minimum confidence level chosen UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2828607242"] = "No minimum confidence level chosen" diff --git a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor index 288cc7a62..96fdc3f0a 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor +++ b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor @@ -57,6 +57,13 @@ @T("Editable defaults") + @if (this.WarnAboutEmptyLockedSettings) + { + + @string.Format(T("{0} of the selected settings are empty and are exported as empty locked values. Users cannot change a locked setting, so an empty required one leaves the tool unusable. Deselect the areas you have not configured, or export them as editable defaults."), this.EmptySelectedFieldCount) + + } + @if (PluginFactory.EnterpriseEncryption?.IsAvailable is not true) diff --git a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs index 38e10eabd..c479b8195 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs @@ -22,6 +22,7 @@ public partial class ToolSettingsExportDialog : SettingsDialogBase private IReadOnlyList areas = []; private HashSet selectedAreaIds = new(StringComparer.Ordinal); private HashSet configuredSecretFields = new(StringComparer.Ordinal); + private HashSet emptyFieldNames = new(StringComparer.Ordinal); private ToolSettingsExportMode mode = ToolSettingsExportMode.LOCKED; private bool includeSecrets; private bool includeMinimumProviderConfidence = true; @@ -39,6 +40,22 @@ public partial class ToolSettingsExportDialog : SettingsDialogBase private bool CanIncludeSecrets => this.HasSelectedSecrets && PluginFactory.EnterpriseEncryption?.IsAvailable is true; + /// + /// How many of the selected settings hold no value, counting a field shared by two areas once. + /// + /// + /// Saving a tool's settings writes every field of its schema, empty ones included, so an area + /// the administrator never filled in still exports. Locked, those empty values are what the + /// recipient is left with and cannot change, which is worth saying before the export. + /// + private int EmptySelectedFieldCount => this.areas + .Where(area => this.selectedAreaIds.Contains(area.Id)) + .SelectMany(area => area.FieldNames) + .Distinct(StringComparer.Ordinal) + .Count(this.emptyFieldNames.Contains); + + private bool WarnAboutEmptyLockedSettings => this.mode is ToolSettingsExportMode.LOCKED && this.EmptySelectedFieldCount > 0; + private bool CanExport => this.IsAdmin && !this.isLoading && !this.isExporting && !this.isDisposed && this.toolDefinition is not null && this.implementation is not null && (this.selectedAreaIds.Count > 0 || this.includeMinimumProviderConfidence); @@ -64,13 +81,22 @@ protected override async Task OnInitializedAsync() this.areas = this.implementation.GetExportableSettings(this.toolDefinition); this.selectedAreaIds = this.areas.Select(area => area.Id).ToHashSet(StringComparer.Ordinal); - // Retain only the names of configured secret fields, not their plaintext values. - // ExportAsync reads effective settings again when the administrator exports. + // Retain only field names, never the values themselves, so no plaintext secret lives + // in this component. ExportAsync reads effective settings again when the + // administrator exports. var values = await this.ToolSettingsService.GetSettingsAsync(this.toolDefinition); this.configuredSecretFields = this.toolDefinition.SettingsSchema.Properties .Where(property => property.Value.Secret && values.TryGetValue(property.Key, out var value) && !string.IsNullOrWhiteSpace(value)) .Select(property => property.Key) .ToHashSet(StringComparer.Ordinal); + + // A field the export writes as an empty value: it has to be present, because a + // missing one is skipped rather than exported, and it has to be a non-secret, + // because an empty secret is skipped as well. + this.emptyFieldNames = this.toolDefinition.SettingsSchema.Properties + .Where(property => !property.Value.Secret && values.TryGetValue(property.Key, out var value) && string.IsNullOrWhiteSpace(value)) + .Select(property => property.Key) + .ToHashSet(StringComparer.Ordinal); } catch (Exception) { diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index b5ae05005..1da0ee6e7 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -8235,6 +8235,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2051465 -- Editable defaults UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2389486789"] = "Bearbeitbare Standardwerte" +-- {0} of the selected settings are empty and are exported as empty locked values. Users cannot change a locked setting, so an empty required one leaves the tool unusable. Deselect the areas you have not configured, or export them as editable defaults. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2555293033"] = "{0} der ausgewählten Einstellungen sind leer und werden als leere, gesperrte Werte exportiert. Benutzer können eine gesperrte Einstellung nicht ändern. Ist eine erforderliche Einstellung leer und gesperrt, kann das Tool nicht verwendet werden. Wählen Sie die Bereiche ab, die Sie nicht konfiguriert haben, oder exportieren Sie sie als bearbeitbare Standardwerte." + -- No minimum confidence level chosen UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2828607242"] = "Kein Mindestvertrauensniveau ausgewählt" diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index 6465765a0..f011efea4 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -8235,6 +8235,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2051465 -- Editable defaults UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2389486789"] = "Editable defaults" +-- {0} of the selected settings are empty and are exported as empty locked values. Users cannot change a locked setting, so an empty required one leaves the tool unusable. Deselect the areas you have not configured, or export them as editable defaults. +UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2555293033"] = "{0} of the selected settings are empty and are exported as empty locked values. Users cannot change a locked setting, so an empty required one leaves the tool unusable. Deselect the areas you have not configured, or export them as editable defaults." + -- No minimum confidence level chosen UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSEXPORTDIALOG::T2828607242"] = "No minimum confidence level chosen" From 59342e8689ac137221b315ee8bd2a7c0a75efa6b Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 18:55:33 +0200 Subject: [PATCH 07/11] Comment instead of writing the confidence override flag --- .../ToolCallingSystem/ToolSettingsService.Export.cs | 10 ++++++++-- documentation/Enterprise IT.md | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs index d90cb5f68..372f3daa0 100644 --- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs @@ -104,8 +104,14 @@ private static ToolSettingsExportResult BuildConfigurationSection(ToolDefinition [definition.Id] = minimumProviderConfidence.ToString(), }); - // The existing plugin contract locks the entire confidence dictionary, not one entry: - lua.AppendLine($"CONFIG[\"SETTINGS\"][\"{MINIMUM_CONFIDENCE}.AllowUserOverride\"] = false"); + // + // A managed setting without an AllowUserOverride flag is locked anyway, so writing + // "= false" here would only restate the default — and would silently undo an + // administrator's own "= true" further up in the same plugin, for the whole + // dictionary rather than this tool's entry. A comment says the same thing without + // overwriting anything: + // + lua.AppendLine($"-- The whole table is locked unless you set CONFIG[\"SETTINGS\"][\"{MINIMUM_CONFIDENCE}.AllowUserOverride\"] = true"); } return new(LuaCode: lua.ToString()); diff --git a/documentation/Enterprise IT.md b/documentation/Enterprise IT.md index 3d3e992da..324788cd4 100644 --- a/documentation/Enterprise IT.md +++ b/documentation/Enterprise IT.md @@ -649,7 +649,7 @@ Start from the [example configuration plugin](../app/MindWork%20AI%20Studio/Plug 2. Select the areas to export. All areas start selected. For Web Search, SearXNG, Staan, Tavily, and General are independent: selecting only Tavily does not include the search language, strategy, or preferred backend. Select General separately when you need those settings. 3. Choose **Locked settings** or **Editable defaults**. Locked settings go into `DataTools.LockedToolSettings` and cannot be changed by users. Editable defaults go into `DataTools.DefaultToolSettings`; a user's saved value takes precedence over them. 4. Optionally select **Include encrypted API keys and other secrets**, which starts off. The option is available only when the selected areas contain configured secrets and this machine has a valid enterprise encryption secret. Deploy the same secret to recipients as described in [Setting Up Encrypted API Keys](#setting-up-encrypted-api-keys). Secrets always go into `LockedToolSettings`, including when you choose editable defaults for the other fields. Managed tool secrets are used from the configuration without replacing the user's own keyring entries; removing the managed secret makes the user's own key available again. -5. Review **Include minimum provider confidence**, which starts on. The exported requirement applies to the whole tool and is always locked. The accompanying `DataTools.MinimumProviderConfidenceByToolId.AllowUserOverride = false` locks the entire confidence table in the plugin, including entries for other tools. Deselect this option if your fragment should not configure provider confidence. +5. Review **Include minimum provider confidence**, which starts on. The exported requirement applies to the whole tool and is locked, because a managed setting without an `AllowUserOverride` flag is locked by default. The export therefore only adds a comment about that flag instead of writing it: setting it applies to the entire confidence table, including entries for other tools, so that decision stays yours. Deselect this option if your fragment should not configure provider confidence. 6. Click **Export to clipboard**, then paste the fragment into your plugin after its `CONFIG["SETTINGS"] = {}` initialization and after any assignments that replace the tables you want to extend. Review the code and test the plugin using [Local staging and testing](#local-staging-and-testing) before rollout. The export dialog stays open so you can produce another selection. The export reads saved, effective settings, including organization-managed values. It does not save settings or change the keyring. Missing values are omitted, explicitly empty non-secret values are preserved, and implicit runtime defaults are not added. Incomplete configurations can be exported so that you can finish them in Lua. If encryption fails, no partial fragment is copied; an empty export also leaves the clipboard unchanged. @@ -666,7 +666,7 @@ CONFIG["SETTINGS"]["DataTools.LockedToolSettings"]["read_web_page.allowedPrivate CONFIG["SETTINGS"]["DataTools.MinimumProviderConfidenceByToolId"] = CONFIG["SETTINGS"]["DataTools.MinimumProviderConfidenceByToolId"] or {} CONFIG["SETTINGS"]["DataTools.MinimumProviderConfidenceByToolId"]["read_web_page"] = "VERY_LOW" -CONFIG["SETTINGS"]["DataTools.MinimumProviderConfidenceByToolId.AllowUserOverride"] = false +-- The whole table is locked unless you set CONFIG["SETTINGS"]["DataTools.MinimumProviderConfidenceByToolId.AllowUserOverride"] = true ``` ### Exporting only one search backend From ecab429fa046b1c6a115a630ddf3a98560391047 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 18:57:38 +0200 Subject: [PATCH 08/11] Document the export mode and drop its unreachable check --- .../Assistants/I18N/allTexts.lua | 3 --- .../ToolSettingsExportMode.cs | 18 ++++++++++++++++++ .../ToolSettingsService.Export.cs | 3 --- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 6e791cbac..63af55b13 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -11740,9 +11740,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES:: -- Any language UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T747012729"] = "Any language" --- The selected tool configuration export mode is invalid. -UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T1327976665"] = "The selected tool configuration export mode is invalid." - -- The tool's minimum provider confidence level is invalid. UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T2093219126"] = "The tool's minimum provider confidence level is invalid." diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportMode.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportMode.cs index a5fe8e15d..89774da30 100644 --- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportMode.cs +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsExportMode.cs @@ -1,7 +1,25 @@ namespace AIStudio.Tools.ToolCallingSystem; +/// +/// How firmly an exported tool setting applies to the people who receive the configuration plugin. +/// +/// +/// Chosen per export, and it covers the ordinary settings only. A secret is always locked, no +/// matter which mode is picked, because a pre-filled secret is one the user may save as their +/// own — see the tool settings service for that rule. The minimum provider confidence is +/// likewise a fixed requirement. +/// public enum ToolSettingsExportMode { + /// + /// The organization fixes the value: it goes into LockedToolSettings, the user cannot change + /// it, and it is reapplied on every configuration update. + /// LOCKED, + + /// + /// The organization pre-fills the value: it goes into DefaultToolSettings, and a value the + /// user saves afterwards wins over it. + /// DEFAULT, } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs index 372f3daa0..45bfa5a63 100644 --- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs @@ -57,9 +57,6 @@ private static IReadOnlyList GetSelectedFieldNames(ToolDefinition defini private static ToolSettingsExportResult BuildConfigurationSection(ToolDefinition definition, IReadOnlyList areas, IReadOnlyDictionary values, ToolSettingsExportOptions options, ConfidenceLevel minimumProviderConfidence, EnterpriseEncryption? encryption) { - if (!Enum.IsDefined(options.Mode)) - return new(ErrorMessage: TB("The selected tool configuration export mode is invalid.")); - var lockedValues = new Dictionary(StringComparer.Ordinal); var defaultValues = new Dictionary(StringComparer.Ordinal); foreach (var fieldName in GetSelectedFieldNames(definition, areas, options.SelectedAreaIds)) From 4626bf45f7cdb9cc0e70e6a0abfe61a3c51b902a Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 19:03:29 +0200 Subject: [PATCH 09/11] Log export failures and inline the builder signature --- .../Settings/ToolSettingsExportDialog.razor.cs | 12 +++++++++--- .../ToolCallingSystem/ToolSettingsService.Export.cs | 3 +-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs index c479b8195..55cc38ca4 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/Settings/ToolSettingsExportDialog.razor.cs @@ -17,6 +17,9 @@ public partial class ToolSettingsExportDialog : SettingsDialogBase [Inject] private ToolSettingsService ToolSettingsService { get; init; } = null!; + [Inject] + private ILogger Logger { get; init; } = null!; + private ToolDefinition? toolDefinition; private IToolImplementation? implementation; private IReadOnlyList areas = []; @@ -98,9 +101,11 @@ protected override async Task OnInitializedAsync() .Select(property => property.Key) .ToHashSet(StringComparer.Ordinal); } - catch (Exception) + catch (Exception e) { - // A runtime error may contain secret data, so never display the exception text. + // A runtime error may contain secret data, so it goes to the log for diagnosis but + // never into the dialog: + this.Logger.LogError(e, "Failed to load the configuration of the tool '{ToolId}' for export.", this.ToolId); this.toolDefinition = null; this.message = T("The tool configuration could not be loaded. Please close this dialog and try again."); } @@ -180,8 +185,9 @@ private async Task Export() // administrators can retry or export another selection from the same tool. await this.RustService.CopyText2Clipboard(result.LuaCode); } - catch (Exception) + catch (Exception e) { + this.Logger.LogError(e, "Failed to export the configuration of the tool '{ToolId}'.", this.ToolId); this.message = T("The tool configuration could not be exported. Please try again."); } finally diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs index 45bfa5a63..6013e80c8 100644 --- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs +++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolSettingsService.Export.cs @@ -54,8 +54,7 @@ private static IReadOnlyList GetSelectedFieldNames(ToolDefinition defini /// Builds a fragment from one snapshot. A failed encryption returns no Lua, even when other /// fields have already been processed, so the caller cannot copy a partial export by accident. /// - private static ToolSettingsExportResult BuildConfigurationSection(ToolDefinition definition, IReadOnlyList areas, IReadOnlyDictionary values, - ToolSettingsExportOptions options, ConfidenceLevel minimumProviderConfidence, EnterpriseEncryption? encryption) + private static ToolSettingsExportResult BuildConfigurationSection(ToolDefinition definition, IReadOnlyList areas, IReadOnlyDictionary values, ToolSettingsExportOptions options, ConfidenceLevel minimumProviderConfidence, EnterpriseEncryption? encryption) { var lockedValues = new Dictionary(StringComparer.Ordinal); var defaultValues = new Dictionary(StringComparer.Ordinal); From d6c461fc0a5dbda0ee1b5ac817c0a916252b10e6 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 19:14:15 +0200 Subject: [PATCH 10/11] Mention the tool configuration export in the changelog --- app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md index 1ee360db9..e9c24e990 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.9.1.md @@ -6,6 +6,6 @@ - Added tools to the policies of the Document Analysis assistant. A policy states which tools an analysis may use, and the AI uses exactly those — nobody has to pick them per document. AI Studio warns you beforehand when the provider you selected is not trusted enough for a tool the policy names. IT departments can roll policies out together with their tools. - Added tools to assistant plugins and direct-chat launchers. Plugin authors name them in the new `ToolIds` field, either as the tools an assistant runs with or as the tools a launcher preselects for the chat it opens; the example assistant plugin shows both. Which tools an assistant asks for is part of what you get to see before you enable it: its security card names them, and the security audit takes them into account. - Added tools to the Assistant Builder. For a direct-chat launcher you pick them yourself, alongside the workspace, provider, and data sources. For an assistant, the AI chooses from the tools installed here and says so in the draft, so you see the decision before the assistant is written. -- Added organization-wide management for tools. IT departments can switch tools off entirely (`DataTools.EnableTools`), disable individual ones (`DataTools.DisabledToolIds`), raise the provider trust a tool requires (`DataTools.MinimumProviderConfidenceByToolId`), and manage every tool setting by tool and field name — either fixed (`DataTools.LockedToolSettings`) or as a pre-filled value the user may still change (`DataTools.DefaultToolSettings`). None of these needs to be known to AI Studio in advance, so it covers the tools future plugins will bring just as well. Secrets such as API keys can be rolled out too, encrypted with your enterprise encryption secret, the same way you already deploy provider keys. The example configuration plugin documents every setting of both tools. +- Added organization-wide management for tools. Among other options, IT departments can switch tools off entirely, disable individual ones, or define the provider trust a tool requires. You do not have to write any of it by hand: set a tool up in the app, then export its configuration as ready-made Lua code for your plugin, with encrypted API keys if you want them. - Added tool calling to the abilities you can state yourself in the expert provider settings. When you use a model AI Studio does not recognize as tool-capable, you can now declare that it is, the same way you already could for image input or reasoning. - Improved loading web content in the assistants: it now uses the same reader as the Read Web Page tool, which extracts the main content of a page more reliably and skips navigation and boilerplate. Pages from your own network, including local servers, keep working as before. When a page cannot be read, AI Studio now says why instead of leaving the field empty. From e420df8091d9aa3f45c6c848ccfa9f55c2d547a5 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 5 Sep 2026 19:15:29 +0200 Subject: [PATCH 11/11] Updated I18N --- .../de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua | 3 --- .../en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua | 3 --- 2 files changed, 6 deletions(-) diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index 1da0ee6e7..15b44bbbc 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -11742,9 +11742,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES:: -- Any language UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T747012729"] = "Beliebige Sprache" --- The selected tool configuration export mode is invalid. -UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T1327976665"] = "Der ausgewählte Exportmodus für die Werkzeugkonfiguration ist ungültig." - -- The tool's minimum provider confidence level is invalid. UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T2093219126"] = "Das minimale Vertrauensniveau für Anbieter dieses Werkzeugs ist ungültig." diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index f011efea4..ee4ef8234 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -11742,9 +11742,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES:: -- Any language UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSOPTIONSOURCES::T747012729"] = "Any language" --- The selected tool configuration export mode is invalid. -UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T1327976665"] = "The selected tool configuration export mode is invalid." - -- The tool's minimum provider confidence level is invalid. UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLSETTINGSSERVICE::T2093219126"] = "The tool's minimum provider confidence level is invalid."