Added tool calling support (#731)

Co-authored-by: krut_ni <nils.kruthoff@dlr.de>
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-09-04 15:48:07 +02:00
1 parent b00c3f9ab3
commit 4d8d30e15e
266 files changed
+11186 -740

No files matched your search

@@ -194,4 +194,6 @@ public sealed class Data
public DataBiasOfTheDay BiasOfTheDay { get; init; } = new();
public DataI18N I18N { get; init; } = new();
}
public DataTools Tools { get; init; } = new(x => x.Tools);
}
@@ -57,6 +57,19 @@ public sealed record DataDocumentAnalysisPolicy : ConfigurationBaseObject
/// The minimum confidence level required for a provider to be considered.
/// </summary>
public ConfidenceLevel MinimumProviderConfidence { get; set; } = ConfidenceLevel.NONE;
/// <summary>
/// The tools this policy permits the model to use.
/// </summary>
/// <remarks>
/// A limit, not a preselection: a tool absent from this list cannot be chosen for a run of this
/// policy. Empty therefore means no tools at all, which is what a policy written before this
/// field existed gets — an analysis keeps working exactly as its author wrote it.<br/><br/>
/// This narrows what the user may pick; it never widens what a tool is allowed to do. Every
/// permitted tool still has to pass the provider confidence checks, so a tool demanding High
/// confidence stays out of reach of a weaker provider whether a policy lists it or not.
/// </remarks>
public HashSet<string> AllowedToolIds { get; set; } = [];
/// <summary>
/// Which LLM provider should be preselected?
@@ -130,6 +143,23 @@ public sealed record DataDocumentAnalysisPolicy : ConfigurationBaseObject
if (table.TryGetValue("HidePolicyDefinition", out var hideValue) && hideValue.TryRead<bool>(out var hide))
hidePolicyDefinition = hide;
//
// Unknown tool IDs are kept rather than rejected: an organization may roll out a policy
// before the plugin providing that tool reaches every workstation. A tool that does not
// exist simply never shows up, and the policy starts working once it does.
//
var allowedToolIds = new HashSet<string>(StringComparer.Ordinal);
if (table.TryGetValue("AllowedToolIds", out var toolIdsValue) && toolIdsValue.TryRead<LuaTable>(out var toolIdsTable))
{
for (var toolIdx = 1; toolIdx <= toolIdsTable.ArrayLength; toolIdx++)
{
if (toolIdsTable[toolIdx].TryRead<string>(out var toolId) && !string.IsNullOrWhiteSpace(toolId))
allowedToolIds.Add(toolId.Trim());
else
LOG.LogWarning("The configured document analysis policy {PolicyIndex} contains an invalid entry in its AllowedToolIds list.", idx);
}
}
policy = new DataDocumentAnalysisPolicy
{
Id = id.ToString(),
@@ -139,6 +169,7 @@ public sealed record DataDocumentAnalysisPolicy : ConfigurationBaseObject
AnalysisRules = analysisRules,
OutputRules = outputRules,
MinimumProviderConfidence = minimumConfidence,
AllowedToolIds = allowedToolIds,
PreselectedProvider = preselectedProvider,
PreselectedProfile = preselectedProfile,
HidePolicyDefinition = hidePolicyDefinition,
@@ -0,0 +1,64 @@
using System.Linq.Expressions;
namespace AIStudio.Settings.DataModel;
public sealed class DataTools(Expression<Func<Data, DataTools>>? configSelection = null)
{
public DataTools() : this(null)
{
}
/// <summary>
/// The settings the user entered per tool: tool ID, then field name.
/// </summary>
public Dictionary<string, Dictionary<string, string>> Settings { get; set; } = [];
public Dictionary<string, HashSet<string>> DefaultToolIdsByComponent { 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(
configSelection,
x => x.MinimumProviderConfidenceByToolId,
new Dictionary<string, string>(StringComparer.Ordinal));
/// <summary>
/// Tool settings an organization fixed, which the user cannot change. Keys are
/// "toolId.fieldName".
/// </summary>
/// <remarks>
/// Keyed by tool and field rather than held in a property per setting, because a property per
/// setting only works for the tools AI Studio ships. Tools defined by plugin authors are not
/// known at compile time, yet an organization has to be able to configure them the same way.
/// <br/><br/>
/// Secrets never travel this way. They belong in the operating system's keyring, which a
/// configuration file cannot reach.
/// </remarks>
public Dictionary<string, string> LockedToolSettings { get; set; } = ManagedConfiguration.Register(
configSelection,
x => x.LockedToolSettings,
new Dictionary<string, string>(StringComparer.Ordinal));
/// <summary>
/// Tool settings an organization pre-filled but left changeable. Keys are "toolId.fieldName".
/// </summary>
/// <remarks>
/// Applies until the user saves a value of their own, which then wins. That is the difference
/// to the locked settings above, and the reason both exist: an organization can fix the search
/// instance while leaving the timeouts to the user.
/// </remarks>
public Dictionary<string, string> DefaultToolSettings { get; set; } = ManagedConfiguration.Register(
configSelection,
x => x.DefaultToolSettings,
new Dictionary<string, string>(StringComparer.Ordinal));
}