mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-03-29 21:31:39 +00:00
added a new color picker component to the lua parsing
This commit is contained in:
parent
fc3b46a2d8
commit
a5149e460f
@ -135,5 +135,28 @@
|
|||||||
</MudList>
|
</MudList>
|
||||||
}
|
}
|
||||||
break;
|
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;
|
||||||
|
|
||||||
|
<MudItem Class="d-flex">
|
||||||
|
<MudColorPicker @bind-Text="@this.colorPickerFields[colorPicker.Name]"
|
||||||
|
Label="@colorPicker.Label"
|
||||||
|
Placeholder="@colorPicker.Placeholder"
|
||||||
|
ShowAlpha="@colorPicker.ShowAlpha"
|
||||||
|
ShowToolbar="@colorPicker.ShowToolbar"
|
||||||
|
ShowModeSwitch="@colorPicker.ShowModeSwitch"
|
||||||
|
PickerVariant="@variant"
|
||||||
|
Rounded="@rounded"
|
||||||
|
Elevation="@elevation"
|
||||||
|
Style="@($"color: {this.colorPickerFields[colorPicker.Name]};")"
|
||||||
|
Class="@MergeClass(colorPicker.Class, "mb-3")"/>
|
||||||
|
</MudItem>
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,6 +45,7 @@ public partial class AssistantDynamic : AssistantBaseCore<SettingsDialogDynamic>
|
|||||||
private Dictionary<string, bool> switchFields = new();
|
private Dictionary<string, bool> switchFields = new();
|
||||||
private Dictionary<string, WebContentState> webContentFields = new();
|
private Dictionary<string, WebContentState> webContentFields = new();
|
||||||
private Dictionary<string, FileContentState> fileContentFields = new();
|
private Dictionary<string, FileContentState> fileContentFields = new();
|
||||||
|
private Dictionary<string, string> colorPickerFields = new();
|
||||||
private readonly Dictionary<string, string> imageCache = new();
|
private readonly Dictionary<string, string> imageCache = new();
|
||||||
private string pluginPath = string.Empty;
|
private string pluginPath = string.Empty;
|
||||||
private const string PLUGIN_SCHEME = "plugin://";
|
private const string PLUGIN_SCHEME = "plugin://";
|
||||||
@ -111,6 +112,12 @@ public partial class AssistantDynamic : AssistantBaseCore<SettingsDialogDynamic>
|
|||||||
this.fileContentFields.Add(fileContent.Name, new FileContentState());
|
this.fileContentFields.Add(fileContent.Name, new FileContentState());
|
||||||
}
|
}
|
||||||
break;
|
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<SettingsDialogDynamic>
|
|||||||
{
|
{
|
||||||
entry.Value.Content = string.Empty;
|
entry.Value.Content = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var entry in this.colorPickerFields)
|
||||||
|
{
|
||||||
|
this.colorPickerFields[entry.Key] = string.Empty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool MightPreselectValues()
|
protected override bool MightPreselectValues()
|
||||||
@ -256,6 +268,8 @@ public partial class AssistantDynamic : AssistantBaseCore<SettingsDialogDynamic>
|
|||||||
fields[entry.Key] = entry.Value.Content ?? string.Empty;
|
fields[entry.Key] = entry.Value.Content ?? string.Empty;
|
||||||
foreach (var entry in this.fileContentFields)
|
foreach (var entry in this.fileContentFields)
|
||||||
fields[entry.Key] = entry.Value.Content ?? string.Empty;
|
fields[entry.Key] = entry.Value.Content ?? string.Empty;
|
||||||
|
foreach (var entry in this.colorPickerFields)
|
||||||
|
fields[entry.Key] = entry.Value ?? string.Empty;
|
||||||
|
|
||||||
input["fields"] = fields;
|
input["fields"] = fields;
|
||||||
|
|
||||||
@ -282,6 +296,9 @@ public partial class AssistantDynamic : AssistantBaseCore<SettingsDialogDynamic>
|
|||||||
case AssistantFileContentReader fileContent:
|
case AssistantFileContentReader fileContent:
|
||||||
this.AddMetaEntry(meta, fileContent.Name, component.Type, null, fileContent.UserPrompt);
|
this.AddMetaEntry(meta, fileContent.Name, component.Type, null, fileContent.UserPrompt);
|
||||||
break;
|
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<SettingsDialogDynamic>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
prompt += $"{userInput}{Environment.NewLine}";
|
prompt += $"{userInput}{Environment.NewLine}";
|
||||||
break;
|
break;
|
||||||
@ -414,8 +441,16 @@ public partial class AssistantDynamic : AssistantBaseCore<SettingsDialogDynamic>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string? GetOptionalStyle(string? style) => string.IsNullOrWhiteSpace(style) ? null : style;
|
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)
|
if (profile == default || profile == Profile.NO_PROFILE)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -12,6 +12,7 @@ Supported types (matching the Blazor UI components):
|
|||||||
- `TEXT_AREA`: any user input field with `Name`, `Label`, `UserPrompt`, `PrefillText`, `IsSingleLine`, `ReadOnly`.
|
- `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`.
|
- `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`.
|
- `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.
|
- `PROVIDER_SELECTION` / `PROFILE_SELECTION`: hooks into the shared provider/profile selectors.
|
||||||
- `WEB_CONTENT_READER`: renders `ReadWebContent`; include `Name`, `UserPrompt`, `Preselect`, `PreselectContentCleanerAgent`.
|
- `WEB_CONTENT_READER`: renders `ReadWebContent`; include `Name`, `UserPrompt`, `Preselect`, `PreselectContentCleanerAgent`.
|
||||||
- `FILE_CONTENT_READER`: renders `ReadFileContent`; include `Name`, `UserPrompt`.
|
- `FILE_CONTENT_READER`: renders `ReadFileContent`; include `Name`, `UserPrompt`.
|
||||||
@ -31,7 +32,7 @@ user prompt:
|
|||||||
<value extracted from the component>
|
<value extracted from the component>
|
||||||
```
|
```
|
||||||
|
|
||||||
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)
|
### 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.
|
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`
|
- `input.fields`: values keyed by component `Name`
|
||||||
- Text area, dropdown, and readers are strings
|
- Text area, dropdown, and readers are strings
|
||||||
- Switch is a boolean
|
- Switch is a boolean
|
||||||
|
- Color picker is the selected color as a string
|
||||||
- `input.meta`: per-component metadata keyed by component `Name`
|
- `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)
|
- `Label` (string, when provided)
|
||||||
- `UserPrompt` (string, when provided)
|
- `UserPrompt` (string, when provided)
|
||||||
- `input.profile`: selected profile data
|
- `input.profile`: selected profile data
|
||||||
@ -63,7 +65,7 @@ input = {
|
|||||||
},
|
},
|
||||||
meta = {
|
meta = {
|
||||||
["<Name>"] = {
|
["<Name>"] = {
|
||||||
Type = "<TEXT_AREA|DROPDOWN|SWITCH|WEB_CONTENT_READER|FILE_CONTENT_READER>",
|
Type = "<TEXT_AREA|DROPDOWN|SWITCH|WEB_CONTENT_READER|FILE_CONTENT_READER|COLOR_PICKER>",
|
||||||
Label = "<string?>",
|
Label = "<string?>",
|
||||||
UserPrompt = "<string?>"
|
UserPrompt = "<string?>"
|
||||||
},
|
},
|
||||||
@ -103,6 +105,8 @@ ASSISTANT.BuildPrompt = function(input)
|
|||||||
local value = input.fields[name]
|
local value = input.fields[name]
|
||||||
if meta.Type == "SWITCH" then
|
if meta.Type == "SWITCH" then
|
||||||
table.insert(parts, name .. ": " .. tostring(value))
|
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
|
elseif value and value ~= "" then
|
||||||
table.insert(parts, name .. ": " .. value)
|
table.insert(parts, name .. ": " .. value)
|
||||||
end
|
end
|
||||||
@ -111,6 +115,37 @@ ASSISTANT.BuildPrompt = function(input)
|
|||||||
end
|
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
|
#### 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.
|
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.
|
||||||
|
|
||||||
|
|||||||
@ -168,6 +168,19 @@ ASSISTANT = {
|
|||||||
["UserPrompt"] = "<help text reminding the user what kind of file they should load>"
|
["UserPrompt"] = "<help text reminding the user what kind of file they should load>"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
["Type"] = "COLOR_PICKER",
|
||||||
|
["Props"] = {
|
||||||
|
["Name"] = "<unique identifier of this component>", -- required
|
||||||
|
["Label"] = "<heading of your component>", -- required
|
||||||
|
["Placeholder"] = "<use this as a default color property with HEX code (e.g '#FFFF12') or just show hints to the user>",
|
||||||
|
["ShowAlpha"] = true, -- weather alpha channels are shown
|
||||||
|
["ShowToolbar"] = true, -- weather the toolbar to toggle between picker, grid or palette is shown
|
||||||
|
["ShowModeSwitch"] = true, -- weather switch to toggle between RGB(A), HEX or HSL color mode is shown
|
||||||
|
["PickerVariant"] = "<DIALOG | INLINE | STATIC (default)>",
|
||||||
|
["UserPrompt"] = "<help text reminding the user what kind of file they should load>",
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,8 @@ public class AssistantComponentFactory
|
|||||||
return new AssistantFileContentReader { Props = props, Children = children };
|
return new AssistantFileContentReader { Props = props, Children = children };
|
||||||
case AssistantComponentType.IMAGE:
|
case AssistantComponentType.IMAGE:
|
||||||
return new AssistantImage { Props = props, Children = children };
|
return new AssistantImage { Props = props, Children = children };
|
||||||
|
case AssistantComponentType.COLOR_PICKER:
|
||||||
|
return new AssistantColorPicker { Props = props, Children = children };
|
||||||
default:
|
default:
|
||||||
LOGGER.LogError($"Unknown assistant component type!\n{type} is not a supported assistant component type");
|
LOGGER.LogError($"Unknown assistant component type!\n{type} is not a supported assistant component type");
|
||||||
throw new Exception($"Unknown assistant component type: {type}");
|
throw new Exception($"Unknown assistant component type: {type}");
|
||||||
|
|||||||
@ -0,0 +1,67 @@
|
|||||||
|
namespace AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||||
|
|
||||||
|
internal sealed class AssistantColorPicker : AssistantComponentBase
|
||||||
|
{
|
||||||
|
public override AssistantComponentType Type => AssistantComponentType.COLOR_PICKER;
|
||||||
|
public override Dictionary<string, object> Props { get; set; } = new();
|
||||||
|
public override List<IAssistantComponent> Children { get; set; } = new();
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.Name));
|
||||||
|
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.Name), value);
|
||||||
|
}
|
||||||
|
public string Label
|
||||||
|
{
|
||||||
|
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.Label));
|
||||||
|
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.Label), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Placeholder
|
||||||
|
{
|
||||||
|
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.Placeholder));
|
||||||
|
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.Placeholder), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowAlpha
|
||||||
|
{
|
||||||
|
get => !this.Props.TryGetValue(nameof(this.ShowAlpha), out var val) || val is true;
|
||||||
|
set => this.Props[nameof(this.ShowAlpha)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowToolbar
|
||||||
|
{
|
||||||
|
get => !this.Props.TryGetValue(nameof(this.ShowToolbar), out var val) || val is true;
|
||||||
|
set => this.Props[nameof(this.ShowToolbar)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowModeSwitch
|
||||||
|
{
|
||||||
|
get => !this.Props.TryGetValue(nameof(this.ShowModeSwitch), out var val) || val is true;
|
||||||
|
set => this.Props[nameof(this.ShowModeSwitch)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string PickerVariant
|
||||||
|
{
|
||||||
|
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.PickerVariant));
|
||||||
|
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.PickerVariant), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string UserPrompt
|
||||||
|
{
|
||||||
|
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.UserPrompt));
|
||||||
|
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.UserPrompt), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Class
|
||||||
|
{
|
||||||
|
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.Class));
|
||||||
|
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.Class), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Style
|
||||||
|
{
|
||||||
|
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.Style));
|
||||||
|
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.Style), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,4 +15,5 @@ public enum AssistantComponentType
|
|||||||
WEB_CONTENT_READER,
|
WEB_CONTENT_READER,
|
||||||
FILE_CONTENT_READER,
|
FILE_CONTENT_READER,
|
||||||
IMAGE,
|
IMAGE,
|
||||||
|
COLOR_PICKER,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,5 +57,9 @@ public static class ComponentPropSpecs
|
|||||||
required: ["Src"],
|
required: ["Src"],
|
||||||
optional: ["Alt", "Caption", "Class", "Style"]
|
optional: ["Alt", "Caption", "Class", "Style"]
|
||||||
),
|
),
|
||||||
|
[AssistantComponentType.COLOR_PICKER] = new(
|
||||||
|
required: ["Name", "Label"],
|
||||||
|
optional: ["Placeholder", "ShowAlpha", "ShowToolbar", "ShowModeSwitch", "PickerVariant", "UserPrompt", "Class", "Style"]
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user