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;
+ }
+}