using AIStudio.Provider; using AIStudio.Tools.PluginSystem; using SharedTools; using LuaTable = Lua.LuaTable; namespace AIStudio.Settings.DataModel; public sealed record DataDocumentAnalysisPolicy : ConfigurationBaseObject { private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger(); /// public override string Id { get; init; } = string.Empty; /// public override uint Num { get; init; } /// public override string Name { get => this.PolicyName; init => this.PolicyName = value; } /// public override bool IsEnterpriseConfiguration { get; init; } /// /// The name of the document analysis policy. /// public string PolicyName { get; set; } = string.Empty; /// /// The description of the document analysis policy. /// public string PolicyDescription { get; set; } = string.Empty; /// /// Is this policy protected? If so, it cannot be deleted or modified by the user. /// public bool IsProtected { get; set; } /// public override Guid EnterpriseConfigurationPluginId { get; init; } = Guid.Empty; /// /// The rules for the document analysis policy. /// public string AnalysisRules { get; set; } = string.Empty; /// /// The rules for the output of the document analysis, e.g., the desired format, structure, etc. /// public string OutputRules { get; set; } = string.Empty; /// /// The minimum confidence level required for a provider to be considered. /// public ConfidenceLevel MinimumProviderConfidence { get; set; } = ConfidenceLevel.NONE; /// /// The tools this policy permits the model to use. /// /// /// 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.

/// 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. ///
public HashSet AllowedToolIds { get; set; } = []; /// /// Which LLM provider should be preselected? /// public string PreselectedProvider { get; set; } = string.Empty; /// /// Preselect a profile? /// public string PreselectedProfile { get; set; } = string.Empty; /// /// Hide the policy definition section in the UI? /// If true, the policy definition panel will be hidden and only the document selection will be shown. /// This is useful for enterprise configurations where users should not see or modify the policy details. /// public bool HidePolicyDefinition { get; set; } public static bool TryProcessConfiguration(int idx, LuaTable table, Guid configPluginId, out ConfigurationBaseObject policy) { policy = new DataDocumentAnalysisPolicy(); if (!table.TryGetValue("Id", out var idValue) || !idValue.TryRead(out var idText) || !Guid.TryParse(idText, out var id)) { LOG.LogWarning("The configured document analysis policy {PolicyIndex} does not contain a valid ID. The ID must be a valid GUID.", idx); return false; } if (!table.TryGetValue("PolicyName", out var nameValue) || !nameValue.TryRead(out var name) || string.IsNullOrWhiteSpace(name)) { LOG.LogWarning("The configured document analysis policy {PolicyIndex} does not contain a valid PolicyName field.", idx); return false; } if (!table.TryGetValue("PolicyDescription", out var descriptionValue) || !descriptionValue.TryRead(out var description) || string.IsNullOrWhiteSpace(description)) { LOG.LogWarning("The configured document analysis policy {PolicyIndex} does not contain a valid PolicyDescription field.", idx); return false; } if (!table.TryGetValue("AnalysisRules", out var analysisRulesValue) || !analysisRulesValue.TryRead(out var analysisRules) || string.IsNullOrWhiteSpace(analysisRules)) { LOG.LogWarning("The configured document analysis policy {PolicyIndex} does not contain valid AnalysisRules field.", idx); return false; } if (!table.TryGetValue("OutputRules", out var outputRulesValue) || !outputRulesValue.TryRead(out var outputRules) || string.IsNullOrWhiteSpace(outputRules)) { LOG.LogWarning("The configured document analysis policy {PolicyIndex} does not contain valid OutputRules field.", idx); return false; } var minimumConfidence = ConfidenceLevel.NONE; if (table.TryGetValue("MinimumProviderConfidence", out var minConfValue) && minConfValue.TryRead(out var minConfText)) { if (!Enum.TryParse(minConfText, true, out minimumConfidence)) { LOG.LogWarning("The configured document analysis policy {PolicyIndex} contains an invalid MinimumProviderConfidence: {ConfidenceLevel}.", idx, minConfText); minimumConfidence = ConfidenceLevel.NONE; } } var preselectedProvider = string.Empty; if (table.TryGetValue("PreselectedProvider", out var providerValue) && providerValue.TryRead(out var providerId)) preselectedProvider = providerId; var preselectedProfile = string.Empty; if (table.TryGetValue("PreselectedProfile", out var profileValue) && profileValue.TryRead(out var profileId)) preselectedProfile = profileId; var hidePolicyDefinition = false; if (table.TryGetValue("HidePolicyDefinition", out var hideValue) && hideValue.TryRead(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(StringComparer.Ordinal); if (table.TryGetValue("AllowedToolIds", out var toolIdsValue) && toolIdsValue.TryRead(out var toolIdsTable)) { for (var toolIdx = 1; toolIdx <= toolIdsTable.ArrayLength; toolIdx++) { if (toolIdsTable[toolIdx].TryRead(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(), Num = 0, // will be set later by the PluginConfigurationObject PolicyName = name, PolicyDescription = description, AnalysisRules = analysisRules, OutputRules = outputRules, MinimumProviderConfidence = minimumConfidence, AllowedToolIds = allowedToolIds, PreselectedProvider = preselectedProvider, PreselectedProfile = preselectedProfile, HidePolicyDefinition = hidePolicyDefinition, IsProtected = true, IsEnterpriseConfiguration = true, EnterpriseConfigurationPluginId = configPluginId, }; return true; } /// /// Exports the policy as a Lua configuration section. /// /// /// Unlike the other exports, this one keeps the ID of the policy. /// /// A Lua configuration section string. public string ExportAsConfigurationSection() { var preselectedProvider = string.IsNullOrWhiteSpace(this.PreselectedProvider) ? string.Empty : this.PreselectedProvider; var preselectedProfile = string.IsNullOrWhiteSpace(this.PreselectedProfile) ? string.Empty : this.PreselectedProfile; var id = string.IsNullOrWhiteSpace(this.Id) ? Guid.NewGuid().ToString() : this.Id; var allowedToolIds = string.Join(", ", this.AllowedToolIds.OrderBy(x => x, StringComparer.Ordinal).Select(x => LuaTools.ToLuaStringLiteral(x))); return $$""" CONFIG["DOCUMENT_ANALYSIS_POLICIES"][#CONFIG["DOCUMENT_ANALYSIS_POLICIES"]+1] = { ["Id"] = "{{LuaTools.EscapeLuaString(id)}}", ["PolicyName"] = {{LuaTools.ToLuaStringLiteral(this.PolicyName.Trim())}}, ["PolicyDescription"] = {{LuaTools.ToLuaStringLiteral(this.PolicyDescription.Trim())}}, ["AnalysisRules"] = {{LuaTools.ToLuaStringLiteral(this.AnalysisRules.Trim(), forceLongString: true)}}, ["OutputRules"] = {{LuaTools.ToLuaStringLiteral(this.OutputRules.Trim(), forceLongString: true)}}, -- Optional: minimum provider confidence required for this policy. -- Allowed values are: NONE, VERY_LOW, LOW, MODERATE, MEDIUM, HIGH ["MinimumProviderConfidence"] = "{{this.MinimumProviderConfidence}}", -- The tools an analysis with this policy may use, by tool ID. -- This is a limit, not a preselection: a tool which is not listed here cannot -- be used for this policy. An empty list means no tools. A listed tool must -- still meet the confidence requirements of the provider in use. ["AllowedToolIds"] = { {{allowedToolIds}} }, -- Optional: preselect a provider or profile by ID. -- The IDs must exist in CONFIG["LLM_PROVIDERS"] or CONFIG["PROFILES"]. ["PreselectedProvider"] = "{{LuaTools.EscapeLuaString(preselectedProvider)}}", ["PreselectedProfile"] = "{{LuaTools.EscapeLuaString(preselectedProfile)}}", -- Optional: hide the policy definition section in the UI. -- When set to true, users will only see the document selection interface -- and cannot view or modify the policy settings. -- This is useful for enterprise configurations where policy details should remain hidden. -- Allowed values are: true, false (default: false) ["HidePolicyDefinition"] = {{this.HidePolicyDefinition.ToString().ToLowerInvariant()}}, } """; } }