Skip to content

Plugin Configuration Schema Development Documentation

This document introduces how to use MaiBot's plugin configuration system to make your plugin support WebUI visual configuration.

Overview

MaiBot's plugin configuration system allows plugin developers to define configuration items declaratively, and WebUI automatically generates configuration forms based on the configuration Schema.

Core Components

ComponentDescription
ConfigFieldConfiguration field definition, describing type, default value, UI control, etc. of a single configuration item
ConfigSectionConfiguration section metadata, describing title, icon, etc. of a group of related configurations
ConfigTabTab definition, used to organize multiple sections into a tab
ConfigLayoutPage layout definition, supporting automatic layout, tab layout, etc.

Quick Start

Basic Usage

python
from src.plugin_system.base.base_plugin import BasePlugin
from src.plugin_system.base.config_types import ConfigField

class MyPlugin(BasePlugin):
    plugin_name = "my_plugin"
    enable_plugin = True
    dependencies = []
    python_dependencies = []
    config_file_name = "config.toml"
    
    # Define configuration Schema
    config_schema = {
        "plugin": {
            "name": ConfigField(
                type=str,
                default="my_plugin",
                description="Plugin name",
                required=True
            ),
            "enabled": ConfigField(
                type=bool,
                default=True,
                description="Whether to enable plugin"
            ),
        },
        "api": {
            "key": ConfigField(
                type=str,
                default="",
                description="API key",
                input_type="password",
                placeholder="Please enter your API key"
            ),
            "timeout": ConfigField(
                type=int,
                default=30,
                description="Request timeout (seconds)",
                min=1,
                max=120
            ),
        }
    }
    
    # Optional: Section metadata
    config_section_descriptions = {
        "plugin": "Plugin basic information",
        "api": "API configuration",
    }

ConfigField Details

Constructor Parameters

Basic Fields (Required)

ParameterTypeDescription
typetypeField type: str, int, float, bool, list, dict
defaultAnyDefault value
descriptionstrField description, also used as default label
ParameterTypeDescription
requiredboolWhether required, default False
choicesList[Any]Optional value list, used for dropdown selection
minfloatMinimum value (numeric types)
maxfloatMaximum value (numeric types)
stepfloatStep value (numeric types)
patternstrRegular validation (string type)
max_lengthintMaximum length (string type)
examplestrExample value, used for generating configuration file comments

UI Display Control

ParameterTypeDescription
labelstrDisplay label, default uses description
placeholderstrInput box placeholder
hintstrHint text below field
iconstrField icon name
hiddenboolWhether hidden in UI, default False
disabledboolWhether editing disabled, default False
orderintSorting weight, smaller numbers appear first, default 0

Input Control Types

ParameterTypeDescription
input_typestrForce specify control type, automatically inferred if not specified
rowsinttextarea row count, default 3

Supported input_type values:

ValueDescription
textSingle-line text input box
passwordPassword input box (with show/hide toggle)
textareaMulti-line text area
numberNumber input box
switchSwitch toggle (boolean value)
sliderSlider (needs to cooperate with min/max)
selectDropdown selection (needs to cooperate with choices)
listDynamic list editor (supports drag-and-drop sorting)
colorColor picker (planned)
codeCode editor (planned)
fileFile upload (planned)
jsonJSON editor (planned)

Grouping and Conditional Display

ParameterTypeDescription
groupstrField grouping, further subdivision within section
depends_onstrDependent field path, e.g., "section.field"
depends_valueAnyValue needed for dependent field

List Type Specific

ParameterTypeDescription
item_typestrArray element type: "string", "number", "object"
item_fieldsDict[str, Any]When item_type="object", define object field structure
min_itemsintArray minimum element count
max_itemsintArray maximum element count

List Type Examples:

python
# Simple string list
"keywords": ConfigField(
    type=list,
    default=["Keyword1", "Keyword2"],
    description="Trigger keywords",
    item_type="string",
    placeholder="Enter keyword",
    max_items=20,
    hint="Supports up to 20 keywords"
),

# Number list
"retry_delays": ConfigField(
    type=list,
    default=[1, 2, 5, 10],
    description="Retry delays (seconds)",
    item_type="number",
    min_items=1,
    max_items=5,
),

# Object list (complex structure)
"api_endpoints": ConfigField(
    type=list,
    default=[{"name": "Main server", "url": "https://api.example.com"}],
    description="API endpoint list",
    item_type="object",
    item_fields={
        "name": {"type": "string", "label": "Name", "placeholder": "Endpoint name"},
        "url": {"type": "string", "label": "URL", "placeholder": "https://..."},
        "priority": {"type": "number", "label": "Priority", "default": 0},
    },
    min_items=1,
    max_items=5,
),

Control Auto-inference Rules

If input_type not specified, system automatically selects control based on following rules:

ConditionControl Type
type=boolSwitch toggle
type=int/float + has min and maxSlider
type=int/floatNumberInput number input box
type=str + has choicesSelect dropdown selection
type=str + input_type="password"Password box
type=str + input_type="textarea"Textarea text area
type=listDynamicList dynamic list
type=dictJSON editor
type=str (default)Input text box

Examples

python
config_schema = {
    "api": {
        # Password input box
        "api_key": ConfigField(
            type=str,
            default="",
            description="API key",
            input_type="password",
            placeholder="sk-xxxxxxxx",
            required=True,
            hint="Obtain from service provider console"
        ),
        
        # Slider with range restriction
        "temperature": ConfigField(
            type=float,
            default=0.7,
            description="Generation temperature",
            min=0.0,
            max=2.0,
            step=0.1,
            hint="Higher values make output more random"
        ),
        
        # Dropdown selection
        "model": ConfigField(
            type=str,
            default="gpt-4",
            description="Model to use",
            choices=["gpt-3.5-turbo", "gpt-4", "gpt-4-turbo"],
            icon="cpu"
        ),
        
        # Multi-line text
        "system_prompt": ConfigField(
            type=str,
            default="",
            description="System prompt",
            input_type="textarea",
            rows=5,
            placeholder="Enter system prompt..."
        ),
        
        # Conditional display: only shows when debug is True
        "debug_log_path": ConfigField(
            type=str,
            default="./debug.log",
            description="Debug log path",
            depends_on="debug.enabled",
            depends_value=True
        ),
    }
}

ConfigSection Details

Used to add metadata to configuration sections, such as title, icon, whether collapsed by default, etc.

Method 1: Simple String

python
config_section_descriptions = {
    "plugin": "Plugin basic information",
    "api": "API configuration",
}

Method 2: Using ConfigSection

python
from src.plugin_system.base.config_types import ConfigSection

config_section_descriptions = {
    "plugin": ConfigSection(
        title="Plugin basic information",
        description="Configure plugin basic properties",
        icon="settings",
        order=1
    ),
    "api": ConfigSection(
        title="API configuration",
        description="External API connection parameters",
        icon="cloud",
        order=2
    ),
    "advanced": ConfigSection(
        title="Advanced settings",
        icon="code",
        collapsed=True,  # Collapsed by default
        order=99
    ),
}

Method 3: Using Convenience Function

python
from src.plugin_system.base.config_types import section_meta

config_section_descriptions = {
    "plugin": section_meta("Plugin basic information", icon="settings", order=1),
    "api": section_meta("API configuration", icon="cloud", order=2),
    "advanced": section_meta("Advanced settings", collapsed=True, order=99),
}

ConfigSection Parameters

ParameterTypeDefault ValueDescription
titlestrRequiredDisplay title
descriptionstrNoneDetailed description
iconstrNoneIcon name
collapsedboolFalseWhether collapsed by default
orderint0Sorting weight

Custom Layout

By default, all sections are displayed as collapsible panels. If more complex layout needed, can use config_layout.

Tab Layout

python
from src.plugin_system.base.config_types import ConfigLayout, ConfigTab

class MyPlugin(BasePlugin):
    # ... other properties ...
    
    config_schema = {
        "plugin": { ... },
        "api": { ... },
        "model": { ... },
        "debug": { ... },
        "logging": { ... },
    }
    
    config_layout = ConfigLayout(
        type="tabs",
        tabs=[
            ConfigTab(
                id="basic",
                title="Basic settings",
                sections=["plugin", "api"],
                icon="settings"
            ),
            ConfigTab(
                id="model",
                title="Model configuration",
                sections=["model"],
                icon="cpu"
            ),
            ConfigTab(
                id="dev",
                title="Developer",
                sections=["debug", "logging"],
                icon="terminal",
                badge="Dev"  # Display badge
            ),
        ]
    )

ConfigTab Parameters

ParameterTypeDefault ValueDescription
idstrRequiredTab ID
titlestrRequiredDisplay title
sectionsList[str][]Included section name list
iconstrNoneIcon name
orderint0Sorting weight
badgestrNoneBadge text

ConfigLayout Parameters

ParameterTypeDefault ValueDescription
typestr"auto"Layout type: auto, tabs, pages
tabsList[ConfigTab][]Tab list

Layout type description:

TypeDescription
autoAutomatic layout, sections displayed as collapsible panels
tabsTab layout, top tab switching
pagesPage layout, left navigation + right content (planned)

Complete Example

python
from src.plugin_system.base.base_plugin import BasePlugin
from src.plugin_system.base.config_types import (
    ConfigField,
    ConfigSection,
    ConfigLayout,
    ConfigTab,
)
from src.plugin_system.apis.plugin_register_api import register_plugin


@register_plugin
class TTSPlugin(BasePlugin):
    """TTS Voice Synthesis Plugin"""
    
    plugin_name = "tts_plugin"
    enable_plugin = True
    dependencies = []
    python_dependencies = []
    config_file_name = "config.toml"
    
    # Configuration Schema
    config_schema = {
        "plugin": {
            "name": ConfigField(
                type=str,
                default="tts_plugin",
                description="Plugin name",
                required=True
            ),
            "version": ConfigField(
                type=str,
                default="1.0.0",
                description="Plugin version"
            ),
            "enabled": ConfigField(
                type=bool,
                default=True,
                description="Whether to enable plugin"
            ),
        },
        "tts": {
            "provider": ConfigField(
                type=str,
                default="azure",
                description="TTS service provider",
                choices=["azure", "google", "local"],
                order=1
            ),
            "api_key": ConfigField(
                type=str,
                default="",
                description="API key",
                input_type="password",
                required=True,
                order=2
            ),
            "voice": ConfigField(
                type=str,
                default="zh-CN-XiaoxiaoNeural",
                description="Voice role",
                placeholder="e.g.: zh-CN-XiaoxiaoNeural",
                order=3
            ),
            "speed": ConfigField(
                type=float,
                default=1.0,
                description="Speech speed",
                min=0.5,
                max=2.0,
                step=0.1,
                order=4
            ),
        },
        "cache": {
            "enabled": ConfigField(
                type=bool,
                default=True,
                description="Enable cache"
            ),
            "max_size": ConfigField(
                type=int,
                default=100,
                description="Maximum cache count",
                min=10,
                max=1000,
                depends_on="cache.enabled",
                depends_value=True
            ),
            "ttl": ConfigField(
                type=int,
                default=3600,
                description="Cache expiration time (seconds)",
                min=60,
                depends_on="cache.enabled",
                depends_value=True
            ),
        },
        "debug": {
            "enabled": ConfigField(
                type=bool,
                default=False,
                description="Debug mode"
            ),
            "log_level": ConfigField(
                type=str,
                default="INFO",
                description="Log level",
                choices=["DEBUG", "INFO", "WARNING", "ERROR"]
            ),
        },
    }
    
    # Section metadata
    config_section_descriptions = {
        "plugin": ConfigSection(
            title="Plugin information",
            icon="info",
            order=1
        ),
        "tts": ConfigSection(
            title="TTS configuration",
            description="Voice synthesis related settings",
            icon="volume-2",
            order=2
        ),
        "cache": ConfigSection(
            title="Cache settings",
            icon="database",
            order=3
        ),
        "debug": ConfigSection(
            title="Debug options",
            icon="bug",
            collapsed=True,
            order=99
        ),
    }
    
    # Custom layout (optional)
    config_layout = ConfigLayout(
        type="tabs",
        tabs=[
            ConfigTab(id="main", title="Main settings", sections=["plugin", "tts"]),
            ConfigTab(id="advanced", title="Advanced", sections=["cache", "debug"]),
        ]
    )
    
    # ... plugin other implementations ...

Reading Configuration in Plugin

python
class MyPlugin(BasePlugin):
    def some_method(self):
        # Read single configuration item
        api_key = self.get_config("api.key")
        timeout = self.get_config("api.timeout", default=30)
        
        # Read entire section
        api_config = self.config.get("api", {})
        
        # Check if enabled
        if self.get_config("plugin.enabled", True):
            # Execute logic
            pass

WebUI API

WebUI provides following APIs for configuration management:

EndpointMethodDescription
/api/webui/plugins/config/{plugin_id}/schemaGETGet plugin configuration Schema
/api/webui/plugins/config/{plugin_id}GETGet current configuration values
/api/webui/plugins/config/{plugin_id}PUTUpdate configuration
/api/webui/plugins/config/{plugin_id}/resetPOSTReset to default configuration
/api/webui/plugins/config/{plugin_id}/togglePOSTToggle enable/disable status

Best Practices

1. Reasonably Organize Sections

Put related configuration items in same section, use meaningful section names.

python
# Good practice
config_schema = {
    "api": { ... },      # API related
    "model": { ... },    # Model related
    "cache": { ... },    # Cache related
}

# Avoid
config_schema = {
    "settings": { ... },  # Too general
    "misc": { ... },      # Not clear
}

2. Provide Meaningful Descriptions and Hints

python
ConfigField(
    type=str,
    default="",
    description="OpenAI API key",  # Clear description
    hint="Obtain from platform.openai.com",  # Helpful hint
    placeholder="sk-..."  # Format example
)

3. Use Appropriate Control Types

python
# Sensitive information use password box
"api_key": ConfigField(type=str, input_type="password", ...)

# Limited options use dropdown
"model": ConfigField(type=str, choices=["gpt-3.5", "gpt-4"], ...)

# Range values use slider
"temperature": ConfigField(type=float, min=0, max=2, ...)

# Long text use textarea
"prompt": ConfigField(type=str, input_type="textarea", rows=5, ...)

4. Set Reasonable Default Values

python
ConfigField(
    type=int,
    default=30,  # Reasonable default value
    min=1,
    max=120,
    description="Timeout (seconds)"
)

5. Use Conditional Display to Reduce Interface Complexity

python
"debug_enabled": ConfigField(type=bool, default=False, ...),
"debug_log_path": ConfigField(
    type=str,
    depends_on="debug.debug_enabled",
    depends_value=True,
    ...
)

6. Use order to Control Display Order

python
"important_field": ConfigField(..., order=1),
"less_important": ConfigField(..., order=10),
"rarely_used": ConfigField(..., order=99),

Migration Guide

If your plugin uses old version config_schema, upgrading is very simple:

Old Version

python
config_schema = {
    "api": {
        "key": ConfigField(type=str, default="", description="API key"),
    }
}

New Version (Fully Compatible)

Old code can continue working without modification. If need to use new features, just add new parameters:

python
config_schema = {
    "api": {
        "key": ConfigField(
            type=str,
            default="",
            description="API key",
            # New parameters
            input_type="password",
            placeholder="Please enter API key",
            hint="Obtain from console",
            required=True,
            order=1
        ),
    }
}

Frequently Asked Questions

Q: When do configuration modifications take effect?

A: After configuration saved to TOML file, need to reload plugin to take effect. WebUI will display prompt information.

Q: How to validate configuration values?

A: Currently supports basic validation (required, range, regex), complex validation logic needs to be implemented in plugin code.

Q: Which icons are supported?

A: Icons use Lucide Icons, reference https://lucide.dev/icons

Q: How to handle sensitive configuration?

A: Using input_type="password" will hide input content in UI, but still plain text storage in configuration file. If need encrypted storage, need to implement yourself.