mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-16 01:40:15 +08:00
feat: 增强装饰器功能,添加会话命令支持及相关权限和限流装饰器
This commit is contained in:
@@ -3,13 +3,30 @@
|
|||||||
提供声明式的方法来注册 handler 和 capability。
|
提供声明式的方法来注册 handler 和 capability。
|
||||||
装饰器会在方法上附加元数据,由 Star.__init_subclass__ 自动收集。
|
装饰器会在方法上附加元数据,由 Star.__init_subclass__ 自动收集。
|
||||||
|
|
||||||
可用的装饰器:
|
触发器装饰器:
|
||||||
- @on_command: 命令触发器
|
- @on_command: 命令触发器
|
||||||
- @on_message: 消息触发器(关键词/正则)
|
- @on_message: 消息触发器(关键词/正则)
|
||||||
- @on_event: 事件触发器
|
- @on_event: 事件触发器
|
||||||
- @on_schedule: 定时任务触发器
|
- @on_schedule: 定时任务触发器
|
||||||
- @require_admin: 权限标记
|
- @conversation_command: 带会话生命周期的命令触发器
|
||||||
|
|
||||||
|
权限与过滤装饰器:
|
||||||
|
- @require_admin / @admin_only: 管理员权限标记
|
||||||
|
- @platforms: 限定平台
|
||||||
|
- @group_only / @private_only: 群聊/私聊限定
|
||||||
|
- @message_types: 消息类型过滤
|
||||||
|
|
||||||
|
限流装饰器:
|
||||||
|
- @rate_limit: 滑动窗口限流
|
||||||
|
- @cooldown: 冷却时间
|
||||||
|
|
||||||
|
优先级装饰器:
|
||||||
|
- @priority: 设置执行优先级
|
||||||
|
|
||||||
|
能力导出装饰器:
|
||||||
- @provide_capability: 声明对外暴露的能力
|
- @provide_capability: 声明对外暴露的能力
|
||||||
|
- @register_llm_tool: 注册 LLM 工具
|
||||||
|
- @register_agent: 注册 Agent
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
class MyPlugin(Star):
|
class MyPlugin(Star):
|
||||||
@@ -645,8 +662,35 @@ def conversation_command(
|
|||||||
busy_message: str | None = None,
|
busy_message: str | None = None,
|
||||||
grace_period: float = 1.0,
|
grace_period: float = 1.0,
|
||||||
) -> Callable[[HandlerCallable], HandlerCallable]:
|
) -> 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"}:
|
if mode not in {"replace", "reject"}:
|
||||||
raise ValueError("conversation_command mode must be 'replace' or 'reject'")
|
raise ValueError("conversation_command mode must be 'replace' or 'reject'")
|
||||||
|
# bool 是 int 子类,需单独排除
|
||||||
if isinstance(timeout, bool) or int(timeout) <= 0:
|
if isinstance(timeout, bool) or int(timeout) <= 0:
|
||||||
raise ValueError("conversation_command timeout must be a positive integer")
|
raise ValueError("conversation_command timeout must be a positive integer")
|
||||||
if float(grace_period) <= 0:
|
if float(grace_period) <= 0:
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ from ..protocol.descriptors import (
|
|||||||
from ..schedule import ScheduleContext
|
from ..schedule import ScheduleContext
|
||||||
from ..session_waiter import SessionWaiterManager
|
from ..session_waiter import SessionWaiterManager
|
||||||
from ..star import Star
|
from ..star import Star
|
||||||
from .capability_dispatcher import CapabilityDispatcher
|
|
||||||
from ._command_matching import (
|
from ._command_matching import (
|
||||||
build_command_args,
|
build_command_args,
|
||||||
build_regex_args,
|
build_regex_args,
|
||||||
match_command_name,
|
match_command_name,
|
||||||
)
|
)
|
||||||
|
from .capability_dispatcher import CapabilityDispatcher
|
||||||
from .limiter import LimiterEngine
|
from .limiter import LimiterEngine
|
||||||
from .loader import LoadedHandler
|
from .loader import LoadedHandler
|
||||||
|
|
||||||
@@ -456,7 +456,7 @@ class HandlerDispatcher:
|
|||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
assert loaded.conversation is not None
|
assert loaded.conversation is not None
|
||||||
conversation_meta = loaded.conversation
|
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}"
|
key = f"{self._resolve_plugin_id(loaded)}:{event.session_id}"
|
||||||
active = self._conversations.get(key)
|
active = self._conversations.get(key)
|
||||||
if active is not None and not active.task.done():
|
if active is not None and not active.task.done():
|
||||||
|
|||||||
Reference in New Issue
Block a user