From 79c92bb8f18fc827aa1c4094019fa49ad9f3c993 Mon Sep 17 00:00:00 2001 From: nilsk Date: Sat, 21 Mar 2026 02:01:13 +0100 Subject: [PATCH] centralized conversion methods to reduce repetition --- .../DataModel/AssistantLuaConversion.cs | 271 ++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 app/MindWork AI Studio/Tools/PluginSystem/Assistants/DataModel/AssistantLuaConversion.cs diff --git a/app/MindWork AI Studio/Tools/PluginSystem/Assistants/DataModel/AssistantLuaConversion.cs b/app/MindWork AI Studio/Tools/PluginSystem/Assistants/DataModel/AssistantLuaConversion.cs new file mode 100644 index 00000000..4ec19801 --- /dev/null +++ b/app/MindWork AI Studio/Tools/PluginSystem/Assistants/DataModel/AssistantLuaConversion.cs @@ -0,0 +1,271 @@ +using System.Collections; +using Lua; + +namespace AIStudio.Tools.PluginSystem.Assistants.DataModel; + +internal static class AssistantLuaConversion +{ + /// + /// Converts a sequence of scalar .NET values into the array-like Lua table shape used by assistant state. + /// + public static LuaTable CreateLuaArray(IEnumerable values) => CreateLuaArrayCore(values); + + /// + /// Reads a Lua value into either a scalar .NET value or one of the structured assistant data model types. + /// Lua itself only exposes scalars and tables, so structured assistant types such as dropdown/list items + /// must be detected from well-known table shapes. + /// + public static bool TryReadScalarOrStructuredValue(LuaValue value, out object result) + { + if (value.TryRead(out var stringValue)) + { + result = stringValue; + return true; + } + + if (value.TryRead(out var boolValue)) + { + result = boolValue; + return true; + } + + if (value.TryRead(out var doubleValue)) + { + result = doubleValue; + return true; + } + + if (value.TryRead(out var table) && TryParseDropdownItem(table, out var dropdownItem)) + { + result = dropdownItem; + return true; + } + + if (value.TryRead(out var dropdownListTable) && TryParseDropdownItemList(dropdownListTable, out var dropdownItems)) + { + result = dropdownItems; + return true; + } + + if (value.TryRead(out var listItemListTable) && TryParseListItemList(listItemListTable, out var listItems)) + { + result = listItems; + return true; + } + + result = null!; + return false; + } + + /// + /// Writes an assistant value into a Lua table. + /// This supports a broader set of .NET types than , + /// because assistant props and state already exist as rich C# objects before being serialized back to Lua. + /// + public static bool TryWriteAssistantValue(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] = boolValue; + return true; + case byte byteValue: + table[key] = byteValue; + return true; + case sbyte sbyteValue: + table[key] = sbyteValue; + return true; + case short shortValue: + table[key] = shortValue; + return true; + case ushort ushortValue: + table[key] = ushortValue; + return true; + case int intValue: + table[key] = intValue; + return true; + case uint uintValue: + table[key] = uintValue; + return true; + case long longValue: + table[key] = longValue; + return true; + case ulong ulongValue: + table[key] = ulongValue; + return true; + case float floatValue: + table[key] = floatValue; + return true; + case double doubleValue: + table[key] = doubleValue; + return true; + case decimal decimalValue: + table[key] = (double)decimalValue; + return true; + case Enum enumValue: + table[key] = enumValue.ToString(); + return true; + case AssistantDropdownItem dropdownItem: + table[key] = CreateDropdownItemTable(dropdownItem); + return true; + case IEnumerable dropdownItems: + table[key] = CreateLuaArrayCore(dropdownItems.Select(CreateDropdownItemTable)); + return true; + case IEnumerable listItems: + table[key] = CreateLuaArrayCore(listItems.Select(CreateListItemTable)); + return true; + case IEnumerable strings: + table[key] = CreateLuaArrayCore(strings); + return true; + default: + return false; + } + } + + private static bool TryParseDropdownItem(LuaTable table, out AssistantDropdownItem item) + { + item = new AssistantDropdownItem(); + + if (!table.TryGetValue("Value", out var valueValue) || !valueValue.TryRead(out var value)) + return false; + + if (!table.TryGetValue("Display", out var displayValue) || !displayValue.TryRead(out var display)) + return false; + + item.Value = value; + item.Display = display; + return true; + } + + private static bool TryParseDropdownItemList(LuaTable table, out List items) + { + items = new List(); + + for (var index = 1; index <= table.ArrayLength; index++) + { + var value = table[index]; + if (!value.TryRead(out var itemTable) || !TryParseDropdownItem(itemTable, out var item)) + { + items = null!; + return false; + } + + items.Add(item); + } + + return true; + } + + private static bool TryParseListItem(LuaTable table, out AssistantListItem item) + { + item = new AssistantListItem(); + + if (!table.TryGetValue("Text", out var textValue) || !textValue.TryRead(out var text)) + return false; + + if (!table.TryGetValue("Type", out var typeValue) || !typeValue.TryRead(out var type)) + return false; + + table.TryGetValue("Icon", out var iconValue); + iconValue.TryRead(out var icon); + + table.TryGetValue("IconColor", out var iconColorValue); + iconColorValue.TryRead(out var iconColor); + + item.Text = text; + item.Type = type; + item.Icon = icon; + item.IconColor = iconColor; + + if (table.TryGetValue("Href", out var hrefValue) && hrefValue.TryRead(out var href)) + item.Href = href; + + return true; + } + + private static bool TryParseListItemList(LuaTable table, out List items) + { + items = new List(); + + for (var index = 1; index <= table.ArrayLength; index++) + { + var value = table[index]; + if (!value.TryRead(out var itemTable) || !TryParseListItem(itemTable, out var item)) + { + items = null!; + return false; + } + + items.Add(item); + } + + return true; + } + + 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 CreateLuaArrayCore(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 => boolValue, + byte byteValue => byteValue, + sbyte sbyteValue => sbyteValue, + short shortValue => shortValue, + ushort ushortValue => ushortValue, + int intValue => intValue, + uint uintValue => uintValue, + long longValue => longValue, + ulong ulongValue => ulongValue, + float floatValue => floatValue, + double doubleValue => doubleValue, + decimal decimalValue => (double)decimalValue, + _ => LuaValue.Nil, + }; + } + + return luaArray; + } +}