mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-02 10:40:15 +08:00
feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器
This commit is contained in:
@@ -3,13 +3,30 @@
|
||||
提供声明式的方法来注册 handler 和 capability。
|
||||
装饰器会在方法上附加元数据,由 Star.__init_subclass__ 自动收集。
|
||||
|
||||
可用的装饰器:
|
||||
触发器装饰器:
|
||||
- @on_command: 命令触发器
|
||||
- @on_message: 消息触发器(关键词/正则)
|
||||
- @on_event: 事件触发器
|
||||
- @on_schedule: 定时任务触发器
|
||||
- @require_admin: 权限标记
|
||||
- @conversation_command: 带会话生命周期的命令触发器
|
||||
|
||||
权限与过滤装饰器:
|
||||
- @require_admin / @admin_only: 管理员权限标记
|
||||
- @platforms: 限定平台
|
||||
- @group_only / @private_only: 群聊/私聊限定
|
||||
- @message_types: 消息类型过滤
|
||||
|
||||
限流装饰器:
|
||||
- @rate_limit: 滑动窗口限流
|
||||
- @cooldown: 冷却时间
|
||||
|
||||
优先级装饰器:
|
||||
- @priority: 设置执行优先级
|
||||
|
||||
能力导出装饰器:
|
||||
- @provide_capability: 声明对外暴露的能力
|
||||
- @register_llm_tool: 注册 LLM 工具
|
||||
- @register_agent: 注册 Agent
|
||||
|
||||
Example:
|
||||
class MyPlugin(Star):
|
||||
@@ -645,8 +662,35 @@ def conversation_command(
|
||||
busy_message: str | None = None,
|
||||
grace_period: float = 1.0,
|
||||
) -> Callable[[HandlerCallable], HandlerCallable]:
|
||||
"""注册带会话生命周期的命令处理方法。
|
||||
|
||||
在 ``on_command`` 基础上附加会话元数据,支持超时、并发策略和宽限期控制。
|
||||
|
||||
Args:
|
||||
command: 命令名称或序列(首项为正式名,其余视为别名)
|
||||
aliases: 额外别名列表
|
||||
description: 命令描述
|
||||
timeout: 会话超时时间(秒),必须为正整数
|
||||
mode: 会话冲突时的行为:
|
||||
- ``"replace"``: 替换当前会话
|
||||
- ``"reject"``: 拒绝新请求
|
||||
busy_message: 拒绝新请求时的提示消息
|
||||
grace_period: 宽限期(秒),用于会话生命周期处理
|
||||
|
||||
Returns:
|
||||
装饰器函数
|
||||
|
||||
Raises:
|
||||
ValueError: mode 不合法、timeout 非正整数或 grace_period 非正数
|
||||
|
||||
Example:
|
||||
@conversation_command("chat", timeout=120, mode="reject", busy_message="请稍后再试")
|
||||
async def chat(self, event: MessageEvent, ctx: Context):
|
||||
await event.reply("开始对话...")
|
||||
"""
|
||||
if mode not in {"replace", "reject"}:
|
||||
raise ValueError("conversation_command mode must be 'replace' or 'reject'")
|
||||
# bool 是 int 子类,需单独排除
|
||||
if isinstance(timeout, bool) or int(timeout) <= 0:
|
||||
raise ValueError("conversation_command timeout must be a positive integer")
|
||||
if float(grace_period) <= 0:
|
||||
|
||||
@@ -60,12 +60,12 @@ from ..protocol.descriptors import (
|
||||
from ..schedule import ScheduleContext
|
||||
from ..session_waiter import SessionWaiterManager
|
||||
from ..star import Star
|
||||
from .capability_dispatcher import CapabilityDispatcher
|
||||
from ._command_matching import (
|
||||
build_command_args,
|
||||
build_regex_args,
|
||||
match_command_name,
|
||||
)
|
||||
from .capability_dispatcher import CapabilityDispatcher
|
||||
from .limiter import LimiterEngine
|
||||
from .loader import LoadedHandler
|
||||
|
||||
@@ -456,7 +456,7 @@ class HandlerDispatcher:
|
||||
) -> dict[str, Any]:
|
||||
assert loaded.conversation is not None
|
||||
conversation_meta = loaded.conversation
|
||||
summary = {"sent_message": False, "stop": False, "call_llm": False}
|
||||
summary = {"sent_message": False, "stop": True, "call_llm": False}
|
||||
key = f"{self._resolve_plugin_id(loaded)}:{event.session_id}"
|
||||
active = self._conversations.get(key)
|
||||
if active is not None and not active.task.done():
|
||||
|
||||
Reference in New Issue
Block a user