mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-24 20:52:11 +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"/>
|
<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" />
|
<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
|
-- Tool Settings
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T3730473128"] = "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
|
-- Status
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T6222351"] = "Status"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::SETTINGS::SETTINGSPANELTOOLS::T6222351"] = "Status"
|
||||||
|
|
||||||
@ -3724,6 +3727,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3119156561"] = "Required
|
|||||||
-- Close
|
-- Close
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3448155331"] = "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.
|
-- No tools are available in this context.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::TOOLSELECTION::T3904490680"] = "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
|
-- Tool Settings
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3730473128"] = "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.
|
-- The selected tool could not be loaded.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::TOOLSETTINGSDIALOG::T3907843187"] = "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.
|
-- 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."
|
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.
|
-- 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."
|
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.")"/>
|
<ProfileSelection MarginLeft="" CurrentProfile="@this.currentProfile" CurrentProfileChanged="@this.ProfileWasChanged" Disabled="@(!this.currentChatTemplate.AllowProfileUsage)" DisabledText="@T("Profile usage is disabled according to your chat template settings.")"/>
|
||||||
|
|
||||||
<ToolSelection Component="Components.CHAT" LLMProvider="@this.Provider" SelectedToolIds="@this.selectedToolIds" SelectedToolIdsChanged="@this.SelectedToolIdsChanged" Disabled="@this.IsCurrentChatStreaming" />
|
@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))
|
@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -37,7 +37,13 @@
|
|||||||
</MudMenu>
|
</MudMenu>
|
||||||
</MudTd>
|
</MudTd>
|
||||||
<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" />
|
<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))" />
|
<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.Component is not AIStudio.Tools.Components.CHAT &&
|
||||||
!this.SettingsManager.IsToolSelectionVisible(this.Component);
|
!this.SettingsManager.IsToolSelectionVisible(this.Component);
|
||||||
|
|
||||||
|
private bool IsToolDisabled(string toolId) => !this.SettingsManager.IsToolActive(toolId);
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
this.availableTools = (await this.ToolRegistry.GetCatalogAsync(this.Component))
|
this.availableTools = (await this.ToolRegistry.GetCatalogAsync(this.Component))
|
||||||
|
|||||||
@ -47,8 +47,14 @@
|
|||||||
<MudPaper Class="pa-2 mb-2 border rounded-lg">
|
<MudPaper Class="pa-2 mb-2 border rounded-lg">
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween">
|
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween">
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
<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" />
|
<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()">
|
<MudTooltip Text="@item.Implementation.GetDescription()">
|
||||||
<MudText Typo="Typo.body1">@item.Implementation.GetDisplayName()</MudText>
|
<MudText Typo="Typo.body1">@item.Implementation.GetDisplayName()</MudText>
|
||||||
</MudTooltip>
|
</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>
|
<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))
|
@if (!string.IsNullOrWhiteSpace(providerConfidenceHint))
|
||||||
{
|
{
|
||||||
<MudText Typo="Typo.caption" Color="Color.Warning">@providerConfidenceHint</MudText>
|
<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)
|
private async Task ChangeSelection(string toolId, bool isSelected)
|
||||||
{
|
{
|
||||||
|
if (isSelected && !this.SettingsManager.IsToolActive(toolId))
|
||||||
|
return;
|
||||||
|
|
||||||
var updated = new HashSet<string>(this.SelectedToolIds, StringComparer.Ordinal);
|
var updated = new HashSet<string>(this.SelectedToolIds, StringComparer.Ordinal);
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
updated.Add(toolId);
|
updated.Add(toolId);
|
||||||
|
|||||||
@ -19,6 +19,11 @@
|
|||||||
@this.implementation?.GetDescription()
|
@this.implementation?.GetDescription()
|
||||||
</MudJustifiedText>
|
</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))
|
@if (!string.IsNullOrWhiteSpace(this.validationMessage))
|
||||||
{
|
{
|
||||||
<MudAlert Severity="Severity.Error" Class="mb-4">@this.validationMessage</MudAlert>
|
<MudAlert Severity="Severity.Error" Class="mb-4">@this.validationMessage</MudAlert>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
using AIStudio.Settings;
|
|
||||||
using AIStudio.Tools.ToolCallingSystem;
|
using AIStudio.Tools.ToolCallingSystem;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
@ -53,19 +52,8 @@ public partial class ToolSettingsDialog : SettingsDialogBase
|
|||||||
return string.Format(T("{0} Default: {1}"), description, defaultValue);
|
return string.Format(T("{0} Default: {1}"), description, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsFieldDisabled(string fieldName)
|
private bool IsFieldDisabled(string fieldName) =>
|
||||||
{
|
this.toolDefinition is not null && this.ToolSettingsService.IsFieldLocked(this.toolDefinition, 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 string GetFieldPlaceholder(string fieldName, ToolSettingsFieldDefinition fieldDefinition) =>
|
private string GetFieldPlaceholder(string fieldName, ToolSettingsFieldDefinition fieldDefinition) =>
|
||||||
string.IsNullOrWhiteSpace(this.GetValue(fieldName)) ? this.GetFieldDefaultValue(fieldName, fieldDefinition) : string.Empty;
|
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"
|
-- Examples are: "CmdOrControl+Shift+D", "Alt+F9", "F8"
|
||||||
-- CONFIG["SETTINGS"]["DataApp.ShortcutVoiceRecording"] = "CmdOrControl+1"
|
-- 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.
|
-- Configure the minimum provider confidence level required for individual tools.
|
||||||
-- Tool IDs include: web_search, read_web_page
|
-- Tool IDs include: web_search, read_web_page
|
||||||
-- Allowed values are: NONE, UNTRUSTED, VERY_LOW, LOW, MODERATE, MEDIUM, HIGH
|
-- Allowed values are: NONE, UNTRUSTED, VERY_LOW, LOW, MODERATE, MEDIUM, HIGH
|
||||||
@ -365,21 +374,47 @@ CONFIG["SETTINGS"] = {}
|
|||||||
-- ["read_web_page"] = "MEDIUM"
|
-- ["read_web_page"] = "MEDIUM"
|
||||||
-- }
|
-- }
|
||||||
|
|
||||||
-- Configure the SearXNG instance URL used by the Web Search tool.
|
-- Configure the Web Search tool. All values are strings.
|
||||||
-- You can enter either the instance root URL or the /search endpoint.
|
-- WebSearchBaseUrl: required SearXNG HTTP(S) root URL or /search endpoint; no default.
|
||||||
-- CONFIG["SETTINGS"]["DataTools.WebSearchBaseUrl"] = "https://searxng.website/"
|
-- 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.
|
-- Configure the Read Web Page tool. All values are strings.
|
||||||
-- Public web pages do not need to be listed here.
|
-- ReadWebPageTimeoutSeconds: positive integer; default 30, effective maximum 60.
|
||||||
-- Private hosts listed here still require a provider with HIGH confidence before any page content is sent to the model.
|
-- CONFIG["SETTINGS"]["DataTools.ReadWebPageTimeoutSeconds"] = "30"
|
||||||
-- For hosts on this allowlist, AI Studio also tries the current user's operating-system sign-in
|
-- ReadWebPageMaxContentCharacters: positive integer; default 30000, effective maximum 50000.
|
||||||
-- automatically when the server requests integrated authentication (for example Kerberos or NTLM).
|
-- CONFIG["SETTINGS"]["DataTools.ReadWebPageMaxContentCharacters"] = "30000"
|
||||||
-- This does not reuse Firefox cookies or an existing browser session.
|
-- ReadWebPageAllowedPrivateHosts: optional comma-separated private or VPN host patterns; default is empty.
|
||||||
-- Separate host patterns with commas. Wildcards only match subdomains, so add the root domain separately if needed.
|
-- Public pages do not need to be listed. Wildcards only match subdomains, so add the root domain separately.
|
||||||
-- Examples:
|
-- 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"] = "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.
|
-- Configure the HTTP timeout for external requests, in seconds.
|
||||||
-- The default is 3600 (1 hour).
|
-- 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 providerConfidence = this.Provider.GetConfidence(settingsManager).Level;
|
||||||
var minimumWebSearchConfidence = settingsManager.GetMinimumProviderConfidenceForTool(ToolSelectionRules.WEB_SEARCH_TOOL_ID);
|
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
|
IList<object> providerTools = modelCapabilities.Contains(Capability.WEB_SEARCH) && isWebSearchAllowed
|
||||||
? [ ProviderTools.WEB_SEARCH ]
|
? [ ProviderTools.WEB_SEARCH ]
|
||||||
: [];
|
: [];
|
||||||
|
|||||||
@ -16,6 +16,16 @@ public sealed class DataTools(Expression<Func<Data, DataTools>>? configSelection
|
|||||||
|
|
||||||
public HashSet<string> VisibleToolSelectionComponents { get; set; } = [];
|
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>>(
|
public Dictionary<string, string> MinimumProviderConfidenceByToolId { get; set; } = ManagedConfiguration.Register<DataTools, Dictionary<string, string>>(
|
||||||
configSelection,
|
configSelection,
|
||||||
x => x.MinimumProviderConfidenceByToolId,
|
x => x.MinimumProviderConfidenceByToolId,
|
||||||
@ -26,6 +36,66 @@ public sealed class DataTools(Expression<Func<Data, DataTools>>? configSelection
|
|||||||
x => x.WebSearchBaseUrl,
|
x => x.WebSearchBaseUrl,
|
||||||
string.Empty);
|
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>(
|
public string ReadWebPageAllowedPrivateHosts { get; set; } = ManagedConfiguration.Register<DataTools>(
|
||||||
configSelection,
|
configSelection,
|
||||||
x => x.ReadWebPageAllowedPrivateHosts,
|
x => x.ReadWebPageAllowedPrivateHosts,
|
||||||
|
|||||||
@ -594,6 +594,9 @@ public sealed class SettingsManager
|
|||||||
|
|
||||||
public HashSet<string> FilterToolIdsForProvider(AIStudio.Settings.Provider provider, IEnumerable<string> selectedToolIds)
|
public HashSet<string> FilterToolIdsForProvider(AIStudio.Settings.Provider provider, IEnumerable<string> selectedToolIds)
|
||||||
{
|
{
|
||||||
|
if (!this.AreToolsEnabled())
|
||||||
|
return [];
|
||||||
|
|
||||||
var toolCallingAvailability = provider.GetToolCallingAvailability();
|
var toolCallingAvailability = provider.GetToolCallingAvailability();
|
||||||
if (!toolCallingAvailability.IsAvailable)
|
if (!toolCallingAvailability.IsAvailable)
|
||||||
return [];
|
return [];
|
||||||
@ -610,6 +613,12 @@ public sealed class SettingsManager
|
|||||||
|
|
||||||
foreach (var toolId in filtered.ToList())
|
foreach (var toolId in filtered.ToList())
|
||||||
{
|
{
|
||||||
|
if (!this.IsToolActive(toolId))
|
||||||
|
{
|
||||||
|
filtered.Remove(toolId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var minimumToolConfidence = this.GetMinimumProviderConfidenceForTool(toolId);
|
var minimumToolConfidence = this.GetMinimumProviderConfidenceForTool(toolId);
|
||||||
if (!ToolSelectionRules.IsProviderConfidenceAllowed(providerConfidence, minimumToolConfidence))
|
if (!ToolSelectionRules.IsProviderConfidenceAllowed(providerConfidence, minimumToolConfidence))
|
||||||
filtered.Remove(toolId);
|
filtered.Remove(toolId);
|
||||||
@ -618,6 +627,12 @@ public sealed class SettingsManager
|
|||||||
return filtered;
|
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
|
public bool IsToolSelectionVisible(AIStudio.Tools.Components component) => component switch
|
||||||
{
|
{
|
||||||
AIStudio.Tools.Components.CHAT => true,
|
AIStudio.Tools.Components.CHAT => true,
|
||||||
@ -772,4 +787,4 @@ public sealed class SettingsManager
|
|||||||
// Return the full name of the property, including the class name:
|
// Return the full name of the property, including the class name:
|
||||||
return $"{typeof(TIn).Name}.{memberExpr.Member.Name}";
|
return $"{typeof(TIn).Name}.{memberExpr.Member.Name}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -199,13 +199,29 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
|||||||
// Config: global voice recording shortcut
|
// Config: global voice recording shortcut
|
||||||
ManagedConfiguration.TryProcessConfiguration(x => x.App, x => x.ShortcutVoiceRecording, this.Id, settingsTable, dryRun);
|
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
|
// Config: minimum provider confidence per tool
|
||||||
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.MinimumProviderConfidenceByToolId, this.Id, settingsTable, dryRun);
|
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.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);
|
ManagedConfiguration.TryProcessConfiguration(x => x.Tools, x => x.ReadWebPageAllowedPrivateHosts, this.Id, settingsTable, dryRun);
|
||||||
|
|
||||||
// Config: timeout for external HTTP requests
|
// 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))
|
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.App, x => x.ShortcutVoiceRecording, AVAILABLE_PLUGINS))
|
||||||
wasConfigurationChanged = true;
|
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:
|
// Check for minimum provider confidence per tool:
|
||||||
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.MinimumProviderConfidenceByToolId, AVAILABLE_PLUGINS))
|
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.MinimumProviderConfidenceByToolId, AVAILABLE_PLUGINS))
|
||||||
wasConfigurationChanged = true;
|
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))
|
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.WebSearchBaseUrl, AVAILABLE_PLUGINS))
|
||||||
wasConfigurationChanged = true;
|
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))
|
if(ManagedConfiguration.IsConfigurationLeftOver(x => x.Tools, x => x.ReadWebPageAllowedPrivateHosts, AVAILABLE_PLUGINS))
|
||||||
wasConfigurationChanged = true;
|
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))
|
if (!ToolSettingsValueParser.TryReadOptionalPositiveInt(settingsValues, "maxResults", positiveIntegerErrorFormat, out _, out var maxResultsError))
|
||||||
{
|
{
|
||||||
return Task.FromResult<ToolConfigurationState?>(new ToolConfigurationState
|
return Task.FromResult<ToolConfigurationState?>(new ToolConfigurationState
|
||||||
|
|||||||
@ -98,6 +98,8 @@ public sealed class ToolCatalogItem
|
|||||||
|
|
||||||
public required ToolConfigurationState ConfigurationState { get; init; }
|
public required ToolConfigurationState ConfigurationState { get; init; }
|
||||||
|
|
||||||
|
public bool IsActive { get; init; }
|
||||||
|
|
||||||
public ConfidenceLevel MinimumProviderConfidence { get; init; } = ConfidenceLevel.NONE;
|
public ConfidenceLevel MinimumProviderConfidence { get; init; } = ConfidenceLevel.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -208,6 +208,7 @@ public sealed class ToolRegistry
|
|||||||
Definition = definition,
|
Definition = definition,
|
||||||
Implementation = implementation,
|
Implementation = implementation,
|
||||||
ConfigurationState = await this.toolSettingsService.GetConfigurationStateAsync(definition, implementation),
|
ConfigurationState = await this.toolSettingsService.GetConfigurationStateAsync(definition, implementation),
|
||||||
|
IsActive = this.settingsManager.IsToolActive(definition.Id),
|
||||||
MinimumProviderConfidence = this.settingsManager.GetMinimumProviderConfidenceForTool(definition.Id),
|
MinimumProviderConfidence = this.settingsManager.GetMinimumProviderConfidenceForTool(definition.Id),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -223,6 +224,12 @@ public sealed class ToolRegistry
|
|||||||
ConfidenceLevel providerConfidence,
|
ConfidenceLevel providerConfidence,
|
||||||
bool isToolSelectionVisible)
|
bool isToolSelectionVisible)
|
||||||
{
|
{
|
||||||
|
if (!this.settingsManager.AreToolsEnabled())
|
||||||
|
{
|
||||||
|
this.logger.LogInformation("Tool calling is skipped because tools are disabled by managed configuration.");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
if (!isToolSelectionVisible)
|
if (!isToolSelectionVisible)
|
||||||
{
|
{
|
||||||
this.logger.LogInformation("Tool calling is skipped for component '{Component}' because tool selection is not visible.", component);
|
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);
|
var result = new List<(ToolDefinition, IToolImplementation)>(definitions.Count);
|
||||||
foreach (var definition in definitions)
|
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))
|
if (!this.implementationsByKey.TryGetValue(definition.ImplementationKey, out var implementation))
|
||||||
{
|
{
|
||||||
this.logger.LogInformation("Skipping tool '{ToolId}' because no implementation is registered.", definition.Id);
|
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;
|
||||||
|
using AIStudio.Settings.DataModel;
|
||||||
using AIStudio.Tools.Services;
|
using AIStudio.Tools.Services;
|
||||||
|
|
||||||
namespace AIStudio.Tools.ToolCallingSystem;
|
namespace AIStudio.Tools.ToolCallingSystem;
|
||||||
|
|
||||||
public sealed class ToolSettingsService(SettingsManager settingsManager, RustService rustService)
|
public sealed class ToolSettingsService(SettingsManager settingsManager, RustService rustService)
|
||||||
{
|
{
|
||||||
private const string WEB_SEARCH_BASE_URL_FIELD = "baseUrl";
|
private static readonly Dictionary<(string ToolId, string FieldName), ManagedToolSetting> MANAGED_SETTINGS = new()
|
||||||
private const string READ_WEB_PAGE_ALLOWED_PRIVATE_HOSTS_FIELD = "allowedPrivateHosts";
|
{
|
||||||
|
[(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)
|
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 fieldName = property.Key;
|
||||||
var fieldDefinition = property.Value;
|
var fieldDefinition = property.Value;
|
||||||
if (IsWebSearchBaseUrlField(definition, fieldName))
|
if (TryGetManagedSetting(definition, fieldName, out var managedSetting))
|
||||||
{
|
{
|
||||||
values[fieldName] = settingsManager.ConfigurationData.Tools.WebSearchBaseUrl;
|
var meta = managedSetting.GetMeta();
|
||||||
continue;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,18 +122,15 @@ public sealed class ToolSettingsService(SettingsManager settingsManager, RustSer
|
|||||||
values.TryGetValue(fieldName, out var value);
|
values.TryGetValue(fieldName, out var value);
|
||||||
value ??= string.Empty;
|
value ??= string.Empty;
|
||||||
|
|
||||||
if (IsWebSearchBaseUrlField(definition, fieldName))
|
if (TryGetManagedSetting(definition, fieldName, out var managedSetting))
|
||||||
{
|
{
|
||||||
if (!IsWebSearchBaseUrlLocked())
|
if (managedSetting.GetMeta()?.IsLocked is true)
|
||||||
settingsManager.ConfigurationData.Tools.WebSearchBaseUrl = value;
|
continue;
|
||||||
|
|
||||||
continue;
|
if (managedSetting.SetLegacyLocalValue is not null)
|
||||||
}
|
managedSetting.SetLegacyLocalValue(settingsManager.ConfigurationData.Tools, value);
|
||||||
|
else
|
||||||
if (IsReadWebPageAllowedPrivateHostsField(definition, fieldName))
|
storedValues[fieldName] = value;
|
||||||
{
|
|
||||||
if (!IsReadWebPageAllowedPrivateHostsLocked())
|
|
||||||
settingsManager.ConfigurationData.Tools.ReadWebPageAllowedPrivateHosts = value;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -137,17 +153,26 @@ public sealed class ToolSettingsService(SettingsManager settingsManager, RustSer
|
|||||||
await MessageBus.INSTANCE.SendMessage<object?>(null, Event.CONFIGURATION_CHANGED, null);
|
await MessageBus.INSTANCE.SendMessage<object?>(null, Event.CONFIGURATION_CHANGED, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsWebSearchBaseUrlField(ToolDefinition definition, string fieldName) =>
|
public bool IsFieldLocked(ToolDefinition definition, string fieldName) =>
|
||||||
definition.Id.Equals(ToolSelectionRules.WEB_SEARCH_TOOL_ID, StringComparison.Ordinal) &&
|
TryGetManagedSetting(definition, fieldName, out var managedSetting) &&
|
||||||
fieldName.Equals(WEB_SEARCH_BASE_URL_FIELD, StringComparison.Ordinal);
|
managedSetting.GetMeta()?.IsLocked is true;
|
||||||
|
|
||||||
private static bool IsWebSearchBaseUrlLocked() =>
|
private static bool TryGetManagedSetting(ToolDefinition definition, string fieldName, out ManagedToolSetting managedSetting) =>
|
||||||
ManagedConfiguration.TryGet(x => x.Tools, x => x.WebSearchBaseUrl, out var meta) && meta.IsLocked;
|
MANAGED_SETTINGS.TryGetValue((definition.Id, fieldName), out managedSetting!);
|
||||||
|
|
||||||
private static bool IsReadWebPageAllowedPrivateHostsField(ToolDefinition definition, string fieldName) =>
|
private static ManagedToolSetting CreateManagedToolSetting(
|
||||||
definition.Id.Equals(ToolSelectionRules.READ_WEB_PAGE_TOOL_ID, StringComparison.Ordinal) &&
|
Expression<Func<DataTools, string>> propertyExpression,
|
||||||
fieldName.Equals(READ_WEB_PAGE_ALLOWED_PRIVATE_HOSTS_FIELD, StringComparison.Ordinal);
|
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 static bool IsReadWebPageAllowedPrivateHostsLocked() =>
|
private sealed record ManagedToolSetting(
|
||||||
ManagedConfiguration.TryGet(x => x.Tools, x => x.ReadWebPageAllowedPrivateHosts, out var meta) && meta.IsLocked;
|
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)
|
# 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.
|
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
|
## Checklist
|
||||||
|
|
||||||
@ -230,6 +230,7 @@ For settings that administrators should be able to manage centrally, add the set
|
|||||||
- Add the `IToolImplementation` class.
|
- Add the `IToolImplementation` class.
|
||||||
- Register the implementation in `Program.cs`.
|
- Register the implementation in `Program.cs`.
|
||||||
- Validate settings and model arguments.
|
- Validate settings and model arguments.
|
||||||
|
- Add the enterprise mapping for each administratively configurable non-secret setting.
|
||||||
- Protect secrets and sensitive trace arguments.
|
- Protect secrets and sensitive trace arguments.
|
||||||
- Add provider-confidence checks when tool output may contain sensitive data.
|
- Add provider-confidence checks when tool output may contain sensitive data.
|
||||||
- Update configuration plugin documentation when admins can manage the setting.
|
- Update configuration plugin documentation when admins can manage the setting.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user