mirror of https://github.com/Mai-with-u/MaiBot.git
feat(webui): enhance ConfigSchemaGenerator with field_docs and UI metadata
- Add AttrDocBase.get_class_field_docs() classmethod for class-level field docs extraction - Merge json_schema_extra (x-widget, x-icon, step) into schema output - Map Pydantic constraints (ge/le) to minValue/maxValue for frontend compatibility - Add ge=0, le=1 constraints to ChatConfig.talk_value for validation Completes Task 1 (including subtasks 1a, 1b, 1c, 1d) of webui-config-visualization-refactor plan.pull/1496/head
parent
19c9c5a39a
commit
278a084c23
|
|
@ -5,7 +5,7 @@ import types
|
|||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from typing import Union, get_args, get_origin, Tuple, Any, List, Dict, Set, Literal
|
||||
from typing import Any, Dict, List, Literal, Set, Tuple, Union, cast, get_args, get_origin
|
||||
|
||||
__all__ = ["ConfigBase", "Field", "AttributeData"]
|
||||
|
||||
|
|
@ -44,6 +44,16 @@ class AttrDocBase:
|
|||
# 从类定义节点中提取字段文档
|
||||
return self._extract_field_docs(class_node, allow_extra_methods)
|
||||
|
||||
@classmethod
|
||||
def get_class_field_docs(cls) -> dict[str, str]:
|
||||
class_source = cls._get_class_source()
|
||||
class_node = cls._find_class_node(class_source)
|
||||
return AttrDocBase._extract_field_docs(
|
||||
cast(AttrDocBase, cast(Any, cls)),
|
||||
class_node,
|
||||
allow_extra_methods=False,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _get_class_source(cls) -> str:
|
||||
"""获取类定义所在文件的完整源代码"""
|
||||
|
|
@ -265,7 +275,7 @@ class ConfigBase(BaseModel, AttrDocBase):
|
|||
if origin_type in (int, float, str, bool, complex, bytes, Any):
|
||||
continue
|
||||
# 允许嵌套的ConfigBase自定义类
|
||||
if inspect.isclass(origin_type) and issubclass(origin_type, ConfigBase): # type: ignore
|
||||
if isinstance(origin_type, type) and issubclass(cast(type, origin_type), ConfigBase):
|
||||
continue
|
||||
# 只允许 list, set, dict 三类泛型
|
||||
if origin_type not in (list, set, dict, List, Set, Dict, Literal):
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@ class ChatConfig(ConfigBase):
|
|||
|
||||
talk_value: float = Field(
|
||||
default=1,
|
||||
ge=0,
|
||||
le=1,
|
||||
json_schema_extra={
|
||||
"x-widget": "slider",
|
||||
"x-icon": "message-circle",
|
||||
|
|
|
|||
|
|
@ -77,6 +77,18 @@ class ConfigSchemaGenerator:
|
|||
if options:
|
||||
schema["options"] = options
|
||||
|
||||
# Task 1c: Merge json_schema_extra (x-widget, x-icon, step, etc.)
|
||||
if hasattr(field_info, "json_schema_extra") and field_info.json_schema_extra:
|
||||
schema.update(field_info.json_schema_extra)
|
||||
|
||||
# Task 1d: Map Pydantic constraints to minValue/maxValue (frontend naming convention)
|
||||
if hasattr(field_info, "metadata") and field_info.metadata:
|
||||
for constraint in field_info.metadata:
|
||||
if hasattr(constraint, "ge"):
|
||||
schema["minValue"] = constraint.ge
|
||||
if hasattr(constraint, "le"):
|
||||
schema["maxValue"] = constraint.le
|
||||
|
||||
return schema
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
Loading…
Reference in New Issue