re-style: 格式化代码

This commit is contained in:
John Richard
2025-10-02 20:26:01 +08:00
parent ecb02cae31
commit 7923eafef3
263 changed files with 3103 additions and 3123 deletions

View File

@@ -4,31 +4,31 @@
提供插件开发的基础类和类型定义
"""
from .base_plugin import BasePlugin
from .base_action import BaseAction
from .base_tool import BaseTool
from .base_command import BaseCommand
from .base_events_handler import BaseEventHandler
from .base_plugin import BasePlugin
from .base_tool import BaseTool
from .command_args import CommandArgs
from .component_types import (
ComponentType,
ActionActivationType,
ActionInfo,
ChatMode,
ChatType,
ComponentInfo,
ActionInfo,
CommandInfo,
PlusCommandInfo,
ToolInfo,
PluginInfo,
PythonDependency,
ComponentInfo,
ComponentType,
EventHandlerInfo,
EventType,
MaiMessages,
PluginInfo,
PlusCommandInfo,
PythonDependency,
ToolInfo,
ToolParamType,
)
from .config_types import ConfigField
from .plus_command import PlusCommand, PlusCommandAdapter, create_plus_command_adapter
from .command_args import CommandArgs
__all__ = [
"BasePlugin",

View File

@@ -1,14 +1,11 @@
import time
import asyncio
import time
from abc import ABC, abstractmethod
from typing import Tuple, Optional, List, Dict
from src.common.logger import get_logger
from src.chat.message_receive.chat_stream import ChatStream
from src.plugin_system.base.component_types import ActionActivationType, ChatMode, ActionInfo, ComponentType, ChatType
from src.plugin_system.apis import send_api, database_api, message_api
from src.common.logger import get_logger
from src.plugin_system.apis import database_api, message_api, send_api
from src.plugin_system.base.component_types import ActionActivationType, ActionInfo, ChatMode, ChatType, ComponentType
logger = get_logger("base_action")
@@ -39,7 +36,7 @@ class BaseAction(ABC):
"""是否为二步Action。如果为TrueAction将分两步执行第一步选择操作第二步执行具体操作"""
step_one_description: str = ""
"""第一步的描述用于向LLM展示Action的基本功能"""
sub_actions: List[Tuple[str, str, Dict[str, str]]] = []
sub_actions: list[tuple[str, str, dict[str, str]]] = []
"""子Action列表格式为[(子Action名, 子Action描述, 子Action参数)]。仅在二步Action中使用"""
def __init__(
@@ -50,8 +47,8 @@ class BaseAction(ABC):
thinking_id: str,
chat_stream: ChatStream,
log_prefix: str = "",
plugin_config: Optional[dict] = None,
action_message: Optional[dict] = None,
plugin_config: dict | None = None,
action_message: dict | None = None,
**kwargs,
):
# sourcery skip: hoist-similar-statement-from-if, merge-else-if-into-elif, move-assign-in-block, swap-if-else-branches, swap-nested-ifs
@@ -109,8 +106,8 @@ class BaseAction(ABC):
# 二步Action相关实例属性
self.is_two_step_action: bool = getattr(self.__class__, "is_two_step_action", False)
self.step_one_description: str = getattr(self.__class__, "step_one_description", "")
self.sub_actions: List[Tuple[str, str, Dict[str, str]]] = getattr(self.__class__, "sub_actions", []).copy()
self._selected_sub_action: Optional[str] = None
self.sub_actions: list[tuple[str, str, dict[str, str]]] = getattr(self.__class__, "sub_actions", []).copy()
self._selected_sub_action: str | None = None
"""当前选择的子Action名称用于二步Action的状态管理"""
# =============================================================================
@@ -200,7 +197,7 @@ class BaseAction(ABC):
"""
return self._validate_chat_type()
async def wait_for_new_message(self, timeout: int = 1200) -> Tuple[bool, str]:
async def wait_for_new_message(self, timeout: int = 1200) -> tuple[bool, str]:
"""等待新消息或超时
在loop_start_time之后等待新消息如果没有新消息且没有超时就一直等待。
@@ -232,7 +229,7 @@ class BaseAction(ABC):
# 检查新消息
current_time = time.time()
new_message_count = message_api.count_new_messages(
new_message_count = await message_api.count_new_messages(
chat_id=self.chat_id, start_time=loop_start_time, end_time=current_time
)
@@ -258,7 +255,7 @@ class BaseAction(ABC):
return False, ""
except Exception as e:
logger.error(f"{self.log_prefix} 等待新消息时发生错误: {e}")
return False, f"等待新消息失败: {str(e)}"
return False, f"等待新消息失败: {e!s}"
async def send_text(self, content: str, reply_to: str = "", typing: bool = False) -> bool:
"""发送文本消息
@@ -359,7 +356,7 @@ class BaseAction(ABC):
)
async def send_command(
self, command_name: str, args: Optional[dict] = None, display_message: str = "", storage_message: bool = True
self, command_name: str, args: dict | None = None, display_message: str = "", storage_message: bool = True
) -> bool:
"""发送命令消息
@@ -400,7 +397,7 @@ class BaseAction(ABC):
logger.error(f"{self.log_prefix} 发送命令时出错: {e}")
return False
async def call_action(self, action_name: str, action_data: Optional[dict] = None) -> Tuple[bool, str]:
async def call_action(self, action_name: str, action_data: dict | None = None) -> tuple[bool, str]:
"""
在当前Action中调用另一个Action。
@@ -514,7 +511,7 @@ class BaseAction(ABC):
sub_actions=getattr(cls, "sub_actions", []).copy(),
)
async def handle_step_one(self) -> Tuple[bool, str]:
async def handle_step_one(self) -> tuple[bool, str]:
"""处理二步Action的第一步
Returns:
@@ -546,7 +543,7 @@ class BaseAction(ABC):
# 调用第二步执行
return await self.execute_step_two(selected_action)
async def execute_step_two(self, sub_action_name: str) -> Tuple[bool, str]:
async def execute_step_two(self, sub_action_name: str) -> tuple[bool, str]:
"""执行二步Action的第二步
Args:
@@ -562,7 +559,7 @@ class BaseAction(ABC):
return False, f"二步Action必须实现execute_step_two方法来处理操作: {sub_action_name}"
@abstractmethod
async def execute(self) -> Tuple[bool, str]:
async def execute(self) -> tuple[bool, str]:
"""执行Action的抽象方法子类必须实现
对于二步Action会自动处理第一步逻辑
@@ -577,7 +574,7 @@ class BaseAction(ABC):
# 普通Action由子类实现
pass
async def handle_action(self) -> Tuple[bool, str]:
async def handle_action(self) -> tuple[bool, str]:
"""兼容旧系统的handle_action接口委托给execute方法
为了保持向后兼容性旧系统的代码可能会调用handle_action方法。

View File

@@ -1,9 +1,11 @@
from abc import ABC, abstractmethod
from typing import List, TYPE_CHECKING
from typing import TYPE_CHECKING
from src.common.data_models.message_manager_data_model import StreamContext
from .component_types import ChatType
from src.plugin_system.base.component_types import ChatterInfo, ComponentType
from .component_types import ChatType
if TYPE_CHECKING:
from src.chat.planner_actions.action_manager import ChatterActionManager
@@ -13,7 +15,7 @@ class BaseChatter(ABC):
"""Chatter组件的名称"""
chatter_description: str = ""
"""Chatter组件的描述"""
chat_types: List[ChatType] = [ChatType.PRIVATE, ChatType.GROUP]
chat_types: list[ChatType] = [ChatType.PRIVATE, ChatType.GROUP]
def __init__(self, stream_id: str, action_manager: "ChatterActionManager"):
"""

View File

@@ -1,9 +1,9 @@
from abc import ABC, abstractmethod
from typing import Dict, Tuple, Optional
from src.common.logger import get_logger
from src.plugin_system.base.component_types import CommandInfo, ComponentType, ChatType
from src.chat.message_receive.message import MessageRecv
from src.common.logger import get_logger
from src.plugin_system.apis import send_api
from src.plugin_system.base.component_types import ChatType, CommandInfo, ComponentType
logger = get_logger("base_command")
@@ -29,7 +29,7 @@ class BaseCommand(ABC):
chat_type_allow: ChatType = ChatType.ALL
"""允许的聊天类型,默认为所有类型"""
def __init__(self, message: MessageRecv, plugin_config: Optional[dict] = None):
def __init__(self, message: MessageRecv, plugin_config: dict | None = None):
"""初始化Command组件
Args:
@@ -37,7 +37,7 @@ class BaseCommand(ABC):
plugin_config: 插件配置字典
"""
self.message = message
self.matched_groups: Dict[str, str] = {} # 存储正则表达式匹配的命名组
self.matched_groups: dict[str, str] = {} # 存储正则表达式匹配的命名组
self.plugin_config = plugin_config or {} # 直接存储插件配置字典
self.log_prefix = "[Command]"
@@ -55,7 +55,7 @@ class BaseCommand(ABC):
f"{'群聊' if is_group else '私聊'}, 允许类型: {self.chat_type_allow.value}"
)
def set_matched_groups(self, groups: Dict[str, str]) -> None:
def set_matched_groups(self, groups: dict[str, str]) -> None:
"""设置正则表达式匹配的命名组
Args:
@@ -93,7 +93,7 @@ class BaseCommand(ABC):
return self._validate_chat_type()
@abstractmethod
async def execute(self) -> Tuple[bool, Optional[str], bool]:
async def execute(self) -> tuple[bool, str | None, bool]:
"""执行Command的抽象方法子类必须实现
Returns:
@@ -175,7 +175,7 @@ class BaseCommand(ABC):
)
async def send_command(
self, command_name: str, args: Optional[dict] = None, display_message: str = "", storage_message: bool = True
self, command_name: str, args: dict | None = None, display_message: str = "", storage_message: bool = True
) -> bool:
"""发送命令消息

View File

@@ -1,5 +1,5 @@
import asyncio
from typing import List, Dict, Any, Optional
from typing import Any
from src.common.logger import get_logger
@@ -25,22 +25,22 @@ class HandlerResult:
class HandlerResultsCollection:
"""HandlerResult集合提供便捷的查询方法"""
def __init__(self, results: List[HandlerResult]):
def __init__(self, results: list[HandlerResult]):
self.results = results
def all_continue_process(self) -> bool:
"""检查是否所有handler的continue_process都为True"""
return all(result.continue_process for result in self.results)
def get_all_results(self) -> List[HandlerResult]:
def get_all_results(self) -> list[HandlerResult]:
"""获取所有HandlerResult"""
return self.results
def get_failed_handlers(self) -> List[HandlerResult]:
def get_failed_handlers(self) -> list[HandlerResult]:
"""获取执行失败的handler结果"""
return [result for result in self.results if not result.success]
def get_stopped_handlers(self) -> List[HandlerResult]:
def get_stopped_handlers(self) -> list[HandlerResult]:
"""获取continue_process为False的handler结果"""
return [result for result in self.results if not result.continue_process]
@@ -57,7 +57,7 @@ class HandlerResultsCollection:
else:
return {result.handler_name: result.message for result in self.results}
def get_handler_result(self, handler_name: str) -> Optional[HandlerResult]:
def get_handler_result(self, handler_name: str) -> HandlerResult | None:
"""获取指定handler的结果"""
for result in self.results:
if result.handler_name == handler_name:
@@ -72,7 +72,7 @@ class HandlerResultsCollection:
"""获取执行失败的handler数量"""
return sum(1 for result in self.results if not result.success)
def get_summary(self) -> Dict[str, Any]:
def get_summary(self) -> dict[str, Any]:
"""获取执行摘要"""
return {
"total_handlers": len(self.results),
@@ -85,13 +85,13 @@ class HandlerResultsCollection:
class BaseEvent:
def __init__(self, name: str, allowed_subscribers: List[str] = None, allowed_triggers: List[str] = None):
def __init__(self, name: str, allowed_subscribers: list[str] = None, allowed_triggers: list[str] = None):
self.name = name
self.enabled = True
self.allowed_subscribers = allowed_subscribers # 记录事件处理器名
self.allowed_triggers = allowed_triggers # 记录插件名
self.subscribers: List["BaseEventHandler"] = [] # 订阅该事件的事件处理器列表
self.subscribers: list["BaseEventHandler"] = [] # 订阅该事件的事件处理器列表
self.event_handle_lock = asyncio.Lock()

View File

@@ -1,8 +1,8 @@
from abc import ABC, abstractmethod
from typing import Tuple, Optional, List, Union
from src.common.logger import get_logger
from .component_types import EventType, EventHandlerInfo, ComponentType
from .component_types import ComponentType, EventHandlerInfo, EventType
logger = get_logger("base_event_handler")
@@ -21,7 +21,7 @@ class BaseEventHandler(ABC):
"""处理器权重,越大权重越高"""
intercept_message: bool = False
"""是否拦截消息,默认为否"""
init_subscribe: List[Union[EventType, str]] = [EventType.UNKNOWN]
init_subscribe: list[EventType | str] = [EventType.UNKNOWN]
"""初始化时订阅的事件名称"""
plugin_name = None
@@ -44,7 +44,7 @@ class BaseEventHandler(ABC):
self.plugin_config = getattr(self.__class__, "plugin_config", {})
@abstractmethod
async def execute(self, kwargs: dict | None) -> Tuple[bool, bool, Optional[str]]:
async def execute(self, kwargs: dict | None) -> tuple[bool, bool, str | None]:
"""执行事件处理的抽象方法,子类必须实现
Args:
kwargs (dict | None): 事件消息对象当你注册的事件为ON_START和ON_STOP时message为None

View File

@@ -1,13 +1,13 @@
from abc import abstractmethod
from typing import List, Type, Tuple, Union
from .plugin_base import PluginBase
from src.common.logger import get_logger
from src.plugin_system.base.component_types import ActionInfo, CommandInfo, PlusCommandInfo, EventHandlerInfo, ToolInfo
from src.plugin_system.base.component_types import ActionInfo, CommandInfo, EventHandlerInfo, PlusCommandInfo, ToolInfo
from .base_action import BaseAction
from .base_command import BaseCommand
from .base_events_handler import BaseEventHandler
from .base_tool import BaseTool
from .plugin_base import PluginBase
from .plus_command import PlusCommand
logger = get_logger("base_plugin")
@@ -28,14 +28,12 @@ class BasePlugin(PluginBase):
@abstractmethod
def get_plugin_components(
self,
) -> List[
Union[
Tuple[ActionInfo, Type[BaseAction]],
Tuple[CommandInfo, Type[BaseCommand]],
Tuple[PlusCommandInfo, Type[PlusCommand]],
Tuple[EventHandlerInfo, Type[BaseEventHandler]],
Tuple[ToolInfo, Type[BaseTool]],
]
) -> list[
tuple[ActionInfo, type[BaseAction]]
| tuple[CommandInfo, type[BaseCommand]]
| tuple[PlusCommandInfo, type[PlusCommand]]
| tuple[EventHandlerInfo, type[BaseEventHandler]]
| tuple[ToolInfo, type[BaseTool]]
]:
"""获取插件包含的组件列表

View File

@@ -1,5 +1,6 @@
from abc import ABC, abstractmethod
from typing import Any, List, Optional, Tuple
from typing import Any
from rich.traceback import install
from src.common.logger import get_logger
@@ -17,7 +18,7 @@ class BaseTool(ABC):
"""工具的名称"""
description: str = ""
"""工具的描述"""
parameters: List[Tuple[str, ToolParamType, str, bool, List[str] | None]] = []
parameters: list[tuple[str, ToolParamType, str, bool, list[str] | None]] = []
"""工具的参数定义,为[("param_name", param_type, "description", required, enum_values)]格式
param_name: 参数名称
param_type: 参数类型
@@ -35,7 +36,7 @@ class BaseTool(ABC):
"""是否为该工具启用缓存"""
cache_ttl: int = 3600
"""缓存的TTL值默认为3600秒1小时"""
semantic_cache_query_key: Optional[str] = None
semantic_cache_query_key: str | None = None
"""用于语义缓存的查询参数键名。如果设置,将使用此参数的值进行语义相似度搜索"""
# 二步工具调用相关属性
@@ -43,10 +44,10 @@ class BaseTool(ABC):
"""是否为二步工具。如果为True工具将分两步调用第一步展示工具信息第二步执行具体操作"""
step_one_description: str = ""
"""第一步的描述用于向LLM展示工具的基本功能"""
sub_tools: List[Tuple[str, str, List[Tuple[str, ToolParamType, str, bool, List[str] | None]]]] = []
sub_tools: list[tuple[str, str, list[tuple[str, ToolParamType, str, bool, list[str] | None]]]] = []
"""子工具列表,格式为[(子工具名, 子工具描述, 子工具参数)]。仅在二步工具中使用"""
def __init__(self, plugin_config: Optional[dict] = None):
def __init__(self, plugin_config: dict | None = None):
self.plugin_config = plugin_config or {} # 直接存储插件配置字典
@classmethod
@@ -101,7 +102,7 @@ class BaseTool(ABC):
raise ValueError(f"未找到子工具: {sub_tool_name}")
@classmethod
def get_all_sub_tool_definitions(cls) -> List[dict[str, Any]]:
def get_all_sub_tool_definitions(cls) -> list[dict[str, Any]]:
"""获取所有子工具的定义
Returns:

View File

@@ -3,7 +3,6 @@
提供简单易用的命令参数解析功能
"""
from typing import List, Optional
import shlex
@@ -20,7 +19,7 @@ class CommandArgs:
raw_args: 原始参数字符串
"""
self._raw_args = raw_args.strip()
self._parsed_args: Optional[List[str]] = None
self._parsed_args: list[str] | None = None
def get_raw(self) -> str:
"""获取完整的参数字符串
@@ -30,7 +29,7 @@ class CommandArgs:
"""
return self._raw_args
def get_args(self) -> List[str]:
def get_args(self) -> list[str]:
"""获取解析后的参数列表
将参数按空格分割,支持引号包围的参数

View File

@@ -1,10 +1,11 @@
from enum import Enum
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass, field
from enum import Enum
from typing import Any
from maim_message import Seg
from src.llm_models.payload_content.tool_option import ToolParamType as ToolParamType
from src.llm_models.payload_content.tool_option import ToolCall as ToolCall
from src.llm_models.payload_content.tool_option import ToolParamType as ToolParamType
# 组件类型枚举
@@ -114,7 +115,7 @@ class ComponentInfo:
enabled: bool = True # 是否启用
plugin_name: str = "" # 所属插件名称
is_built_in: bool = False # 是否为内置组件
metadata: Dict[str, Any] = field(default_factory=dict) # 额外元数据
metadata: dict[str, Any] = field(default_factory=dict) # 额外元数据
def __post_init__(self):
if self.metadata is None:
@@ -125,18 +126,18 @@ class ComponentInfo:
class ActionInfo(ComponentInfo):
"""动作组件信息"""
action_parameters: Dict[str, str] = field(
action_parameters: dict[str, str] = field(
default_factory=dict
) # 动作参数与描述,例如 {"param1": "描述1", "param2": "描述2"}
action_require: List[str] = field(default_factory=list) # 动作需求说明
associated_types: List[str] = field(default_factory=list) # 关联的消息类型
action_require: list[str] = field(default_factory=list) # 动作需求说明
associated_types: list[str] = field(default_factory=list) # 关联的消息类型
# 激活类型相关
focus_activation_type: ActionActivationType = ActionActivationType.ALWAYS
normal_activation_type: ActionActivationType = ActionActivationType.ALWAYS
activation_type: ActionActivationType = ActionActivationType.ALWAYS
random_activation_probability: float = 0.0
llm_judge_prompt: str = ""
activation_keywords: List[str] = field(default_factory=list) # 激活关键词列表
activation_keywords: list[str] = field(default_factory=list) # 激活关键词列表
keyword_case_sensitive: bool = False
# 模式和并行设置
mode_enable: ChatMode = ChatMode.ALL
@@ -145,7 +146,7 @@ class ActionInfo(ComponentInfo):
# 二步Action相关属性
is_two_step_action: bool = False # 是否为二步Action
step_one_description: str = "" # 第一步的描述
sub_actions: List[Tuple[str, str, Dict[str, str]]] = field(default_factory=list) # 子Action列表
sub_actions: list[tuple[str, str, dict[str, str]]] = field(default_factory=list) # 子Action列表
def __post_init__(self):
super().__post_init__()
@@ -178,7 +179,7 @@ class CommandInfo(ComponentInfo):
class PlusCommandInfo(ComponentInfo):
"""增强命令组件信息"""
command_aliases: List[str] = field(default_factory=list) # 命令别名列表
command_aliases: list[str] = field(default_factory=list) # 命令别名列表
priority: int = 0 # 命令优先级
chat_type_allow: ChatType = ChatType.ALL # 允许的聊天类型
intercept_message: bool = False # 是否拦截消息
@@ -194,7 +195,7 @@ class PlusCommandInfo(ComponentInfo):
class ToolInfo(ComponentInfo):
"""工具组件信息"""
tool_parameters: List[Tuple[str, ToolParamType, str, bool, List[str] | None]] = field(
tool_parameters: list[tuple[str, ToolParamType, str, bool, list[str] | None]] = field(
default_factory=list
) # 工具参数定义
tool_description: str = "" # 工具描述
@@ -248,18 +249,18 @@ class PluginInfo:
author: str = "" # 插件作者
enabled: bool = True # 是否启用
is_built_in: bool = False # 是否为内置插件
components: List[ComponentInfo] = field(default_factory=list) # 包含的组件列表
dependencies: List[str] = field(default_factory=list) # 依赖的其他插件
python_dependencies: List[PythonDependency] = field(default_factory=list) # Python包依赖
components: list[ComponentInfo] = field(default_factory=list) # 包含的组件列表
dependencies: list[str] = field(default_factory=list) # 依赖的其他插件
python_dependencies: list[PythonDependency] = field(default_factory=list) # Python包依赖
config_file: str = "" # 配置文件路径
metadata: Dict[str, Any] = field(default_factory=dict) # 额外元数据
metadata: dict[str, Any] = field(default_factory=dict) # 额外元数据
# 新增manifest相关信息
manifest_data: Dict[str, Any] = field(default_factory=dict) # manifest文件数据
manifest_data: dict[str, Any] = field(default_factory=dict) # manifest文件数据
license: str = "" # 插件许可证
homepage_url: str = "" # 插件主页
repository_url: str = "" # 插件仓库地址
keywords: List[str] = field(default_factory=list) # 插件关键词
categories: List[str] = field(default_factory=list) # 插件分类
keywords: list[str] = field(default_factory=list) # 插件关键词
categories: list[str] = field(default_factory=list) # 插件分类
min_host_version: str = "" # 最低主机版本要求
max_host_version: str = "" # 最高主机版本要求
@@ -279,7 +280,7 @@ class PluginInfo:
if self.categories is None:
self.categories = []
def get_missing_packages(self) -> List[PythonDependency]:
def get_missing_packages(self) -> list[PythonDependency]:
"""检查缺失的Python包"""
missing = []
for dep in self.python_dependencies:
@@ -290,7 +291,7 @@ class PluginInfo:
missing.append(dep)
return missing
def get_pip_requirements(self) -> List[str]:
def get_pip_requirements(self) -> list[str]:
"""获取所有pip安装格式的依赖"""
return [dep.get_pip_requirement() for dep in self.python_dependencies]
@@ -299,16 +300,16 @@ class PluginInfo:
class MaiMessages:
"""MaiM插件消息"""
message_segments: List[Seg] = field(default_factory=list)
message_segments: list[Seg] = field(default_factory=list)
"""消息段列表,支持多段消息"""
message_base_info: Dict[str, Any] = field(default_factory=dict)
message_base_info: dict[str, Any] = field(default_factory=dict)
"""消息基本信息,包含平台,用户信息等数据"""
plain_text: str = ""
"""纯文本消息内容"""
raw_message: Optional[str] = None
raw_message: str | None = None
"""原始消息内容"""
is_group_message: bool = False
@@ -317,28 +318,28 @@ class MaiMessages:
is_private_message: bool = False
"""是否为私聊消息"""
stream_id: Optional[str] = None
stream_id: str | None = None
"""流ID用于标识消息流"""
llm_prompt: Optional[str] = None
llm_prompt: str | None = None
"""LLM提示词"""
llm_response_content: Optional[str] = None
llm_response_content: str | None = None
"""LLM响应内容"""
llm_response_reasoning: Optional[str] = None
llm_response_reasoning: str | None = None
"""LLM响应推理内容"""
llm_response_model: Optional[str] = None
llm_response_model: str | None = None
"""LLM响应模型名称"""
llm_response_tool_call: Optional[List[ToolCall]] = None
llm_response_tool_call: list[ToolCall] | None = None
"""LLM使用的工具调用"""
action_usage: Optional[List[str]] = None
action_usage: list[str] | None = None
"""使用的Action"""
additional_data: Dict[Any, Any] = field(default_factory=dict)
additional_data: dict[Any, Any] = field(default_factory=dict)
"""附加数据,可以存储额外信息"""
def __post_init__(self):

View File

@@ -2,8 +2,8 @@
插件系统配置类型定义
"""
from typing import Any, Optional, List
from dataclasses import dataclass, field
from typing import Any
@dataclass
@@ -13,6 +13,6 @@ class ConfigField:
type: type # 字段类型
default: Any # 默认值
description: str # 字段描述
example: Optional[str] = None # 示例值
example: str | None = None # 示例值
required: bool = False # 是否必需
choices: Optional[List[Any]] = field(default_factory=list) # 可选值列表
choices: list[Any] | None = field(default_factory=list) # 可选值列表

View File

@@ -1,11 +1,12 @@
from abc import ABC, abstractmethod
from typing import Dict, List, Any, Union
import os
import toml
import orjson
import shutil
import datetime
import os
import shutil
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Any
import orjson
import toml
from src.common.logger import get_logger
from src.config.config import CONFIG_DIR
@@ -38,12 +39,12 @@ class PluginBase(ABC):
@property
@abstractmethod
def dependencies(self) -> List[str]:
def dependencies(self) -> list[str]:
return [] # 依赖的其他插件
@property
@abstractmethod
def python_dependencies(self) -> List[Union[str, PythonDependency]]:
def python_dependencies(self) -> list[str | PythonDependency]:
return [] # Python包依赖支持字符串列表或PythonDependency对象列表
@property
@@ -53,15 +54,15 @@ class PluginBase(ABC):
# manifest文件相关
manifest_file_name: str = "_manifest.json" # manifest文件名
manifest_data: Dict[str, Any] = {} # manifest数据
manifest_data: dict[str, Any] = {} # manifest数据
# 配置定义
@property
@abstractmethod
def config_schema(self) -> Dict[str, Union[Dict[str, ConfigField], str]]:
def config_schema(self) -> dict[str, dict[str, ConfigField] | str]:
return {}
config_section_descriptions: Dict[str, str] = {}
config_section_descriptions: dict[str, str] = {}
def __init__(self, plugin_dir: str):
"""初始化插件
@@ -69,7 +70,7 @@ class PluginBase(ABC):
Args:
plugin_dir: 插件目录路径,由插件管理器传递
"""
self.config: Dict[str, Any] = {} # 插件配置
self.config: dict[str, Any] = {} # 插件配置
self.plugin_dir = plugin_dir # 插件目录路径
self.log_prefix = f"[Plugin:{self.plugin_name}]"
self._is_enabled = self.enable_plugin # 从插件定义中获取默认启用状态
@@ -144,7 +145,7 @@ class PluginBase(ABC):
raise FileNotFoundError(error_msg)
try:
with open(manifest_path, "r", encoding="utf-8") as f:
with open(manifest_path, encoding="utf-8") as f:
self.manifest_data = orjson.loads(f.read())
logger.debug(f"{self.log_prefix} 成功加载manifest文件: {manifest_path}")
@@ -155,8 +156,8 @@ class PluginBase(ABC):
except orjson.JSONDecodeError as e:
error_msg = f"{self.log_prefix} manifest文件格式错误: {e}"
logger.error(error_msg)
raise ValueError(error_msg) # noqa
except IOError as e:
raise ValueError(error_msg)
except OSError as e:
error_msg = f"{self.log_prefix} 读取manifest文件失败: {e}"
logger.error(error_msg)
raise IOError(error_msg) # noqa
@@ -266,7 +267,7 @@ class PluginBase(ABC):
with open(config_file_path, "w", encoding="utf-8") as f:
f.write(toml_str)
logger.info(f"{self.log_prefix} 已生成默认配置文件: {config_file_path}")
except IOError as e:
except OSError as e:
logger.error(f"{self.log_prefix} 保存默认配置文件失败: {e}", exc_info=True)
def _backup_config_file(self, config_file_path: str) -> str:
@@ -288,13 +289,13 @@ class PluginBase(ABC):
return ""
def _synchronize_config(
self, schema_config: Dict[str, Any], user_config: Dict[str, Any]
) -> tuple[Dict[str, Any], bool]:
self, schema_config: dict[str, Any], user_config: dict[str, Any]
) -> tuple[dict[str, Any], bool]:
"""递归地将用户配置与 schema 同步,返回同步后的配置和是否发生变化的标志"""
changed = False
# 内部递归函数
def _sync_dicts(schema_dict: Dict[str, Any], user_dict: Dict[str, Any], parent_key: str = "") -> Dict[str, Any]:
def _sync_dicts(schema_dict: dict[str, Any], user_dict: dict[str, Any], parent_key: str = "") -> dict[str, Any]:
nonlocal changed
synced_dict = schema_dict.copy()
@@ -326,7 +327,7 @@ class PluginBase(ABC):
final_config = _sync_dicts(schema_config, user_config)
return final_config, changed
def _generate_config_from_schema(self) -> Dict[str, Any]:
def _generate_config_from_schema(self) -> dict[str, Any]:
# sourcery skip: dict-comprehension
"""根据schema生成配置数据结构不写入文件"""
if not self.config_schema:
@@ -348,7 +349,7 @@ class PluginBase(ABC):
return config_data
def _save_config_to_file(self, config_data: Dict[str, Any], config_file_path: str):
def _save_config_to_file(self, config_data: dict[str, Any], config_file_path: str):
"""将配置数据保存为TOML文件包含注释"""
if not self.config_schema:
logger.debug(f"{self.log_prefix} 插件未定义config_schema不生成配置文件")
@@ -410,7 +411,7 @@ class PluginBase(ABC):
with open(config_file_path, "w", encoding="utf-8") as f:
f.write(toml_str)
logger.info(f"{self.log_prefix} 配置文件已保存: {config_file_path}")
except IOError as e:
except OSError as e:
logger.error(f"{self.log_prefix} 保存配置文件失败: {e}", exc_info=True)
def _load_plugin_config(self): # sourcery skip: extract-method
@@ -456,7 +457,7 @@ class PluginBase(ABC):
return
try:
with open(user_config_path, "r", encoding="utf-8") as f:
with open(user_config_path, encoding="utf-8") as f:
user_config = toml.load(f) or {}
except Exception as e:
logger.error(f"{self.log_prefix} 加载用户配置文件 {user_config_path} 失败: {e}", exc_info=True)
@@ -520,7 +521,7 @@ class PluginBase(ABC):
return current
def _normalize_python_dependencies(self, dependencies: Any) -> List[PythonDependency]:
def _normalize_python_dependencies(self, dependencies: Any) -> list[PythonDependency]:
"""将依赖列表标准化为PythonDependency对象"""
from packaging.requirements import Requirement
@@ -549,7 +550,7 @@ class PluginBase(ABC):
return normalized
def _check_python_dependencies(self, dependencies: List[PythonDependency]) -> bool:
def _check_python_dependencies(self, dependencies: list[PythonDependency]) -> bool:
"""检查Python依赖并尝试自动安装"""
if not dependencies:
logger.info(f"{self.log_prefix} 无Python依赖需要检查")

View File

@@ -3,17 +3,16 @@
提供更简单易用的命令处理方式,无需手写正则表达式
"""
from abc import ABC, abstractmethod
from typing import Tuple, Optional, List
import re
from abc import ABC, abstractmethod
from src.common.logger import get_logger
from src.plugin_system.base.component_types import PlusCommandInfo, ComponentType, ChatType
from src.chat.message_receive.message import MessageRecv
from src.plugin_system.apis import send_api
from src.plugin_system.base.command_args import CommandArgs
from src.plugin_system.base.base_command import BaseCommand
from src.common.logger import get_logger
from src.config.config import global_config
from src.plugin_system.apis import send_api
from src.plugin_system.base.base_command import BaseCommand
from src.plugin_system.base.command_args import CommandArgs
from src.plugin_system.base.component_types import ChatType, ComponentType, PlusCommandInfo
logger = get_logger("plus_command")
@@ -39,7 +38,7 @@ class PlusCommand(ABC):
command_description: str = ""
"""命令描述"""
command_aliases: List[str] = []
command_aliases: list[str] = []
"""命令别名列表,如 ['say', 'repeat']"""
priority: int = 0
@@ -51,7 +50,7 @@ class PlusCommand(ABC):
intercept_message: bool = False
"""是否拦截消息,不进行后续处理"""
def __init__(self, message: MessageRecv, plugin_config: Optional[dict] = None):
def __init__(self, message: MessageRecv, plugin_config: dict | None = None):
"""初始化命令组件
Args:
@@ -172,7 +171,7 @@ class PlusCommand(ABC):
return False
@abstractmethod
async def execute(self, args: CommandArgs) -> Tuple[bool, Optional[str], bool]:
async def execute(self, args: CommandArgs) -> tuple[bool, str | None, bool]:
"""执行命令的抽象方法,子类必须实现
Args:
@@ -341,7 +340,7 @@ class PlusCommandAdapter(BaseCommand):
将PlusCommand适配到现有的插件系统继承BaseCommand
"""
def __init__(self, plus_command_class, message: MessageRecv, plugin_config: Optional[dict] = None):
def __init__(self, plus_command_class, message: MessageRecv, plugin_config: dict | None = None):
"""初始化适配器
Args:
@@ -363,7 +362,7 @@ class PlusCommandAdapter(BaseCommand):
# 创建PlusCommand实例
self.plus_command = plus_command_class(message, plugin_config)
async def execute(self) -> Tuple[bool, Optional[str], bool]:
async def execute(self) -> tuple[bool, str | None, bool]:
"""执行命令
Returns:
@@ -382,7 +381,7 @@ class PlusCommandAdapter(BaseCommand):
return await self.plus_command.execute(self.plus_command.args)
except Exception as e:
logger.error(f"执行命令时出错: {e}", exc_info=True)
return False, f"命令执行出错: {str(e)}", self.intercept_message
return False, f"命令执行出错: {e!s}", self.intercept_message
def create_plus_command_adapter(plus_command_class):
@@ -401,13 +400,13 @@ def create_plus_command_adapter(plus_command_class):
command_pattern = plus_command_class._generate_command_pattern()
chat_type_allow = getattr(plus_command_class, "chat_type_allow", ChatType.ALL)
def __init__(self, message: MessageRecv, plugin_config: Optional[dict] = None):
def __init__(self, message: MessageRecv, plugin_config: dict | None = None):
super().__init__(message, plugin_config)
self.plus_command = plus_command_class(message, plugin_config)
self.priority = getattr(plus_command_class, "priority", 0)
self.intercept_message = getattr(plus_command_class, "intercept_message", False)
async def execute(self) -> Tuple[bool, Optional[str], bool]:
async def execute(self) -> tuple[bool, str | None, bool]:
"""执行命令"""
# 从BaseCommand的正则匹配结果中提取参数
args_text = ""
@@ -429,7 +428,7 @@ def create_plus_command_adapter(plus_command_class):
return await self.plus_command.execute(command_args)
except Exception as e:
logger.error(f"执行命令时出错: {e}", exc_info=True)
return False, f"命令执行出错: {str(e)}", self.intercept_message
return False, f"命令执行出错: {e!s}", self.intercept_message
return AdapterClass