From f8db7ef440ebb8ede1fedf5f91276b6c0df0d268 Mon Sep 17 00:00:00 2001 From: whatevertogo Date: Tue, 17 Mar 2026 02:14:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=AB=98=E7=BA=A7?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=92=8C=E8=BE=85=E5=8A=A9=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=8C=E5=A2=9E=E5=BC=BA=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E5=92=8C=E4=BA=8B=E4=BB=B6=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-new/astrbot_sdk/docs/api/context.md | 189 ++++++++++++++++ src-new/astrbot_sdk/docs/api/decorators.md | 194 +++++++++++++++++ .../docs/api/message_components.md | 153 +++++++++++++ src-new/astrbot_sdk/docs/api/message_event.md | 206 ++++++++++++++++++ .../astrbot_sdk/docs/api/message_result.md | 41 ++++ 5 files changed, 783 insertions(+) diff --git a/src-new/astrbot_sdk/docs/api/context.md b/src-new/astrbot_sdk/docs/api/context.md index e5d98ae85..e76091602 100644 --- a/src-new/astrbot_sdk/docs/api/context.md +++ b/src-new/astrbot_sdk/docs/api/context.md @@ -1087,6 +1087,195 @@ await ctx.unregister_llm_tool("my_tool") --- +## 高级方法 + +### `tool_loop_agent()` + +执行 Agent 工具循环。 + +**签名**: +```python +async def tool_loop_agent( + self, + request: ProviderRequest | None = None, + **kwargs: Any +) -> LLMResponse +``` + +**参数**: +- `request`: ProviderRequest 对象,包含请求配置 +- `**kwargs`: 额外的请求参数,会自动合并到 request + +**返回**: `LLMResponse` - 包含工具调用结果的完整响应 + +**示例**: + +```python +from astrbot_sdk.llm.entities import ProviderRequest + +response = await ctx.tool_loop_agent( + request=ProviderRequest( + prompt="搜索天气", + system_prompt="你是一个助手" + ) +) +print(response.text) +``` + +--- + +### `register_commands()` + +注册命令(仅在 `astrbot_loaded` 或 `platform_loaded` 事件中可用)。 + +**签名**: +```python +async def register_commands( + self, + command_name: str, + handler_full_name: str, + *, + desc: str = "", + priority: int = 0, + use_regex: bool = False, + ignore_prefix: bool = False, +) -> None +``` + +**参数**: +- `command_name`: 命令名称 +- `handler_full_name`: 处理函数的完整名称(如 `module.handler_name`) +- `desc`: 命令描述 +- `priority`: 优先级 +- `use_regex`: 是否使用正则匹配 +- `ignore_prefix`: 是否忽略前缀(SDK 中不支持) + +**异常**: +- `AstrBotError`: 如果在非加载事件中调用或设置 `ignore_prefix=True` + +**示例**: + +```python +@on_event("astrbot_loaded") +async def on_load(self, event, ctx: Context): + await ctx.register_commands( + command_name="my_cmd", + handler_full_name="my_module.handle_cmd", + desc="我的命令", + priority=10 + ) +``` + +--- + +### `get_platform()` + +获取指定类型的平台兼容层实例。 + +**签名**: +```python +async def get_platform(self, platform_type: str) -> PlatformCompatFacade | None +``` + +**参数**: +- `platform_type`: 平台类型(如 "qq", "telegram") + +**返回**: `PlatformCompatFacade | None` - 平台兼容层实例 + +**示例**: + +```python +platform = await ctx.get_platform("qq") +if platform: + await platform.send_by_session("session_id", "消息") +``` + +--- + +### `get_platform_inst()` + +获取指定 ID 的平台兼容层实例。 + +**签名**: +```python +async def get_platform_inst(self, platform_id: str) -> PlatformCompatFacade | None +``` + +**参数**: +- `platform_id`: 平台实例 ID + +**返回**: `PlatformCompatFacade | None` - 平台兼容层实例 + +--- + +## PlatformCompatFacade + +平台兼容层类,提供安全的平台元信息和主动发送能力。 + +### 属性 + +| 属性 | 类型 | 说明 | +|------|------|------| +| `id` | `str` | 平台实例 ID | +| `name` | `str` | 平台名称 | +| `type` | `str` | 平台类型 | +| `status` | `PlatformStatus` | 平台状态 | +| `errors` | `list[PlatformError]` | 错误列表 | +| `last_error` | `PlatformError \| None` | 最近错误 | +| `unified_webhook` | `bool` | 是否统一 webhook | + +### 方法 + +#### `send()` + +发送消息。 + +```python +await platform.send("session_id", "消息内容") +``` + +#### `send_by_session()` + +通过会话发送消息。 + +```python +await platform.send_by_session("platform:private:123", "消息") +``` + +#### `send_by_id()` + +通过 ID 发送消息。 + +```python +await platform.send_by_id("user123", "消息", message_type="private") +``` + +#### `refresh()` + +刷新平台状态。 + +```python +await platform.refresh() +``` + +#### `clear_errors()` + +清除平台错误。 + +```python +await platform.clear_errors() +``` + +#### `get_stats()` + +获取平台统计信息。 + +```python +stats = await platform.get_stats() +``` + +--- + ## 使用示例 ### 1. 基本对话流程 diff --git a/src-new/astrbot_sdk/docs/api/decorators.md b/src-new/astrbot_sdk/docs/api/decorators.md index 336b237d9..f8462b14e 100644 --- a/src-new/astrbot_sdk/docs/api/decorators.md +++ b/src-new/astrbot_sdk/docs/api/decorators.md @@ -725,6 +725,200 @@ class MyPlugin(Star): --- +## 其他装饰器 + +### @admin_only + +`@require_admin` 的别名,功能完全相同。 + +**签名**: +```python +def admin_only(func: HandlerCallable) -> HandlerCallable +``` + +--- + +### @priority + +设置 handler 执行优先级。 + +**签名**: +```python +def priority(value: int) -> Callable[[HandlerCallable], HandlerCallable] +``` + +**参数**: +- `value`: 优先级数值,越大越先执行 + +**示例**: + +```python +@on_command("high") +@priority(100) +async def high_priority(self, event: MessageEvent): + await event.reply("我优先执行") + +@on_command("low") +@priority(1) +async def low_priority(self, event: MessageEvent): + await event.reply("我后执行") +``` + +--- + +### @conversation_command + +会话命令装饰器,支持会话超时和模式控制。 + +**签名**: +```python +def conversation_command( + command: str | Sequence[str], + *, + aliases: list[str] | None = None, + description: str | None = None, + timeout: int = 60, + mode: ConversationMode = "replace", + busy_message: str | None = None, + grace_period: float = 1.0, +) -> Callable[[HandlerCallable], HandlerCallable] +``` + +**参数**: +- `command`: 命令名称 +- `aliases`: 命令别名列表 +- `description`: 命令描述 +- `timeout`: 会话超时时间(秒) +- `mode`: 会话模式(`"replace"` 或 `"reject"`) +- `busy_message`: 会话忙时的提示消息 +- `grace_period`: 宽限期(秒) + +**示例**: + +```python +@conversation_command( + "survey", + description="问卷调查", + timeout=300, + mode="replace", + busy_message="当前有进行中的问卷" +) +async def survey(self, event: MessageEvent, ctx: Context): + await event.reply("请输入您的姓名:") +``` + +--- + +## 元数据辅助函数 + +### `get_handler_meta(func)` + +获取方法的 handler 元数据。 + +**签名**: +```python +def get_handler_meta(func: HandlerCallable) -> HandlerMeta | None +``` + +**参数**: +- `func`: 要检查的方法 + +**返回**: `HandlerMeta | None` - 元数据对象,如果没有则返回 None + +**示例**: + +```python +from astrbot_sdk.decorators import get_handler_meta + +@on_command("test") +async def test_handler(self, event: MessageEvent): + pass + +meta = get_handler_meta(test_handler) +if meta: + print(f"命令: {meta.trigger.command}") +``` + +--- + +### `get_capability_meta(func)` + +获取方法的 capability 元数据。 + +**签名**: +```python +def get_capability_meta(func: HandlerCallable) -> CapabilityMeta | None +``` + +**参数**: +- `func`: 要检查的方法 + +**返回**: `CapabilityMeta | None` - 元数据对象 + +--- + +### `get_llm_tool_meta(func)` + +获取方法的 LLM 工具元数据。 + +**签名**: +```python +def get_llm_tool_meta(func: HandlerCallable) -> LLMToolMeta | None +``` + +**参数**: +- `func`: 要检查的方法 + +**返回**: `LLMToolMeta | None` - 元数据对象 + +--- + +### `get_agent_meta(obj)` + +获取 Agent 类的元数据。 + +**签名**: +```python +def get_agent_meta(obj: Any) -> AgentMeta | None +``` + +**参数**: +- `obj`: 要检查的类或对象 + +**返回**: `AgentMeta | None` - 元数据对象 + +--- + +### `append_filter_meta(func, *, specs, local_bindings)` + +追加过滤器元数据到方法。 + +**签名**: +```python +def append_filter_meta( + func: HandlerCallable, + *, + specs: list[FilterSpec] | None = None, + local_bindings: list[Any] | None = None +) -> HandlerCallable +``` + +--- + +### `set_command_route_meta(func, route)` + +设置命令路由元数据。 + +**签名**: +```python +def set_command_route_meta( + func: HandlerCallable, + route: CommandRouteSpec +) -> HandlerCallable +``` + +--- + ## 使用示例 ### 示例 1: 基础命令 diff --git a/src-new/astrbot_sdk/docs/api/message_components.md b/src-new/astrbot_sdk/docs/api/message_components.md index 6872a0ac5..3068e6989 100644 --- a/src-new/astrbot_sdk/docs/api/message_components.md +++ b/src-new/astrbot_sdk/docs/api/message_components.md @@ -580,6 +580,43 @@ forward = Forward(id="forward_msg_123") --- +## UnknownComponent - 未知组件 + +用于表示无法识别的组件类型。 + +### 类定义 + +```python +class UnknownComponent(BaseMessageComponent): + type = "unknown" + + def __init__( + self, + *, + raw_type: str = "unknown", + raw_data: dict[str, Any] | None = None, + ) -> None: + self.raw_type = raw_type + self.raw_data = raw_data or {} +``` + +### 构造方法 + +```python +from astrbot_sdk import UnknownComponent + +unknown = UnknownComponent( + raw_type="custom_type", + raw_data={"field": "value"} +) +``` + +### 说明 + +当 `payload_to_component()` 遇到无法识别的组件类型时,会返回 `UnknownComponent` 实例,保留原始数据以便调试。 + +--- + ## MessageChain - 消息链 用于组合多个消息组件。 @@ -707,6 +744,122 @@ payload = await component_to_payload(component) --- +### `is_message_component(value)` + +检查值是否为消息组件。 + +```python +from astrbot_sdk.message_components import is_message_component + +if is_message_component(value): + print("是消息组件") +``` + +--- + +### `payloads_to_components(payloads)` + +批量将 payload 列表转换为组件列表。 + +```python +from astrbot_sdk.message_components import payloads_to_components + +components = payloads_to_components(payload_list) +``` + +--- + +### `build_media_component_from_url(url, *, kind)` + +从 URL 构建媒体组件。 + +```python +from astrbot_sdk.message_components import build_media_component_from_url + +# 自动识别类型 +component = build_media_component_from_url("https://example.com/image.jpg") + +# 指定类型 +component = build_media_component_from_url("https://example.com/file", kind="image") +``` + +--- + +## MediaHelper - 媒体辅助类 + +提供媒体处理的静态方法。 + +### `from_url(url, *, kind)` + +从 URL 创建媒体组件。 + +**签名**: +```python +@staticmethod +async def from_url( + url: str, + *, + kind: str = "auto" +) -> BaseMessageComponent +``` + +**参数**: +- `url`: 媒体 URL +- `kind`: 媒体类型(`"auto"`, `"image"`, `"record"`, `"video"`, `"file"`) + +**返回**: 对应的媒体组件 + +**示例**: + +```python +from astrbot_sdk.message_components import MediaHelper + +# 自动识别 +img = await MediaHelper.from_url("https://example.com/photo.jpg") + +# 指定类型 +video = await MediaHelper.from_url("https://example.com/video.mp4", kind="video") +``` + +--- + +### `download(url, save_dir)` + +下载媒体文件到指定目录。 + +**签名**: +```python +@staticmethod +async def download(url: str, save_dir: Path) -> Path +``` + +**参数**: +- `url`: 媒体 URL(仅支持 http/https) +- `save_dir`: 保存目录路径 + +**返回**: `Path` - 下载后的文件路径 + +**异常**: +- `AstrBotError`: 下载失败时抛出 + +**示例**: + +```python +from pathlib import Path +from astrbot_sdk.message_components import MediaHelper + +try: + path = await MediaHelper.download( + "https://example.com/image.jpg", + Path("./downloads") + ) + print(f"下载到: {path}") +except AstrBotError as e: + print(f"下载失败: {e.message}") +``` + +--- + ## 使用示例 ### 处理图片消息 diff --git a/src-new/astrbot_sdk/docs/api/message_event.md b/src-new/astrbot_sdk/docs/api/message_event.md index 917c59d27..4e1c6b33a 100644 --- a/src-new/astrbot_sdk/docs/api/message_event.md +++ b/src-new/astrbot_sdk/docs/api/message_event.md @@ -814,6 +814,212 @@ def make_result(self) -> MessageEventResult --- +## 序列化与反序列化 + +### `from_payload()` + +从协议载荷创建事件实例(类方法)。 + +**签名**: +```python +@classmethod +def from_payload( + cls, + payload: dict[str, Any], + *, + context: Context | None = None, + reply_handler: ReplyHandler | None = None +) -> MessageEvent +``` + +**参数**: +- `payload`: 协议层传递的消息数据字典 +- `context`: 运行时上下文 +- `reply_handler`: 自定义回复处理器 + +**返回**: `MessageEvent` 实例 + +--- + +### `to_payload()` + +转换为协议载荷格式。 + +**签名**: +```python +def to_payload(self) -> dict[str, Any] +``` + +**返回**: 可序列化的字典 + +--- + +## 会话引用属性 + +### `session_ref` + +获取会话引用对象。 + +**类型**: `SessionRef | None` + +**说明**: 包含会话的完整信息,用于跨平台通信。 + +--- + +### `target` + +`session_ref` 的别名。 + +**类型**: `SessionRef | None` + +--- + +### `unified_msg_origin` + +统一消息来源标识符。 + +**类型**: `str` + +**说明**: 等同于 `session_id`。 + +--- + +## LLM 相关方法 + +### `request_llm()` + +请求触发默认 LLM 链处理当前消息。 + +**签名**: +```python +async def request_llm(self) -> bool +``` + +**返回**: `bool` - 是否应该调用 LLM + +**示例**: + +```python +@on_command("ask") +async def ask(self, event: MessageEvent): + should_call = await event.request_llm() + if should_call: + await event.reply("已触发 LLM 处理") +``` + +--- + +### `should_call_llm()` + +读取当前默认 LLM 决策状态。 + +**签名**: +```python +async def should_call_llm(self) -> bool +``` + +**返回**: `bool` - 是否应该调用 LLM + +**示例**: + +```python +@on_message() +async def handle(self, event: MessageEvent): + if await event.should_call_llm(): + response = await ctx.llm.chat(event.text) + await event.reply(response) +``` + +--- + +## 结果管理方法 + +### `set_result()` + +存储请求范围的 SDK 结果到主机桥。 + +**签名**: +```python +async def set_result(self, result: MessageEventResult) -> MessageEventResult +``` + +**参数**: +- `result`: 消息事件结果对象 + +**返回**: 传入的 `result` 对象 + +**示例**: + +```python +result = event.chain_result([Plain("处理结果")]) +await event.set_result(result) +``` + +--- + +### `get_result()` + +从主机桥读取当前请求范围的 SDK 结果。 + +**签名**: +```python +async def get_result(self) -> MessageEventResult | None +``` + +**返回**: `MessageEventResult | None` - 结果对象,不存在则返回 None + +--- + +### `clear_result()` + +清除当前请求范围的 SDK 结果。 + +**签名**: +```python +async def clear_result(self) -> None +``` + +--- + +## 其他方法 + +### `get_message_outline()` + +获取规范化的消息摘要。 + +**签名**: +```python +def get_message_outline(self) -> str +``` + +**返回**: 消息摘要文本 + +--- + +### `bind_reply_handler()` + +绑定自定义回复处理器。 + +**签名**: +```python +def bind_reply_handler(self, reply_handler: ReplyHandler) -> None +``` + +**参数**: +- `reply_handler`: 回复处理函数,接收文本参数 + +**示例**: + +```python +def custom_reply(text: str): + print(f"回复: {text}") + +event.bind_reply_handler(custom_reply) +await event.reply("测试") # 会调用 custom_reply +``` + +--- + ## 完整使用示例 ### 示例 1: 基础消息处理 diff --git a/src-new/astrbot_sdk/docs/api/message_result.md b/src-new/astrbot_sdk/docs/api/message_result.md index d491ec965..fa3c1cb0b 100644 --- a/src-new/astrbot_sdk/docs/api/message_result.md +++ b/src-new/astrbot_sdk/docs/api/message_result.md @@ -652,6 +652,47 @@ async def user_info(self, event: MessageEvent): --- +## 辅助函数 + +### `coerce_message_chain(value)` + +将多种输入格式统一转换为 MessageChain。 + +**签名**: +```python +def coerce_message_chain(value: Any) -> MessageChain | None +``` + +**参数**: +- `value`: 要转换的值,支持以下类型: + - `MessageEventResult`: 提取其中的 chain + - `MessageChain`: 直接返回 + - `BaseMessageComponent`: 包装为单元素链 + - `list[BaseMessageComponent]`: 包装为链 + +**返回**: `MessageChain | None` - 转换后的消息链,无法转换则返回 None + +**示例**: + +```python +from astrbot_sdk.message_result import coerce_message_chain, MessageChain +from astrbot_sdk.message_components import Plain, Image + +# 从 MessageEventResult 提取 +chain = coerce_message_chain(result) + +# 从 MessageChain 返回 +chain = coerce_message_chain(existing_chain) + +# 从单个组件创建 +chain = coerce_message_chain(Plain("文本")) + +# 从组件列表创建 +chain = coerce_message_chain([Plain("文本"), Image.fromURL("url")]) +``` + +--- + ## 注意事项 1. **MessageChain 可变性**: