This folder keeps the Lua manifest (`plugin.lua`) that defines a custom assistant. Treat it as the single source of truth for how AI Studio renders your assistant UI and builds the submitted prompt.
- [Example: Use Logging in lua functions](#example-use-logging-in-lua-functions)
- [General Tips](#general-tips)
- [Useful Resources](#useful-resources)
## How to Use This Documentation
Use this README in layers. The early sections are a quick reference for the overall assistant manifest shape and the available component types, while the later `... reference` sections are the full detail for each component and advanced behavior.
When you build a plugin, start with the directory layout and the `Structure` section, then jump to the component references you actually use. The resource links at the end are the primary sources for Lua and MudBlazor behavior, and the `General Tips` section collects the practical rules and gotchas that matter most while authoring `plugin.lua`.
Each assistant plugin lives in its own directory under the assistants plugin root. In practice, you usually keep the manifest in `plugin.lua`, optional icon rendering in `icon.lua`, and any bundled media in `assets/`.
-`TEXT_AREA`: user input field based on `MudTextField`; requires `Name`, `Label`, and may include `HelperText`, `HelperTextOnFocus`, `Adornment`, `AdornmentIcon`, `AdornmentText`, `AdornmentColor`, `Counter`, `MaxLength`, `IsImmediate`, `UserPrompt`, `PrefillText`, `IsSingleLine`, `ReadOnly`, `Class`, `Style`.
-`BUTTON`: invokes a Lua callback; `Props` must include `Name`, `Text`, `Action`, and may include `Variant`, `Color`, `IsFullWidth`, `Size`, `StartIcon`, `EndIcon`, `IconColor`, `IconSize`, `Class`, `Style`.
-`BUTTON_GROUP`: groups multiple `BUTTON` children in a `MudButtonGroup`; `Children` must contain only `BUTTON` components and `Props` may include `Variant`, `Color`, `Size`, `OverrideStyles`, `Vertical`, `DropShadow`, `Class`, `Style`.
-`LAYOUT_GRID`: renders a `MudGrid`; `Children` must contain only `LAYOUT_ITEM` components and `Props` may include `Justify`, `Spacing`, `Class`, `Style`.
-`LAYOUT_ITEM`: renders a `MudItem`; use it inside `LAYOUT_GRID` and configure breakpoints with `Xs`, `Sm`, `Md`, `Lg`, `Xl`, `Xxl`, plus optional `Class`, `Style`.
-`LAYOUT_PAPER`: renders a `MudPaper`; may include `Elevation`, `Height`, `MaxHeight`, `MinHeight`, `Width`, `MaxWidth`, `MinWidth`, `IsOutlined`, `IsSquare`, `Class`, `Style`.
-`LAYOUT_STACK`: renders a `MudStack`; may include `IsRow`, `IsReverse`, `Breakpoint`, `Align`, `Justify`, `Stretch`, `Wrap`, `Spacing`, `Class`, `Style`.
-`COLOR_PICKER`: color input based on `MudColorPicker`; requires `Name`, `Label`, and may include `Placeholder`, `ShowAlpha`, `ShowToolbar`, `ShowModeSwitch`, `PickerVariant`, `UserPrompt`, `Class`, `Style`.
-`IMAGE`: embeds a static illustration; `Props` must include `Src` plus optionally `Alt` and `Caption`. `Src` can be an HTTP/HTTPS URL, a `data:` URI, or a plugin-relative path (`plugin://assets/your-image.png`). The runtime will convert plugin-relative paths into `data:` URLs (base64).
Images referenced via the `plugin://` scheme must exist in the plugin directory (e.g., `assets/example.png`). Drop the file there and point `Src` at it. The component will read the file at runtime, encode it as Base64, and render it inside the assistant UI.
- Use `Type = "TEXT_AREA"` to render a MudBlazor text input or textarea.
- Required props:
-`Name`: unique state key used in prompt assembly and `BuildPrompt(input.fields)`.
-`Label`: visible field label.
- Optional props:
-`HelperText`: helper text rendered below the input.
-`HelperTextOnFocus`: defaults to `false`; show helper text only while the field is focused.
-`Adornment`: one of `Start`, `End`, `None`; invalid or omitted values fall back to `Start`.
-`AdornmentIcon`: MudBlazor icon identifier string for the adornment.
-`AdornmentText`: plain adornment text. Do not set this together with `AdornmentIcon`.
-`AdornmentColor`: one of the MudBlazor `Color` enum names such as `Primary`, `Secondary`, `Warning`; invalid or omitted values fall back to `Default`.
-`Counter`: nullable integer. Omit it to hide the counter entirely. Set `0` to show only the current character count. Set `1` or higher to show `current/max`.
-`MaxLength`: maximum number of characters allowed; defaults to `524288`.
-`IsImmediate`: defaults to `false`; updates the bound value on each input event instead of on blur/change.
-`UserPrompt`: prompt context text for this field.
-`PrefillText`: initial input value.
-`IsSingleLine`: defaults to `false`; render as a one-line input instead of a textarea.
-`ReadOnly`: defaults to `false`; disables editing.
-`Class`, `Style`: forwarded to the rendered component for layout/styling.
["UserPrompt"] = "Use this as the accent color for the generated design."
}
}
```
## Prompt Assembly - UserPrompt Property
Each component exposes a `UserPrompt` string. When the assistant runs, `AssistantDynamic` recursively iterates over the component tree and, for each component that has a prompt, emits:
```
context:
<UserPrompt>
---
user prompt:
<valueextractedfromthecomponent>
```
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 Prompt Assembly - BuildPrompt()
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.
---
### Interface
-`ASSISTANT.BuildPrompt(LuaTable input) => string` must return a **string**, the complete User Prompt.
- If the function is missing, returns `nil`, or returns a non-string, AI Studio falls back to the default prompt assembly.
- Errors in the function are caught and logged, then fall back to the default prompt assembly.
---
### `input` table shape
The function receives a single `input` Lua 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`, `COLOR_PICKER`)
-`Label` (string, when provided)
-`UserPrompt` (string, when provided)
-`input.profile`: selected profile data
-`Name`, `NeedToKnow`, `Actions`, `Num`
- When no profile is selected, values match the built-in "Use no profile" entry
```
input = {
fields = {
["<Name>"] = "<string|boolean>",
...
},
meta = {
["<Name>"] = {
Type = "<TEXT_AREA|DROPDOWN|SWITCH|WEB_CONTENT_READER|FILE_CONTENT_READER|COLOR_PICKER>",
Label = "<string?>",
UserPrompt = "<string?>"
},
...
},
profile = {
Name = "<string>",
NeedToKnow = "<string>",
Actions = "<string>",
Num = <number>
}
}
-- <Name> is the value you set in the components name property
```
---
### Using `meta` inside BuildPrompt
`input.meta` is useful when you want to dynamically build the prompt based on component type or reuse existing UI text (labels/user prompts).
#### Example: iterate all fields with labels and include their values
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
end
return table.concat(parts, "\n")
end
```
---
### 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.
1. Give every component a _**unique**_`Name`— it’s used to track state and treated like an Id.
2. Keep in mind that components and their properties are _**case-sensitive**_ (e.g. if you write `["Type"] = "heading"` instead of `["Type"] = "HEADING"` the component will not be registered). Always copy-paste the component from the `plugin.lua` manifest to avoid this.