mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-03-29 17:31:37 +00:00
358 lines
12 KiB
C#
358 lines
12 KiB
C#
using System.Collections;
|
|
using AIStudio.Assistants.Dynamic;
|
|
using Lua;
|
|
|
|
namespace AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
|
|
|
public sealed class AssistantState
|
|
{
|
|
public readonly Dictionary<string, string> Text = new(StringComparer.Ordinal);
|
|
public readonly Dictionary<string, string> SingleSelect = new(StringComparer.Ordinal);
|
|
public readonly Dictionary<string, HashSet<string>> MultiSelect = new(StringComparer.Ordinal);
|
|
public readonly Dictionary<string, bool> Bools = new(StringComparer.Ordinal);
|
|
public readonly Dictionary<string, WebContentState> WebContent = new(StringComparer.Ordinal);
|
|
public readonly Dictionary<string, FileContentState> FileContent = new(StringComparer.Ordinal);
|
|
public readonly Dictionary<string, string> Colors = new(StringComparer.Ordinal);
|
|
public readonly Dictionary<string, string> Dates = new(StringComparer.Ordinal);
|
|
public readonly Dictionary<string, string> DateRanges = new(StringComparer.Ordinal);
|
|
public readonly Dictionary<string, string> Times = new(StringComparer.Ordinal);
|
|
|
|
public void Clear()
|
|
{
|
|
this.Text.Clear();
|
|
this.SingleSelect.Clear();
|
|
this.MultiSelect.Clear();
|
|
this.Bools.Clear();
|
|
this.WebContent.Clear();
|
|
this.FileContent.Clear();
|
|
this.Colors.Clear();
|
|
this.Dates.Clear();
|
|
this.DateRanges.Clear();
|
|
this.Times.Clear();
|
|
}
|
|
|
|
public bool TryApplyValue(string fieldName, LuaValue value, out string expectedType)
|
|
{
|
|
expectedType = string.Empty;
|
|
|
|
if (this.Text.ContainsKey(fieldName))
|
|
{
|
|
expectedType = "string";
|
|
if (!value.TryRead<string>(out var textValue))
|
|
return false;
|
|
|
|
this.Text[fieldName] = textValue ?? string.Empty;
|
|
return true;
|
|
}
|
|
|
|
if (this.SingleSelect.ContainsKey(fieldName))
|
|
{
|
|
expectedType = "string";
|
|
if (!value.TryRead<string>(out var singleSelectValue))
|
|
return false;
|
|
|
|
this.SingleSelect[fieldName] = singleSelectValue ?? string.Empty;
|
|
return true;
|
|
}
|
|
|
|
if (this.MultiSelect.ContainsKey(fieldName))
|
|
{
|
|
expectedType = "string[]";
|
|
if (value.TryRead<LuaTable>(out var multiselectTable))
|
|
{
|
|
this.MultiSelect[fieldName] = ReadStringValues(multiselectTable);
|
|
return true;
|
|
}
|
|
|
|
if (!value.TryRead<string>(out var singleValue))
|
|
return false;
|
|
|
|
this.MultiSelect[fieldName] = string.IsNullOrWhiteSpace(singleValue) ? [] : [singleValue];
|
|
return true;
|
|
}
|
|
|
|
if (this.Bools.ContainsKey(fieldName))
|
|
{
|
|
expectedType = "boolean";
|
|
if (!value.TryRead<bool>(out var boolValue))
|
|
return false;
|
|
|
|
this.Bools[fieldName] = boolValue;
|
|
return true;
|
|
}
|
|
|
|
if (this.WebContent.TryGetValue(fieldName, out var webContentState))
|
|
{
|
|
expectedType = "string";
|
|
if (!value.TryRead<string>(out var webContentValue))
|
|
return false;
|
|
|
|
webContentState.Content = webContentValue ?? string.Empty;
|
|
return true;
|
|
}
|
|
|
|
if (this.FileContent.TryGetValue(fieldName, out var fileContentState))
|
|
{
|
|
expectedType = "string";
|
|
if (!value.TryRead<string>(out var fileContentValue))
|
|
return false;
|
|
|
|
fileContentState.Content = fileContentValue ?? string.Empty;
|
|
return true;
|
|
}
|
|
|
|
if (this.Colors.ContainsKey(fieldName))
|
|
{
|
|
expectedType = "string";
|
|
if (!value.TryRead<string>(out var colorValue))
|
|
return false;
|
|
|
|
this.Colors[fieldName] = colorValue ?? string.Empty;
|
|
return true;
|
|
}
|
|
|
|
if (this.Dates.ContainsKey(fieldName))
|
|
{
|
|
expectedType = "string";
|
|
if (!value.TryRead<string>(out var dateValue))
|
|
return false;
|
|
|
|
this.Dates[fieldName] = dateValue ?? string.Empty;
|
|
return true;
|
|
}
|
|
|
|
if (this.DateRanges.ContainsKey(fieldName))
|
|
{
|
|
expectedType = "string";
|
|
if (!value.TryRead<string>(out var dateRangeValue))
|
|
return false;
|
|
|
|
this.DateRanges[fieldName] = dateRangeValue ?? string.Empty;
|
|
return true;
|
|
}
|
|
|
|
if (this.Times.ContainsKey(fieldName))
|
|
{
|
|
expectedType = "string";
|
|
if (!value.TryRead<string>(out var timeValue))
|
|
return false;
|
|
|
|
this.Times[fieldName] = timeValue ?? string.Empty;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public LuaTable ToLuaTable(IEnumerable<IAssistantComponent> components)
|
|
{
|
|
var table = new LuaTable();
|
|
this.AddEntries(table, components);
|
|
return table;
|
|
}
|
|
|
|
private void AddEntries(LuaTable target, IEnumerable<IAssistantComponent> components)
|
|
{
|
|
foreach (var component in components)
|
|
{
|
|
if (component is INamedAssistantComponent named)
|
|
{
|
|
target[named.Name] = new LuaTable
|
|
{
|
|
["Value"] = component is IStatefulAssistantComponent ? this.ReadValueForLua(named.Name) : LuaValue.Nil,
|
|
["Props"] = this.CreatePropsTable(component),
|
|
};
|
|
}
|
|
|
|
if (component.Children.Count > 0)
|
|
this.AddEntries(target, component.Children);
|
|
}
|
|
}
|
|
|
|
private LuaValue ReadValueForLua(string name)
|
|
{
|
|
if (this.Text.TryGetValue(name, out var textValue))
|
|
return textValue;
|
|
if (this.SingleSelect.TryGetValue(name, out var singleSelectValue))
|
|
return singleSelectValue;
|
|
if (this.MultiSelect.TryGetValue(name, out var multiSelectValue))
|
|
return CreateLuaArray(multiSelectValue.OrderBy(static value => value, StringComparer.Ordinal));
|
|
if (this.Bools.TryGetValue(name, out var boolValue))
|
|
return boolValue;
|
|
if (this.WebContent.TryGetValue(name, out var webContentValue))
|
|
return webContentValue.Content ?? string.Empty;
|
|
if (this.FileContent.TryGetValue(name, out var fileContentValue))
|
|
return fileContentValue.Content ?? string.Empty;
|
|
if (this.Colors.TryGetValue(name, out var colorValue))
|
|
return colorValue;
|
|
if (this.Dates.TryGetValue(name, out var dateValue))
|
|
return dateValue;
|
|
if (this.DateRanges.TryGetValue(name, out var dateRangeValue))
|
|
return dateRangeValue;
|
|
if (this.Times.TryGetValue(name, out var timeValue))
|
|
return timeValue;
|
|
|
|
return LuaValue.Nil;
|
|
}
|
|
|
|
private LuaTable CreatePropsTable(IAssistantComponent component)
|
|
{
|
|
var table = new LuaTable();
|
|
var nonReadableProps = ComponentPropSpecs.SPECS.TryGetValue(component.Type, out var propSpec)
|
|
? propSpec.NonReadable
|
|
: [];
|
|
|
|
foreach (var key in component.Props.Keys)
|
|
{
|
|
if (nonReadableProps.Contains(key, StringComparer.Ordinal))
|
|
continue;
|
|
|
|
if (!component.Props.TryGetValue(key, out var value))
|
|
continue;
|
|
|
|
if (!TryWriteLuaValue(table, key, value))
|
|
continue;
|
|
}
|
|
|
|
return table;
|
|
}
|
|
|
|
private static bool TryWriteLuaValue(LuaTable table, string key, object? value)
|
|
{
|
|
if (value is null or LuaFunction)
|
|
return false;
|
|
|
|
switch (value)
|
|
{
|
|
case LuaValue { Type: not LuaValueType.Nil } luaValue:
|
|
table[key] = luaValue;
|
|
return true;
|
|
case LuaTable luaTable:
|
|
table[key] = luaTable;
|
|
return true;
|
|
case string stringValue:
|
|
table[key] = (LuaValue)stringValue;
|
|
return true;
|
|
case bool boolValue:
|
|
table[key] = (LuaValue)boolValue;
|
|
return true;
|
|
case byte byteValue:
|
|
table[key] = (LuaValue)byteValue;
|
|
return true;
|
|
case sbyte sbyteValue:
|
|
table[key] = (LuaValue)sbyteValue;
|
|
return true;
|
|
case short shortValue:
|
|
table[key] = (LuaValue)shortValue;
|
|
return true;
|
|
case ushort ushortValue:
|
|
table[key] = (LuaValue)ushortValue;
|
|
return true;
|
|
case int intValue:
|
|
table[key] = (LuaValue)intValue;
|
|
return true;
|
|
case uint uintValue:
|
|
table[key] = (LuaValue)uintValue;
|
|
return true;
|
|
case long longValue:
|
|
table[key] = (LuaValue)longValue;
|
|
return true;
|
|
case ulong ulongValue:
|
|
table[key] = (LuaValue)ulongValue;
|
|
return true;
|
|
case float floatValue:
|
|
table[key] = (LuaValue)floatValue;
|
|
return true;
|
|
case double doubleValue:
|
|
table[key] = (LuaValue)doubleValue;
|
|
return true;
|
|
case decimal decimalValue:
|
|
table[key] = (LuaValue)(double)decimalValue;
|
|
return true;
|
|
case Enum enumValue:
|
|
table[key] = enumValue.ToString() ?? string.Empty;
|
|
return true;
|
|
case AssistantDropdownItem dropdownItem:
|
|
table[key] = CreateDropdownItemTable(dropdownItem);
|
|
return true;
|
|
case IEnumerable<AssistantDropdownItem> dropdownItems:
|
|
table[key] = CreateLuaArray(dropdownItems.Select(CreateDropdownItemTable));
|
|
return true;
|
|
case IEnumerable<AssistantListItem> listItems:
|
|
table[key] = CreateLuaArray(listItems.Select(CreateListItemTable));
|
|
return true;
|
|
case IEnumerable<string> strings:
|
|
table[key] = CreateLuaArray(strings);
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static LuaTable CreateDropdownItemTable(AssistantDropdownItem item) =>
|
|
new()
|
|
{
|
|
["Value"] = item.Value,
|
|
["Display"] = item.Display,
|
|
};
|
|
|
|
private static LuaTable CreateListItemTable(AssistantListItem item)
|
|
{
|
|
var table = new LuaTable
|
|
{
|
|
["Type"] = item.Type,
|
|
["Text"] = item.Text,
|
|
["Icon"] = item.Icon,
|
|
["IconColor"] = item.IconColor,
|
|
};
|
|
|
|
if (!string.IsNullOrWhiteSpace(item.Href))
|
|
table["Href"] = item.Href;
|
|
|
|
return table;
|
|
}
|
|
|
|
private static LuaTable CreateLuaArray(IEnumerable values)
|
|
{
|
|
var luaArray = new LuaTable();
|
|
var index = 1;
|
|
|
|
foreach (var value in values)
|
|
luaArray[index++] = value switch
|
|
{
|
|
null => LuaValue.Nil,
|
|
LuaValue luaValue => luaValue,
|
|
LuaTable luaTable => luaTable,
|
|
string stringValue => (LuaValue)stringValue,
|
|
bool boolValue => (LuaValue)boolValue,
|
|
byte byteValue => (LuaValue)byteValue,
|
|
sbyte sbyteValue => (LuaValue)sbyteValue,
|
|
short shortValue => (LuaValue)shortValue,
|
|
ushort ushortValue => (LuaValue)ushortValue,
|
|
int intValue => (LuaValue)intValue,
|
|
uint uintValue => (LuaValue)uintValue,
|
|
long longValue => (LuaValue)longValue,
|
|
ulong ulongValue => (LuaValue)ulongValue,
|
|
float floatValue => (LuaValue)floatValue,
|
|
double doubleValue => (LuaValue)doubleValue,
|
|
decimal decimalValue => (LuaValue)(double)decimalValue,
|
|
_ => LuaValue.Nil,
|
|
};
|
|
|
|
return luaArray;
|
|
}
|
|
|
|
private static HashSet<string> ReadStringValues(LuaTable values)
|
|
{
|
|
var parsedValues = new HashSet<string>(StringComparer.Ordinal);
|
|
|
|
foreach (var entry in values)
|
|
{
|
|
if (entry.Value.TryRead<string>(out var value) && !string.IsNullOrWhiteSpace(value))
|
|
parsedValues.Add(value);
|
|
}
|
|
|
|
return parsedValues;
|
|
}
|
|
}
|