mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-10 07:13:47 +00:00
Multiple Profiles can now be selected
This commit is contained in:
1 parent
d043fbc8f0
commit
cefc5464d5
89 files changed
+1360
-503
No files matched your search
+2
-1
@@ -1,4 +1,5 @@
|
||||
namespace AIStudio.Tools.PluginSystem.Assistants;
|
||||
|
||||
/// <param name="ProfileIds">The exact profiles to use, an empty list for none, or null for chat defaults.</param>
|
||||
/// <param name="ToolIds">The tools preselected for the chat, or null when the launcher names none.</param>
|
||||
public sealed record AssistantChatLaunchConfiguration(string WorkspaceName, Guid? ProviderId, Guid? ProfileId, Guid? ChatTemplateId, IReadOnlyList<Guid>? DataSourceIds, IReadOnlyList<string>? ToolIds);
|
||||
public sealed record AssistantChatLaunchConfiguration(string WorkspaceName, Guid? ProviderId, IReadOnlyList<Guid>? ProfileIds, Guid? ChatTemplateId, IReadOnlyList<Guid>? DataSourceIds, IReadOnlyList<string>? ToolIds);
|
||||
+11
-5
@@ -169,14 +169,20 @@ public static class DirectChatLauncherLuaWriter
|
||||
builder.AppendLine($" [\"WorkspaceName\"] = \"{Escape(definition.Launch.WorkspaceName.Trim())}\",");
|
||||
|
||||
//
|
||||
// Omitted IDs mean "use the chat defaults", while an empty GUID explicitly selects no
|
||||
// profile or no chat template. An empty provider GUID has no such meaning and is invalid:
|
||||
// Omitted IDs mean "use the chat defaults", while an empty profile list or chat-template
|
||||
// GUID explicitly selects none. An empty provider GUID has no such meaning and is invalid:
|
||||
//
|
||||
if (definition.Launch.ProviderId is { } providerId && providerId != Guid.Empty)
|
||||
builder.AppendLine($" [\"ProviderId\"] = \"{providerId}\",");
|
||||
|
||||
if (definition.Launch.ProfileId is { } profileId)
|
||||
builder.AppendLine($" [\"ProfileId\"] = \"{profileId}\",");
|
||||
if (definition.Launch.ProfileIds is { } profileIds)
|
||||
{
|
||||
builder.AppendLine(" [\"ProfileIds\"] = {");
|
||||
foreach (var profileId in profileIds)
|
||||
builder.AppendLine($" \"{profileId}\",");
|
||||
|
||||
builder.AppendLine(" },");
|
||||
}
|
||||
|
||||
if (definition.Launch.ChatTemplateId is { } chatTemplateId)
|
||||
builder.AppendLine($" [\"ChatTemplateId\"] = \"{chatTemplateId}\",");
|
||||
@@ -236,4 +242,4 @@ public static class DirectChatLauncherLuaWriter
|
||||
.Replace("\r", "\\r", StringComparison.Ordinal)
|
||||
.Replace("\n", "\\n", StringComparison.Ordinal)
|
||||
.Replace("\t", "\\t", StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Immutable;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||
using AIStudio.Tools.PluginSystem.Assistants.DataModel.Layout;
|
||||
using Lua;
|
||||
@@ -241,13 +242,13 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
|
||||
}
|
||||
|
||||
if (!TryReadOptionalGuid(assistantTable, "ProviderId", false, out var providerId, out message) ||
|
||||
!TryReadOptionalGuid(assistantTable, "ProfileId", true, out var profileId, out message) ||
|
||||
!TryReadOptionalProfileIds(assistantTable, out var profileIds, out message) ||
|
||||
!TryReadOptionalGuid(assistantTable, "ChatTemplateId", true, out var chatTemplateId, out message) ||
|
||||
!TryReadOptionalDataSourceIds(assistantTable, out var dataSourceIds, out message) ||
|
||||
!TryReadOptionalToolIds(assistantTable, out var toolIds, out message))
|
||||
return false;
|
||||
|
||||
this.ChatLaunchConfiguration = new(workspaceName, providerId, profileId, chatTemplateId, dataSourceIds, toolIds);
|
||||
this.ChatLaunchConfiguration = new(workspaceName, providerId, profileIds, chatTemplateId, dataSourceIds, toolIds);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -309,6 +310,56 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryReadOptionalProfileIds(LuaTable assistantTable, out IReadOnlyList<Guid>? profileIds, out string message)
|
||||
{
|
||||
profileIds = null;
|
||||
message = string.Empty;
|
||||
var hasLegacyId = assistantTable.TryGetValue("ProfileId", out _);
|
||||
var hasIds = assistantTable.TryGetValue("ProfileIds", out var profileIdsValue);
|
||||
if (hasLegacyId && hasIds)
|
||||
{
|
||||
message = TB("The ASSISTANT table contains both ProfileId and ProfileIds. Use only one of them.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasLegacyId)
|
||||
{
|
||||
if (!TryReadOptionalGuid(assistantTable, "ProfileId", true, out var profileId, out message))
|
||||
return false;
|
||||
|
||||
profileIds = profileId == Guid.Empty ? [] : profileId is { } id ? [id] : null;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!hasIds)
|
||||
return true;
|
||||
|
||||
if (!profileIdsValue.TryRead<LuaTable>(out var profileIdsTable))
|
||||
{
|
||||
message = TB("The ASSISTANT table contains invalid ProfileIds. Expected a list of unique, non-empty GUIDs.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var parsedIds = new List<Guid>(profileIdsTable.ArrayLength);
|
||||
var uniqueIds = new HashSet<Guid>();
|
||||
for (var index = 1; index <= profileIdsTable.ArrayLength; index++)
|
||||
{
|
||||
if (!profileIdsTable[index].TryRead<string>(out var idText) ||
|
||||
!Guid.TryParse(idText, out var parsedId) ||
|
||||
parsedId == Guid.Empty ||
|
||||
!uniqueIds.Add(parsedId))
|
||||
{
|
||||
message = TB("The ASSISTANT table contains invalid ProfileIds. Expected a list of unique, non-empty GUIDs.");
|
||||
return false;
|
||||
}
|
||||
|
||||
parsedIds.Add(parsedId);
|
||||
}
|
||||
|
||||
profileIds = parsedIds.ToImmutableArray();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the tools an assistant names: the ones a launcher preselects for its chat, or the ones
|
||||
/// the assistant itself runs with.
|
||||
@@ -383,12 +434,14 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
|
||||
InitializeState(this.RootComponent.Children, assistantState);
|
||||
|
||||
var input = assistantState.ToLuaTable(this.RootComponent?.Children ?? []);
|
||||
input["profiles"] = new LuaTable();
|
||||
input["profile"] = new LuaTable
|
||||
{
|
||||
["Name"] = string.Empty,
|
||||
["NeedToKnow"] = string.Empty,
|
||||
["Actions"] = string.Empty,
|
||||
["Num"] = 0,
|
||||
["Id"] = Profile.NO_PROFILE.Id,
|
||||
["Name"] = Profile.NO_PROFILE.Name,
|
||||
["NeedToKnow"] = Profile.NO_PROFILE.NeedToKnow,
|
||||
["Actions"] = Profile.NO_PROFILE.Actions,
|
||||
["Num"] = Profile.NO_PROFILE.Num,
|
||||
};
|
||||
|
||||
var prompt = await this.TryBuildPromptAsync(input, cancellationToken);
|
||||
|
||||
@@ -210,6 +210,9 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
if (!TryValidateMinimumProviderConfidenceConfiguration(settingsTable, out message))
|
||||
return false;
|
||||
|
||||
if (!TryValidateProfilePreselectionConfiguration(settingsTable, out message))
|
||||
return false;
|
||||
|
||||
this.DeclaredSettingsCount = CountDeclaredSettings(settingsTable);
|
||||
|
||||
// Config: check for updates, and if so, how often?
|
||||
@@ -346,13 +349,29 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
// Config: preselected provider?
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.App, x => x.PreselectedProvider, Guid.Empty, this.Id, settingsTable, dryRun);
|
||||
|
||||
// Config: preselected profile?
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.App, x => x.PreselectedProfile, Guid.Empty, this.Id, settingsTable, dryRun);
|
||||
// Config: preselected profiles? The singular name remains a compatibility alias.
|
||||
var appProfilesValid = settingsTable.TryGetValue("DataApp.PreselectedProfileIds", out _)
|
||||
? ManagedConfiguration.TryProcessProfileIds(x => x.App, x => x.PreselectedProfileIds, this.Id, settingsTable, dryRun)
|
||||
: !settingsTable.TryGetValue("DataApp.PreselectedProfile", out _) ||
|
||||
ManagedConfiguration.TryProcessLegacyProfileIds(x => x.App, x => x.PreselectedProfileIds, "DataApp.PreselectedProfile", this.Id, settingsTable, dryRun);
|
||||
if (!appProfilesValid)
|
||||
{
|
||||
message = TB("The configured app profile preselection is invalid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Config: preselected chat options?
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Chat, x => x.PreselectOptions, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Chat, x => x.PreselectedProvider, Guid.Empty, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Chat, x => x.PreselectedProfile, this.Id, settingsTable, dryRun);
|
||||
var chatProfilesValid = settingsTable.TryGetValue("DataChat.PreselectedProfileIds", out _)
|
||||
? ManagedConfiguration.TryProcessProfilePreselection(x => x.Chat, x => x.PreselectedProfileIds, this.Id, settingsTable, dryRun)
|
||||
: !settingsTable.TryGetValue("DataChat.PreselectedProfile", out _) ||
|
||||
ManagedConfiguration.TryProcessLegacyProfilePreselection(x => x.Chat, x => x.PreselectedProfileIds, "DataChat.PreselectedProfile", this.Id, settingsTable, dryRun);
|
||||
if (!chatProfilesValid)
|
||||
{
|
||||
message = TB("The configured chat profile preselection is invalid.");
|
||||
return false;
|
||||
}
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Chat, x => x.PreselectedChatTemplate, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Chat, x => x.PreselectedDataSourcesDisabled, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Chat, x => x.PreselectedDataSourcesAutomaticSelection, this.Id, settingsTable, dryRun);
|
||||
@@ -360,6 +379,16 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Chat, x => x.PreselectedDataSourceIds, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.Chat, x => x.SendToChatDataSourceBehavior, this.Id, settingsTable, dryRun);
|
||||
|
||||
var visualBriefingProfilesValid = settingsTable.TryGetValue("DataVisualBriefing.PreselectedProfileIds", out _)
|
||||
? ManagedConfiguration.TryProcessProfilePreselection(x => x.VisualBriefing, x => x.PreselectedProfileIds, this.Id, settingsTable, dryRun)
|
||||
: !settingsTable.TryGetValue("DataVisualBriefing.PreselectedProfile", out _) ||
|
||||
ManagedConfiguration.TryProcessLegacyProfilePreselection(x => x.VisualBriefing, x => x.PreselectedProfileIds, "DataVisualBriefing.PreselectedProfile", this.Id, settingsTable, dryRun);
|
||||
if (!visualBriefingProfilesValid)
|
||||
{
|
||||
message = TB("The configured visual briefing profile preselection is invalid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Config: Batch Processing Assistant defaults?
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.BatchProcessing, x => x.PreselectOptions, this.Id, settingsTable, dryRun);
|
||||
ManagedConfiguration.TryProcessConfiguration(x => x.BatchProcessing, x => x.InputDirectory, this.Id, settingsTable, dryRun);
|
||||
@@ -391,6 +420,27 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryValidateProfilePreselectionConfiguration(LuaTable settings, out string message)
|
||||
{
|
||||
foreach (var settingPrefix in new[] { "DataApp", "DataChat", "DataVisualBriefing" })
|
||||
{
|
||||
var singularName = $"{settingPrefix}.PreselectedProfile";
|
||||
var pluralName = $"{settingPrefix}.PreselectedProfileIds";
|
||||
if (settings.TryGetValue(singularName, out _) && settings.TryGetValue(pluralName, out _))
|
||||
{
|
||||
message = string.Format(TB("The SETTINGS table contains both '{0}' and '{1}'. Use only one of them."), singularName, pluralName);
|
||||
return false;
|
||||
}
|
||||
|
||||
var legacyOverrideName = $"{singularName}.AllowUserOverride";
|
||||
if (settings.TryGetValue(legacyOverrideName, out var legacyOverride))
|
||||
settings[$"{pluralName}.AllowUserOverride"] = legacyOverride;
|
||||
}
|
||||
|
||||
message = string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryValidateMinimumProviderConfidenceConfiguration(LuaTable settingsTable, out string message)
|
||||
{
|
||||
const string SETTING_NAME = "DataTools.MinimumProviderConfidenceByToolId";
|
||||
|
||||
Reference in new issue
Block a user