diff --git a/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor b/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor
index 171348e1..dcf10de3 100644
--- a/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor
+++ b/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor
@@ -135,5 +135,28 @@
}
break;
+ case AssistantComponentType.COLOR_PICKER:
+ if (component is AssistantColorPicker assistantColorPicker)
+ {
+ var colorPicker = assistantColorPicker;
+ var variant = this.GetPickerVariant(colorPicker.PickerVariant);
+ var elevation = variant == PickerVariant.Static ? 6 : 0;
+ var rounded = variant == PickerVariant.Static;
+
+
+
+
+ }
+ break;
}
}
diff --git a/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs b/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs
index 1ad79708..5e3cd44b 100644
--- a/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs
+++ b/app/MindWork AI Studio/Assistants/Dynamic/AssistantDynamic.razor.cs
@@ -45,6 +45,7 @@ public partial class AssistantDynamic : AssistantBaseCore
private Dictionary switchFields = new();
private Dictionary webContentFields = new();
private Dictionary fileContentFields = new();
+ private Dictionary colorPickerFields = new();
private readonly Dictionary imageCache = new();
private string pluginPath = string.Empty;
private const string PLUGIN_SCHEME = "plugin://";
@@ -111,6 +112,12 @@ public partial class AssistantDynamic : AssistantBaseCore
this.fileContentFields.Add(fileContent.Name, new FileContentState());
}
break;
+ case AssistantComponentType.COLOR_PICKER:
+ if (component is AssistantColorPicker assistantColorPicker)
+ {
+ this.colorPickerFields.Add(assistantColorPicker.Name, assistantColorPicker.Placeholder);
+ }
+ break;
}
}
}
@@ -167,6 +174,11 @@ public partial class AssistantDynamic : AssistantBaseCore
{
entry.Value.Content = string.Empty;
}
+
+ foreach (var entry in this.colorPickerFields)
+ {
+ this.colorPickerFields[entry.Key] = string.Empty;
+ }
}
protected override bool MightPreselectValues()
@@ -256,6 +268,8 @@ public partial class AssistantDynamic : AssistantBaseCore
fields[entry.Key] = entry.Value.Content ?? string.Empty;
foreach (var entry in this.fileContentFields)
fields[entry.Key] = entry.Value.Content ?? string.Empty;
+ foreach (var entry in this.colorPickerFields)
+ fields[entry.Key] = entry.Value ?? string.Empty;
input["fields"] = fields;
@@ -282,6 +296,9 @@ public partial class AssistantDynamic : AssistantBaseCore
case AssistantFileContentReader fileContent:
this.AddMetaEntry(meta, fileContent.Name, component.Type, null, fileContent.UserPrompt);
break;
+ case AssistantColorPicker colorPicker:
+ this.AddMetaEntry(meta, colorPicker.Name, component.Type, colorPicker.Label, colorPicker.UserPrompt);
+ break;
}
}
}
@@ -391,6 +408,16 @@ public partial class AssistantDynamic : AssistantBaseCore
}
}
break;
+ case AssistantComponentType.COLOR_PICKER:
+ if (component is AssistantColorPicker colorPicker)
+ {
+ prompt += $"context:{Environment.NewLine}{colorPicker.UserPrompt}{Environment.NewLine}---{Environment.NewLine}";
+ if (this.inputFields.TryGetValue(colorPicker.Name, out userInput))
+ {
+ prompt += $"user prompt:{Environment.NewLine}{userInput}";
+ }
+ }
+ break;
default:
prompt += $"{userInput}{Environment.NewLine}";
break;
@@ -414,8 +441,16 @@ public partial class AssistantDynamic : AssistantBaseCore
}
private string? GetOptionalStyle(string? style) => string.IsNullOrWhiteSpace(style) ? null : style;
-
- private string? ValidateProfileSelection(AssistantProfileSelection profileSelection, Profile profile)
+
+ private PickerVariant GetPickerVariant(string pickerVariant) => pickerVariant.ToLowerInvariant() switch
+ {
+ "dialog" => PickerVariant.Dialog,
+ "static" => PickerVariant.Static,
+ "inline" => PickerVariant.Inline,
+ _ => PickerVariant.Static
+ };
+
+ private string? ValidateProfileSelection(AssistantProfileSelection profileSelection, Profile? profile)
{
if (profile == default || profile == Profile.NO_PROFILE)
{
diff --git a/app/MindWork AI Studio/Plugins/assistants/README.md b/app/MindWork AI Studio/Plugins/assistants/README.md
index 76e457e9..aa3e993b 100644
--- a/app/MindWork AI Studio/Plugins/assistants/README.md
+++ b/app/MindWork AI Studio/Plugins/assistants/README.md
@@ -12,6 +12,7 @@ Supported types (matching the Blazor UI components):
- `TEXT_AREA`: any user input field with `Name`, `Label`, `UserPrompt`, `PrefillText`, `IsSingleLine`, `ReadOnly`.
- `DROPDOWN`: selects between variants; `Props` must include `Name`, `Label`, `Default`, `Items`, and optionally `ValueType` plus `UserPrompt`.
- `SWITCH`: boolean option; requires `Name`, `Label`, `Value`, `LabelOn`, `LabelOff`, and may include `UserPrompt`.
+- `COLOR_PICKER`: color input based on `MudColorPicker`; requires `Name`, `Label`, and may include `Placeholder`, `ShowAlpha`, `ShowToolbar`, `ShowModeSwitch`, `PickerVariant`, `UserPrompt`, `Class`, `Style`.
- `PROVIDER_SELECTION` / `PROFILE_SELECTION`: hooks into the shared provider/profile selectors.
- `WEB_CONTENT_READER`: renders `ReadWebContent`; include `Name`, `UserPrompt`, `Preselect`, `PreselectContentCleanerAgent`.
- `FILE_CONTENT_READER`: renders `ReadFileContent`; include `Name`, `UserPrompt`.
@@ -31,7 +32,7 @@ user prompt:
```
-For switches the “value” is the boolean `true/false`; for readers it is the fetched/selected content. Always provide a meaningful `UserPrompt` so the final concatenated prompt remains coherent from the LLM’s perspective.
+For switches the “value” is the boolean `true/false`; for readers it is the fetched/selected content; for color pickers it is the selected color text (for example `#FFAA00` or `rgba(...)`, depending on the picker mode). Always provide a meaningful `UserPrompt` so the final concatenated prompt remains coherent from the LLM’s perspective.
### Advanced: BuildPrompt (optional)
If you want full control over prompt composition, define `ASSISTANT.BuildPrompt` as a Lua function. When present, AI Studio calls it and uses its return value as the final user prompt. The default prompt assembly is skipped.
@@ -46,8 +47,9 @@ The function receives a single `input` table with:
- `input.fields`: values keyed by component `Name`
- Text area, dropdown, and readers are strings
- Switch is a boolean
+ - Color picker is the selected color as a string
- `input.meta`: per-component metadata keyed by component `Name`
- - `Type` (string, e.g. `TEXT_AREA`, `DROPDOWN`, `SWITCH`)
+ - `Type` (string, e.g. `TEXT_AREA`, `DROPDOWN`, `SWITCH`, `COLOR_PICKER`)
- `Label` (string, when provided)
- `UserPrompt` (string, when provided)
- `input.profile`: selected profile data
@@ -63,7 +65,7 @@ input = {
},
meta = {
[""] = {
- Type = "",
+ Type = "",
Label = "",
UserPrompt = ""
},
@@ -103,6 +105,8 @@ ASSISTANT.BuildPrompt = function(input)
local value = input.fields[name]
if meta.Type == "SWITCH" then
table.insert(parts, name .. ": " .. tostring(value))
+ elseif meta.Type == "COLOR_PICKER" and value and value ~= "" then
+ table.insert(parts, name .. ": " .. value)
elseif value and value ~= "" then
table.insert(parts, name .. ": " .. value)
end
@@ -111,6 +115,37 @@ ASSISTANT.BuildPrompt = function(input)
end
```
+### `COLOR_PICKER` reference
+- Use `Type = "COLOR_PICKER"` to render a MudBlazor color picker.
+- Required props:
+ - `Name`: unique state key used in prompt assembly and `BuildPrompt(input.fields)`.
+ - `Label`: visible field label.
+- Optional props:
+ - `Placeholder`: default color hex string (e.g. `#FF10FF`) or initial hint text.
+ - `ShowAlpha`: defaults to `true`; enables alpha channel editing.
+ - `ShowToolbar`: defaults to `true`; shows picker/grid/palette toolbar.
+ - `ShowModeSwitch`: defaults to `true`; allows switching between HEX/RGB(A)/HSL modes.
+ - `PickerVariant`: one of `DIALOG`, `INLINE`, `STATIC`; invalid or omitted values fall back to `STATIC`.
+ - `UserPrompt`: prompt context text for the selected color.
+ - `Class`, `Style`: forwarded to the rendered component for layout/styling.
+
+Example:
+```lua
+{
+ ["Type"] = "COLOR_PICKER",
+ ["Props"] = {
+ ["Name"] = "accentColor",
+ ["Label"] = "Accent color",
+ ["Placeholder"] = "#FFAA00",
+ ["ShowAlpha"] = false,
+ ["ShowToolbar"] = true,
+ ["ShowModeSwitch"] = true,
+ ["PickerVariant"] = "STATIC",
+ ["UserPrompt"] = "Use this as the accent color for the generated design."
+ }
+}
+```
+
#### Using `profile` inside BuildPrompt
Profiles are optional user context (e.g., "NeedToKnow" and "Actions"). You can inject this directly into the user prompt if you want the LLM to always see it.
diff --git a/app/MindWork AI Studio/Plugins/assistants/plugin.lua b/app/MindWork AI Studio/Plugins/assistants/plugin.lua
index fa19e5f9..35b3133f 100644
--- a/app/MindWork AI Studio/Plugins/assistants/plugin.lua
+++ b/app/MindWork AI Studio/Plugins/assistants/plugin.lua
@@ -168,6 +168,19 @@ ASSISTANT = {
["UserPrompt"] = ""
}
},
+ {
+ ["Type"] = "COLOR_PICKER",
+ ["Props"] = {
+ ["Name"] = "", -- required
+ ["Label"] = "", -- required
+ ["Placeholder"] = "