mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-11 19:52:10 +00:00
Tools can now be managed by the Enterprise IT
This commit is contained in:
parent
548cd12934
commit
4fc6a22752
@ -175,7 +175,7 @@
|
||||
<ProfileSelection MarginLeft="" @bind-CurrentProfile="@this.CurrentProfile"/>
|
||||
}
|
||||
|
||||
@if (this.SettingsManager.IsToolSelectionVisible(this.Component))
|
||||
@if (this.SettingsManager.AreToolsEnabled() && this.SettingsManager.IsToolSelectionVisible(this.Component))
|
||||
{
|
||||
<ToolSelection Component="@this.Component" LLMProvider="@this.ProviderSettings" SelectedToolIds="@this.selectedToolIds" SelectedToolIdsChanged="@this.SelectedToolIdsChanged" Disabled="@this.IsProcessing" />
|
||||
}
|
||||
|
||||
@ -3607,6 +3607,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3728248397
|
||||
-- Tool Settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3730473128"] = "Tool Settings"
|
||||
|
||||
-- This tool has been disabled by your organization.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3794167684"] = "This tool has been disabled by your organization."
|
||||
|
||||
-- Status
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T6222351"] = "Status"
|
||||
|
||||
@ -3724,6 +3727,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3119156561"] = "Required
|
||||
-- Close
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3448155331"] = "Close"
|
||||
|
||||
-- This tool has been disabled by your organization.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3794167684"] = "This tool has been disabled by your organization."
|
||||
|
||||
-- No tools are available in this context.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3904490680"] = "No tools are available in this context."
|
||||
|
||||
@ -6535,6 +6541,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3616903110"]
|
||||
-- Tool Settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3730473128"] = "Tool Settings"
|
||||
|
||||
-- This tool has been disabled by your organization.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3794167684"] = "This tool has been disabled by your organization."
|
||||
|
||||
-- The selected tool could not be loaded.
|
||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3907843187"] = "The selected tool could not be loaded."
|
||||
|
||||
@ -9286,6 +9295,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS:
|
||||
-- Optional HTTP timeout for the search request in seconds.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3078115445"] = "Optional HTTP timeout for the search request in seconds."
|
||||
|
||||
-- The default safe search setting must be 0, 1, or 2.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3187215042"] = "The default safe search setting must be 0, 1, or 2."
|
||||
|
||||
-- Search the web with a configured SearXNG instance and retrieve the readable content of the best matching pages.
|
||||
UI_TEXT_CONTENT["AISTUDIO::TOOLS::TOOLCALLINGSYSTEM::TOOLCALLINGIMPLEMENTATIONS::SEARXNGWEBSEARCHTOOL::T3361633224"] = "Search the web with a configured SearXNG instance and retrieve the readable content of the best matching pages."
|
||||
|
||||
|
||||
@ -125,7 +125,10 @@
|
||||
|
||||
<ProfileSelection MarginLeft="" CurrentProfile="@this.currentProfile" CurrentProfileChanged="@this.ProfileWasChanged" Disabled="@(!this.currentChatTemplate.AllowProfileUsage)" DisabledText="@T("Profile usage is disabled according to your chat template settings.")"/>
|
||||
|
||||
@if (this.SettingsManager.AreToolsEnabled())
|
||||
{
|
||||
<ToolSelection Component="Components.CHAT" LLMProvider="@this.Provider" SelectedToolIds="@this.selectedToolIds" SelectedToolIdsChanged="@this.SelectedToolIdsChanged" Disabled="@this.IsCurrentChatStreaming" />
|
||||
}
|
||||
|
||||
@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
|
||||
{
|
||||
|
||||
@ -37,7 +37,13 @@
|
||||
</MudMenu>
|
||||
</MudTd>
|
||||
<MudTd>
|
||||
@if (context.ConfigurationState.IsConfigured)
|
||||
@if (!context.IsActive)
|
||||
{
|
||||
<MudTooltip Text="@T("This tool has been disabled by your organization.")">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Lock" Color="Color.Error" />
|
||||
</MudTooltip>
|
||||
}
|
||||
else if (context.ConfigurationState.IsConfigured)
|
||||
{
|
||||
<MudIcon Icon="@Icons.Material.Filled.CheckCircle" Color="Color.Success" />
|
||||
}
|
||||
|
||||
@ -8,5 +8,5 @@
|
||||
{
|
||||
<ConfigurationOption OptionDescription="@T("Show tool selection in this assistant?")" LabelOn="@T("Tool selection is visible")" LabelOff="@T("Tool selection is hidden")" State="@(() => this.SettingsManager.IsToolSelectionVisible(this.Component))" StateUpdate="@(value => this.SettingsManager.SetToolSelectionVisibility(this.Component, value))" />
|
||||
}
|
||||
<ConfigurationMultiSelect TData="string" OptionDescription="@this.OptionTitle" SelectedValues="@this.GetSelectedValues" Data="@this.availableTools" SelectionUpdate="@this.UpdateSelection" OptionHelp="@this.OptionHelp" Disabled="@(() => this.AreDefaultToolsDisabled)" EmptySelectionText="@T("No tools selected.")" SingleSelectionText="@T("You have selected 1 tool.")" MultipleSelectionText="@T("You have selected {0} tools.")" />
|
||||
<ConfigurationMultiSelect TData="string" OptionDescription="@this.OptionTitle" SelectedValues="@this.GetSelectedValues" Data="@this.availableTools" SelectionUpdate="@this.UpdateSelection" OptionHelp="@this.OptionHelp" Disabled="@(() => this.AreDefaultToolsDisabled)" IsItemLocked="@this.IsToolDisabled" EmptySelectionText="@T("No tools selected.")" SingleSelectionText="@T("You have selected 1 tool.")" MultipleSelectionText="@T("You have selected {0} tools.")" />
|
||||
}
|
||||
|
||||
@ -29,6 +29,8 @@ public partial class ToolDefaultsConfiguration : MSGComponentBase
|
||||
this.Component is not AIStudio.Tools.Components.CHAT &&
|
||||
!this.SettingsManager.IsToolSelectionVisible(this.Component);
|
||||
|
||||
private bool IsToolDisabled(string toolId) => !this.SettingsManager.IsToolActive(toolId);
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
this.availableTools = (await this.ToolRegistry.GetCatalogAsync(this.Component))
|
||||
|
||||
@ -47,8 +47,14 @@
|
||||
<MudPaper Class="pa-2 mb-2 border rounded-lg">
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween">
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||
<MudSwitch T="bool" Color="Color.Primary" Value="@isSelected" ValueChanged="@(value => this.ChangeSelection(item.Definition.Id, value))" Disabled="@(!isConfigured || isBlockedByProviderConfidence || this.Disabled || !this.SupportsTools)" />
|
||||
<MudSwitch T="bool" Color="Color.Primary" Value="@isSelected" ValueChanged="@(value => this.ChangeSelection(item.Definition.Id, value))" Disabled="@(!item.IsActive || !isConfigured || isBlockedByProviderConfidence || this.Disabled || !this.SupportsTools)" />
|
||||
<MudIcon Icon="@item.Implementation.Icon" Color="Color.Info" />
|
||||
@if (!item.IsActive)
|
||||
{
|
||||
<MudTooltip Text="@T("This tool has been disabled by your organization.")">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Lock" Color="Color.Error" Size="Size.Small" />
|
||||
</MudTooltip>
|
||||
}
|
||||
<MudTooltip Text="@item.Implementation.GetDescription()">
|
||||
<MudText Typo="Typo.body1">@item.Implementation.GetDisplayName()</MudText>
|
||||
</MudTooltip>
|
||||
@ -59,6 +65,10 @@
|
||||
{
|
||||
<MudText Typo="Typo.caption" Color="Color.Warning">@(string.IsNullOrWhiteSpace(item.ConfigurationState.Message) ? T("Required settings are missing. Configure this tool before enabling it.") : item.ConfigurationState.Message)</MudText>
|
||||
}
|
||||
@if (!item.IsActive)
|
||||
{
|
||||
<MudText Typo="Typo.caption" Color="Color.Warning">@T("This tool has been disabled by your organization.")</MudText>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(providerConfidenceHint))
|
||||
{
|
||||
<MudText Typo="Typo.caption" Color="Color.Warning">@providerConfidenceHint</MudText>
|
||||
|
||||
@ -73,6 +73,9 @@ public partial class ToolSelection : MSGComponentBase
|
||||
|
||||
private async Task ChangeSelection(string toolId, bool isSelected)
|
||||
{
|
||||
if (isSelected && !this.SettingsManager.IsToolActive(toolId))
|
||||
return;
|
||||
|
||||
var updated = new HashSet<string>(this.SelectedToolIds, StringComparer.Ordinal);
|
||||
if (isSelected)
|
||||
updated.Add(toolId);
|
||||
|
||||
@ -19,6 +19,11 @@
|
||||
@this.implementation?.GetDescription()
|
||||
</MudJustifiedText>
|
||||
|
||||
@if (!this.SettingsManager.IsToolActive(this.toolDefinition.Id))
|
||||
{
|
||||
<MudAlert Severity="Severity.Warning" Class="mb-4">@T("This tool has been disabled by your organization.")</MudAlert>
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(this.validationMessage))
|
||||
{
|
||||
<MudAlert Severity="Severity.Error" Class="mb-4">@this.validationMessage</MudAlert>
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools.ToolCallingSystem;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@ -53,19 +52,8 @@ public partial class ToolSettingsDialog : SettingsDialogBase
|
||||
return string.Format(T("{0} Default: {1}"), description, defaultValue);
|
||||
}
|
||||
|
||||
private bool IsFieldDisabled(string fieldName)
|
||||
{
|
||||
if (this.toolDefinition?.Id.Equals(ToolSelectionRules.WEB_SEARCH_TOOL_ID, StringComparison.Ordinal) is true &&
|
||||
fieldName.Equals("baseUrl", StringComparison.Ordinal) &&
|
||||
ManagedConfiguration.TryGet(x => x.Tools, x => x.WebSearchBaseUrl, out var webSearchMeta) &&
|
||||
webSearchMeta.IsLocked)
|
||||
return true;
|
||||
|
||||
return this.toolDefinition?.Id.Equals(ToolSelectionRules.READ_WEB_PAGE_TOOL_ID, StringComparison.Ordinal) is true &&
|
||||
fieldName.Equals("allowedPrivateHosts", StringComparison.Ordinal) &&
|
||||
ManagedConfiguration.TryGet(x => x.Tools, x => x.ReadWebPageAllowedPrivateHosts, out var readWebPageMeta) &&
|
||||
readWebPageMeta.IsLocked;
|
||||
}
|
||||
private bool IsFieldDisabled(string fieldName) =>
|
||||
this.toolDefinition is not null && this.ToolSettingsService.IsFieldLocked(this.toolDefinition, fieldName);
|
||||
|
||||
private string GetFieldPlaceholder(string fieldName, ToolSettingsFieldDefinition fieldDefinition) =>
|
||||
string.IsNullOrWhiteSpace(this.GetValue(fieldName)) ? this.GetFieldDefaultValue(fieldName, fieldDefinition) : string.Empty;
|
||||
|
||||
@ -356,6 +356,15 @@ CONFIG["SETTINGS"] = {}
|
||||
-- Examples are: "CmdOrControl+Shift+D", "Alt+F9", "F8"
|
||||
-- CONFIG["SETTINGS"]["DataApp.ShortcutVoiceRecording"] = "CmdOrControl+1"
|
||||
|
||||
-- Configure whether tools are available at all. The default is true.
|
||||
-- When tools are disabled globally, tool selection is hidden in chats and assistants,
|
||||
-- but the global tool settings remain available to administrators.
|
||||
-- CONFIG["SETTINGS"]["DataTools.EnableTools"] = false
|
||||
|
||||
-- Disable individual tools by their stable tool ID. The default is an empty set.
|
||||
-- Unknown IDs are safely ignored and can be deployed before a future tool is installed.
|
||||
-- CONFIG["SETTINGS"]["DataTools.DisabledToolIds"] = { "web_search" }
|
||||
|
||||
-- Configure the minimum provider confidence level required for individual tools.
|
||||
-- Tool IDs include: web_search, read_web_page
|
||||
-- Allowed values are: NONE, UNTRUSTED, VERY_LOW, LOW, MODERATE, MEDIUM, HIGH
|
||||
@ -365,21 +374,47 @@ CONFIG["SETTINGS"] = {}
|
||||
-- ["read_web_page"] = "MEDIUM"
|
||||
-- }
|
||||
|
||||
-- Configure the SearXNG instance URL used by the Web Search tool.
|
||||
-- You can enter either the instance root URL or the /search endpoint.
|
||||
-- Configure the Web Search tool. All values are strings.
|
||||
-- WebSearchBaseUrl: required SearXNG HTTP(S) root URL or /search endpoint; no default.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchBaseUrl"] = "https://searxng.website/"
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchBaseUrl.AllowUserOverride"] = false
|
||||
-- WebSearchDefaultLanguage: optional language code; default is empty.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchDefaultLanguage"] = "en"
|
||||
-- WebSearchDefaultSafeSearch: optional SearXNG safe-search level "0", "1", or "2"; default is empty.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchDefaultSafeSearch"] = "1"
|
||||
-- WebSearchDefaultCategories: optional comma-separated categories; default is empty.
|
||||
-- WebSearchDefaultEngines: optional comma-separated engines; default is empty.
|
||||
-- Categories and engines cannot both be configured.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchDefaultCategories"] = "general, science"
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchDefaultEngines"] = ""
|
||||
-- WebSearchMaxResults: positive integer; default 5, effective maximum 20.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchMaxResults"] = "5"
|
||||
-- WebSearchTimeoutSeconds: positive integer; default 20, effective maximum 60.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchTimeoutSeconds"] = "20"
|
||||
-- WebSearchMaxTotalContentCharacters: positive integer; default and maximum 100000.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchMaxTotalContentCharacters"] = "100000"
|
||||
-- WebSearchMinContentCharactersPerResult: positive integer; default and maximum 3000.
|
||||
-- The total content budget must be at least this value multiplied by the hard limit of 20 results.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchMinContentCharactersPerResult"] = "3000"
|
||||
-- WebSearchPageTimeoutSeconds: positive integer; default and maximum 30.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchPageTimeoutSeconds"] = "30"
|
||||
-- WebSearchRetrievalTimeoutSeconds: positive integer; default and maximum 90.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchRetrievalTimeoutSeconds"] = "90"
|
||||
|
||||
-- Configure private or VPN hosts that the Read Web Page tool may access.
|
||||
-- Public web pages do not need to be listed here.
|
||||
-- Private hosts listed here still require a provider with HIGH confidence before any page content is sent to the model.
|
||||
-- For hosts on this allowlist, AI Studio also tries the current user's operating-system sign-in
|
||||
-- automatically when the server requests integrated authentication (for example Kerberos or NTLM).
|
||||
-- This does not reuse Firefox cookies or an existing browser session.
|
||||
-- Separate host patterns with commas. Wildcards only match subdomains, so add the root domain separately if needed.
|
||||
-- Examples:
|
||||
-- Configure the Read Web Page tool. All values are strings.
|
||||
-- ReadWebPageTimeoutSeconds: positive integer; default 30, effective maximum 60.
|
||||
-- CONFIG["SETTINGS"]["DataTools.ReadWebPageTimeoutSeconds"] = "30"
|
||||
-- ReadWebPageMaxContentCharacters: positive integer; default 30000, effective maximum 50000.
|
||||
-- CONFIG["SETTINGS"]["DataTools.ReadWebPageMaxContentCharacters"] = "30000"
|
||||
-- ReadWebPageAllowedPrivateHosts: optional comma-separated private or VPN host patterns; default is empty.
|
||||
-- Public pages do not need to be listed. Wildcards only match subdomains, so add the root domain separately.
|
||||
-- Allowed private hosts require a provider with HIGH confidence. AI Studio tries the current user's
|
||||
-- operating-system sign-in when integrated authentication is requested, but does not reuse browser cookies.
|
||||
-- CONFIG["SETTINGS"]["DataTools.ReadWebPageAllowedPrivateHosts"] = "dlr.de, *.dlr.de"
|
||||
-- CONFIG["SETTINGS"]["DataTools.ReadWebPageAllowedPrivateHosts.AllowUserOverride"] = false
|
||||
|
||||
-- The 14 Web Search and Read Web Page settings are locked by default. Add
|
||||
-- ".AllowUserOverride" = true to any of them to provide an editable organization default instead.
|
||||
-- A saved local value then takes precedence.
|
||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchBaseUrl.AllowUserOverride"] = true
|
||||
|
||||
-- Configure the HTTP timeout for external requests, in seconds.
|
||||
-- The default is 3600 (1 hour).
|
||||
|
||||
@ -107,7 +107,8 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, new Ur
|
||||
//
|
||||
var providerConfidence = this.Provider.GetConfidence(settingsManager).Level;
|
||||
var minimumWebSearchConfidence = settingsManager.GetMinimumProviderConfidenceForTool(ToolSelectionRules.WEB_SEARCH_TOOL_ID);
|
||||
var isWebSearchAllowed = ToolSelectionRules.IsProviderConfidenceAllowed(providerConfidence, minimumWebSearchConfidence);
|
||||
var isWebSearchAllowed = settingsManager.IsToolActive(ToolSelectionRules.WEB_SEARCH_TOOL_ID) &&
|
||||
ToolSelectionRules.IsProviderConfidenceAllowed(providerConfidence, minimumWebSearchConfidence);
|
||||
IList<object> providerTools = modelCapabilities.Contains(Capability.WEB_SEARCH) && isWebSearchAllowed
|
||||
? [ ProviderTools.WEB_SEARCH ]
|
||||
: [];
|
||||
|
||||
@ -16,6 +16,16 @@ public sealed class DataTools(Expression<Func<Data, DataTools>>? configSelection
|
||||
|
||||
public HashSet<string> VisibleToolSelectionComponents { get; set; } = [];
|
||||
|
||||
public bool EnableTools { get; set; } = ManagedConfiguration.Register(
|
||||
configSelection,
|
||||
x => x.EnableTools,
|
||||
true);
|
||||
|
||||
public HashSet<string> DisabledToolIds { get; set; } = ManagedConfiguration.Register(
|
||||
configSelection,
|
||||
x => x.DisabledToolIds,
|
||||
[]);
|
||||
|
||||
public Dictionary<string, string> MinimumProviderConfidenceByToolId { get; set; } = ManagedConfiguration.Register<DataTools, Dictionary<string, string>>(
|
||||
configSelection,
|
||||
x => x.MinimumProviderConfidenceByToolId,
|
||||
@ -26,6 +36,66 @@ public sealed class DataTools(Expression<Func<Data, DataTools>>? configSelection
|
||||
x => x.WebSearchBaseUrl,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchDefaultLanguage { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchDefaultLanguage,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchDefaultSafeSearch { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchDefaultSafeSearch,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchDefaultCategories { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchDefaultCategories,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchDefaultEngines { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchDefaultEngines,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchMaxResults { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchMaxResults,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchTimeoutSeconds { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchTimeoutSeconds,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchMaxTotalContentCharacters { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchMaxTotalContentCharacters,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchMinContentCharactersPerResult { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchMinContentCharactersPerResult,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchPageTimeoutSeconds { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchPageTimeoutSeconds,
|
||||
string.Empty);
|
||||
|
||||
public string WebSearchRetrievalTimeoutSeconds { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.WebSearchRetrievalTimeoutSeconds,
|
||||
string.Empty);
|
||||
|
||||
public string ReadWebPageTimeoutSeconds { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.ReadWebPageTimeoutSeconds,
|
||||
string.Empty);
|
||||
|
||||
public string ReadWebPageMaxContentCharacters { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.ReadWebPageMaxContentCharacters,
|
||||
string.Empty);
|
||||
|
||||
public string ReadWebPageAllowedPrivateHosts { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||
configSelection,
|
||||
x => x.ReadWebPageAllowedPrivateHosts,
|
||||
|
||||
@ -594,6 +594,9 @@ public sealed class SettingsManager
|
||||
|
||||
public HashSet<string> FilterToolIdsForProvider(AIStudio.Settings.Provider provider, IEnumerable<string> selectedToolIds)
|
||||
{
|
||||
if (!this.AreToolsEnabled())
|
||||
return [];
|
||||
|
||||
var toolCallingAvailability = provider.GetToolCallingAvailability();
|
||||
if (!toolCallingAvailability.IsAvailable)
|
||||
return [];
|
||||
@ -610,6 +613,12 @@ public sealed class SettingsManager
|
||||
|
||||
foreach (var toolId in filtered.ToList())
|
||||
{
|
||||
if (!this.IsToolActive(toolId))
|
||||
{
|
||||
filtered.Remove(toolId);
|
||||
continue;
|
||||
}
|
||||
|
||||
var minimumToolConfidence = this.GetMinimumProviderConfidenceForTool(toolId);
|
||||
if (!ToolSelectionRules.IsProviderConfidenceAllowed(providerConfidence, minimumToolConfidence))
|
||||
filtered.Remove(toolId);
|
||||
@ -618,6 +627,12 @@ public sealed class SettingsManager
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public bool AreToolsEnabled() => this.ConfigurationData.Tools.EnableTools;
|
||||
|
||||
public bool IsToolActive(string toolId) =>
|
||||
this.AreToolsEnabled() &&
|
||||
!this.ConfigurationData.Tools.DisabledToolIds.Contains(toolId);
|
||||
|
||||
public bool IsToolSelectionVisible(AIStudio.Tools.Components component) => component switch
|
||||
{
|
||||
AIStudio.Tools.Components.CHAT => true,
|
||||
|
||||
@ -199,13 +199,29 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
// Config: global voice recording shortcut
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.App, x => x.ShortcutVoiceRecording, this.Id, settingsTable, dryRun);
|
||||
|
||||
// Config: global tool availability
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.EnableTools, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.DisabledToolIds, this.Id, settingsTable, dryRun);
|
||||
|
||||
// Config: minimum provider confidence per tool
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.MinimumProviderConfidenceByToolId, this.Id, settingsTable, dryRun);
|
||||
|
||||
// Config: SearXNG base URL for the web search tool
|
||||
// Config: web search tool settings
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchBaseUrl, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchDefaultLanguage, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchDefaultSafeSearch, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchDefaultCategories, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchDefaultEngines, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchMaxResults, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchTimeoutSeconds, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchMaxTotalContentCharacters, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchMinContentCharactersPerResult, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchPageTimeoutSeconds, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.WebSearchRetrievalTimeoutSeconds, this.Id, settingsTable, dryRun);
|
||||
|
||||
// Config: private hosts allowed for the read web page tool
|
||||
// Config: read web page tool settings
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.ReadWebPageTimeoutSeconds, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.ReadWebPageMaxContentCharacters, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.ReadWebPageAllowedPrivateHosts, this.Id, settingsTable, dryRun);
|
||||
|
||||
// Config: timeout for external HTTP requests
|
||||
|
||||
@ -292,15 +292,58 @@ public static partial class PluginFactory
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.App, x => x.ShortcutVoiceRecording, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
// Check for global tool availability:
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.EnableTools, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.DisabledToolIds, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
// Check for minimum provider confidence per tool:
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.MinimumProviderConfidenceByToolId, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
// Check for the SearXNG base URL for the web search tool:
|
||||
// Check for web search tool settings:
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchBaseUrl, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
// Check for private hosts allowed for the read web page tool:
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchDefaultLanguage, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchDefaultSafeSearch, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchDefaultCategories, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchDefaultEngines, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchMaxResults, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchTimeoutSeconds, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchMaxTotalContentCharacters, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchMinContentCharactersPerResult, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchPageTimeoutSeconds, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchRetrievalTimeoutSeconds, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
// Check for read web page tool settings:
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.ReadWebPageTimeoutSeconds, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.ReadWebPageMaxContentCharacters, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.ReadWebPageAllowedPrivateHosts, AVAILABLE_PLUGINS))
|
||||
wasConfigurationChanged = true;
|
||||
|
||||
|
||||
@ -113,6 +113,16 @@ public sealed class SearXNGWebSearchTool : IToolImplementation
|
||||
});
|
||||
}
|
||||
|
||||
var defaultSafeSearch = settingsValues.GetValueOrDefault("defaultSafeSearch");
|
||||
if (!string.IsNullOrWhiteSpace(defaultSafeSearch) && defaultSafeSearch is not ("0" or "1" or "2"))
|
||||
{
|
||||
return Task.FromResult<ToolConfigurationState?>(new ToolConfigurationState
|
||||
{
|
||||
IsConfigured = false,
|
||||
Message = TB("The default safe search setting must be 0, 1, or 2."),
|
||||
});
|
||||
}
|
||||
|
||||
if (!ToolSettingsValueParser.TryReadOptionalPositiveInt(settingsValues, "maxResults", positiveIntegerErrorFormat, out _, out var maxResultsError))
|
||||
{
|
||||
return Task.FromResult<ToolConfigurationState?>(new ToolConfigurationState
|
||||
|
||||
@ -98,6 +98,8 @@ public sealed class ToolCatalogItem
|
||||
|
||||
public required ToolConfigurationState ConfigurationState { get; init; }
|
||||
|
||||
public bool IsActive { get; init; }
|
||||
|
||||
public ConfidenceLevel MinimumProviderConfidence { get; init; } = ConfidenceLevel.NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -208,6 +208,7 @@ public sealed class ToolRegistry
|
||||
Definition = definition,
|
||||
Implementation = implementation,
|
||||
ConfigurationState = await this.toolSettingsService.GetConfigurationStateAsync(definition, implementation),
|
||||
IsActive = this.settingsManager.IsToolActive(definition.Id),
|
||||
MinimumProviderConfidence = this.settingsManager.GetMinimumProviderConfidenceForTool(definition.Id),
|
||||
});
|
||||
}
|
||||
@ -223,6 +224,12 @@ public sealed class ToolRegistry
|
||||
ConfidenceLevel providerConfidence,
|
||||
bool isToolSelectionVisible)
|
||||
{
|
||||
if (!this.settingsManager.AreToolsEnabled())
|
||||
{
|
||||
this.logger.LogInformation("Tool calling is skipped because tools are disabled by managed configuration.");
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!isToolSelectionVisible)
|
||||
{
|
||||
this.logger.LogInformation("Tool calling is skipped for component '{Component}' because tool selection is not visible.", component);
|
||||
@ -250,6 +257,12 @@ public sealed class ToolRegistry
|
||||
var result = new List<(ToolDefinition, IToolImplementation)>(definitions.Count);
|
||||
foreach (var definition in definitions)
|
||||
{
|
||||
if (!this.settingsManager.IsToolActive(definition.Id))
|
||||
{
|
||||
this.logger.LogInformation("Skipping tool '{ToolId}' because it is disabled by managed configuration.", definition.Id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.implementationsByKey.TryGetValue(definition.ImplementationKey, out var implementation))
|
||||
{
|
||||
this.logger.LogInformation("Skipping tool '{ToolId}' because no implementation is registered.", definition.Id);
|
||||
|
||||
@ -1,12 +1,30 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
namespace AIStudio.Tools.ToolCallingSystem;
|
||||
|
||||
public sealed class ToolSettingsService(SettingsManager settingsManager, RustService rustService)
|
||||
{
|
||||
private const string WEB_SEARCH_BASE_URL_FIELD = "baseUrl";
|
||||
private const string READ_WEB_PAGE_ALLOWED_PRIVATE_HOSTS_FIELD = "allowedPrivateHosts";
|
||||
private static readonly Dictionary<(string ToolId, string FieldName), ManagedToolSetting> MANAGED_SETTINGS = new()
|
||||
{
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "baseUrl")] = CreateManagedToolSetting(x => x.WebSearchBaseUrl, (tools, value) => tools.WebSearchBaseUrl = value),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "defaultLanguage")] = CreateManagedToolSetting(x => x.WebSearchDefaultLanguage),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "defaultSafeSearch")] = CreateManagedToolSetting(x => x.WebSearchDefaultSafeSearch),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "defaultCategories")] = CreateManagedToolSetting(x => x.WebSearchDefaultCategories),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "defaultEngines")] = CreateManagedToolSetting(x => x.WebSearchDefaultEngines),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "maxResults")] = CreateManagedToolSetting(x => x.WebSearchMaxResults),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "timeoutSeconds")] = CreateManagedToolSetting(x => x.WebSearchTimeoutSeconds),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "maxTotalContentCharacters")] = CreateManagedToolSetting(x => x.WebSearchMaxTotalContentCharacters),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "minContentCharactersPerResult")] = CreateManagedToolSetting(x => x.WebSearchMinContentCharactersPerResult),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "pageTimeoutSeconds")] = CreateManagedToolSetting(x => x.WebSearchPageTimeoutSeconds),
|
||||
[(ToolSelectionRules.WEB_SEARCH_TOOL_ID, "retrievalTimeoutSeconds")] = CreateManagedToolSetting(x => x.WebSearchRetrievalTimeoutSeconds),
|
||||
[(ToolSelectionRules.READ_WEB_PAGE_TOOL_ID, "timeoutSeconds")] = CreateManagedToolSetting(x => x.ReadWebPageTimeoutSeconds),
|
||||
[(ToolSelectionRules.READ_WEB_PAGE_TOOL_ID, "maxContentCharacters")] = CreateManagedToolSetting(x => x.ReadWebPageMaxContentCharacters),
|
||||
[(ToolSelectionRules.READ_WEB_PAGE_TOOL_ID, "allowedPrivateHosts")] = CreateManagedToolSetting(x => x.ReadWebPageAllowedPrivateHosts, (tools, value) => tools.ReadWebPageAllowedPrivateHosts = value),
|
||||
};
|
||||
|
||||
public async Task<Dictionary<string, string>> GetSettingsAsync(ToolDefinition definition)
|
||||
{
|
||||
@ -16,15 +34,16 @@ public sealed class ToolSettingsService(SettingsManager settingsManager, RustSer
|
||||
{
|
||||
var fieldName = property.Key;
|
||||
var fieldDefinition = property.Value;
|
||||
if (IsWebSearchBaseUrlField(definition, fieldName))
|
||||
if (TryGetManagedSetting(definition, fieldName, out var managedSetting))
|
||||
{
|
||||
values[fieldName] = settingsManager.ConfigurationData.Tools.WebSearchBaseUrl;
|
||||
continue;
|
||||
}
|
||||
var meta = managedSetting.GetMeta();
|
||||
if (meta?.IsLocked is true || managedSetting.SetLegacyLocalValue is not null)
|
||||
values[fieldName] = managedSetting.GetValue(settingsManager.ConfigurationData.Tools);
|
||||
else if (storedValues?.TryGetValue(fieldName, out var managedStoredValue) is true)
|
||||
values[fieldName] = managedStoredValue;
|
||||
else if (meta?.ManagedMode is ManagedConfigurationMode.EDITABLE_DEFAULT)
|
||||
values[fieldName] = managedSetting.GetValue(settingsManager.ConfigurationData.Tools);
|
||||
|
||||
if (IsReadWebPageAllowedPrivateHostsField(definition, fieldName))
|
||||
{
|
||||
values[fieldName] = settingsManager.ConfigurationData.Tools.ReadWebPageAllowedPrivateHosts;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -103,18 +122,15 @@ public sealed class ToolSettingsService(SettingsManager settingsManager, RustSer
|
||||
values.TryGetValue(fieldName, out var value);
|
||||
value ??= string.Empty;
|
||||
|
||||
if (IsWebSearchBaseUrlField(definition, fieldName))
|
||||
if (TryGetManagedSetting(definition, fieldName, out var managedSetting))
|
||||
{
|
||||
if (!IsWebSearchBaseUrlLocked())
|
||||
settingsManager.ConfigurationData.Tools.WebSearchBaseUrl = value;
|
||||
|
||||
if (managedSetting.GetMeta()?.IsLocked is true)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsReadWebPageAllowedPrivateHostsField(definition, fieldName))
|
||||
{
|
||||
if (!IsReadWebPageAllowedPrivateHostsLocked())
|
||||
settingsManager.ConfigurationData.Tools.ReadWebPageAllowedPrivateHosts = value;
|
||||
if (managedSetting.SetLegacyLocalValue is not null)
|
||||
managedSetting.SetLegacyLocalValue(settingsManager.ConfigurationData.Tools, value);
|
||||
else
|
||||
storedValues[fieldName] = value;
|
||||
|
||||
continue;
|
||||
}
|
||||
@ -137,17 +153,26 @@ public sealed class ToolSettingsService(SettingsManager settingsManager, RustSer
|
||||
await MessageBus.INSTANCE.SendMessage<object?>(null, Event.CONFIGURATION_CHANGED, null);
|
||||
}
|
||||
|
||||
private static bool IsWebSearchBaseUrlField(ToolDefinition definition, string fieldName) =>
|
||||
definition.Id.Equals(ToolSelectionRules.WEB_SEARCH_TOOL_ID, StringComparison.Ordinal) &&
|
||||
fieldName.Equals(WEB_SEARCH_BASE_URL_FIELD, StringComparison.Ordinal);
|
||||
public bool IsFieldLocked(ToolDefinition definition, string fieldName) =>
|
||||
TryGetManagedSetting(definition, fieldName, out var managedSetting) &&
|
||||
managedSetting.GetMeta()?.IsLocked is true;
|
||||
|
||||
private static bool IsWebSearchBaseUrlLocked() =>
|
||||
ManagedConfiguration.TryGet(x => x.Tools, x => x.WebSearchBaseUrl, out var meta) && meta.IsLocked;
|
||||
private static bool TryGetManagedSetting(ToolDefinition definition, string fieldName, out ManagedToolSetting managedSetting) =>
|
||||
MANAGED_SETTINGS.TryGetValue((definition.Id, fieldName), out managedSetting!);
|
||||
|
||||
private static bool IsReadWebPageAllowedPrivateHostsField(ToolDefinition definition, string fieldName) =>
|
||||
definition.Id.Equals(ToolSelectionRules.READ_WEB_PAGE_TOOL_ID, StringComparison.Ordinal) &&
|
||||
fieldName.Equals(READ_WEB_PAGE_ALLOWED_PRIVATE_HOSTS_FIELD, StringComparison.Ordinal);
|
||||
|
||||
private static bool IsReadWebPageAllowedPrivateHostsLocked() =>
|
||||
ManagedConfiguration.TryGet(x => x.Tools, x => x.ReadWebPageAllowedPrivateHosts, out var meta) && meta.IsLocked;
|
||||
private static ManagedToolSetting CreateManagedToolSetting(
|
||||
Expression<Func<DataTools, string>> propertyExpression,
|
||||
Action<DataTools, string>? setLegacyLocalValue = null)
|
||||
{
|
||||
var getValue = propertyExpression.Compile();
|
||||
return new ManagedToolSetting(
|
||||
getValue,
|
||||
() => ManagedConfiguration.TryGet(x => x.Tools, propertyExpression, out var meta) ? meta : null,
|
||||
setLegacyLocalValue);
|
||||
}
|
||||
|
||||
private sealed record ManagedToolSetting(
|
||||
Func<DataTools, string> GetValue,
|
||||
Func<ConfigMeta<DataTools, string>?> GetMeta,
|
||||
Action<DataTools, string>? SetLegacyLocalValue);
|
||||
}
|
||||
|
||||
@ -1 +1,3 @@
|
||||
# v26.7.4, build 249 (2026-07-xx xx:xx UTC)
|
||||
|
||||
- Added organization-wide management for tool availability and all Web Search and Read Web Page settings.
|
||||
|
||||
@ -222,7 +222,7 @@ All values must be positive. The total budget must be large enough to reserve th
|
||||
|
||||
The two tools can be selected independently. Tool policy text tells the model not to call `read_web_page` for a URL already returned by `web_search`, because the search result already contains that page's retrieved content.
|
||||
|
||||
For settings that administrators should be able to manage centrally, add the setting to the appropriate `Settings/DataModel` class, register it with `ManagedConfiguration.Register(...)`, process it in `PluginConfiguration`, clean leftovers in `PluginFactory.Loading`, and document it in `Plugins/configuration/plugin.lua`.
|
||||
Every non-secret tool field that administrators should be able to manage centrally must have an explicit enterprise mapping in `ToolSettingsService`. Add its backing setting to the appropriate `Settings/DataModel` class, register it with `ManagedConfiguration.Register(...)`, process it in `PluginConfiguration`, clean leftovers in `PluginFactory.Loading`, and document its allowed values, default, and limits in `Plugins/configuration/plugin.lua`. Locked enterprise values override the local field, while editable enterprise defaults apply only until a user saves a local value. Secret fields require the existing OS-keyring path and must not be routed through plain enterprise settings.
|
||||
|
||||
## Checklist
|
||||
|
||||
@ -230,6 +230,7 @@ For settings that administrators should be able to manage centrally, add the set
|
||||
- Add the `IToolImplementation` class.
|
||||
- Register the implementation in `Program.cs`.
|
||||
- Validate settings and model arguments.
|
||||
- Add the enterprise mapping for each administratively configurable non-secret setting.
|
||||
- Protect secrets and sensitive trace arguments.
|
||||
- Add provider-confidence checks when tool output may contain sensitive data.
|
||||
- Update configuration plugin documentation when admins can manage the setting.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user