feat(protocol): 优化协议模块导出,确保根目录专注于原生 v4 模型,遗留适配器从子模块显式导入

This commit is contained in:
whatevertogo
2026-03-13 06:34:57 +08:00
parent a93f267d8a
commit 3d5c8f7ff7
4 changed files with 20 additions and 55 deletions

View File

@@ -14,6 +14,7 @@
- 2026-03-13: Keep `astrbot_sdk.runtime` root exports narrow. `Peer` / `Transport` / `CapabilityRouter` / `HandlerDispatcher` are reasonable advanced runtime primitives, but loader/bootstrap data structures and orchestration helpers (`LoadedPlugin`, `PluginEnvironmentManager`, `WorkerSession`, `run_supervisor`, etc.) should stay in their submodules instead of becoming accidental root-level stable API.
- 2026-03-13: `runtime.loader` must preserve declared legacy handler order. Falling back to `dir(instance)` or sorting the merged discoverable names reorders compat handlers alphabetically, which changes which legacy command/hook appears first to the supervisor and breaks old-plugin expectations.
- 2026-03-13: `runtime.loader.import_string()` cannot trust `sys.modules` when plugins reuse generic top-level package names like `commands.*`. Before importing a plugin module, compare the cached root package against the current plugin directory and evict conflicting root/submodules, or later plugins will accidentally reuse an earlier plugin's package tree.
- 2026-03-13: Keep `astrbot_sdk.protocol` root focused on native v4 protocol models and parsers. Legacy JSON-RPC helpers remain supported, but they should be imported from `astrbot_sdk.protocol.legacy_adapter` explicitly instead of being re-exported from the package root.
# 开发命令

View File

@@ -14,6 +14,7 @@
- 2026-03-13: Keep `astrbot_sdk.runtime` root exports narrow. `Peer` / `Transport` / `CapabilityRouter` / `HandlerDispatcher` are reasonable advanced runtime primitives, but loader/bootstrap data structures and orchestration helpers (`LoadedPlugin`, `PluginEnvironmentManager`, `WorkerSession`, `run_supervisor`, etc.) should stay in their submodules instead of becoming accidental root-level stable API.
- 2026-03-13: `runtime.loader` must preserve declared legacy handler order. Falling back to `dir(instance)` or sorting the merged discoverable names reorders compat handlers alphabetically, which changes which legacy command/hook appears first to the supervisor and breaks old-plugin expectations.
- 2026-03-13: `runtime.loader.import_string()` cannot trust `sys.modules` when plugins reuse generic top-level package names like `commands.*`. Before importing a plugin module, compare the cached root package against the current plugin directory and evict conflicting root/submodules, or later plugins will accidentally reuse an earlier plugin's package tree.
- 2026-03-13: Keep `astrbot_sdk.protocol` root focused on native v4 protocol models and parsers. Legacy JSON-RPC helpers remain supported, but they should be imported from `astrbot_sdk.protocol.legacy_adapter` explicitly instead of being re-exported from the package root.
# 开发命令

View File

@@ -1,11 +1,8 @@
"""AstrBot v4 协议公共入口。
这里暴露的是协议层的公共模型和 legacy 适配入口。需要区分两件事:
1. v4 原生协议:
`InitializeMessage` / `InvokeMessage` / `ResultMessage` / `EventMessage`
2. legacy JSON-RPC 兼容:
`LegacyAdapter` 及其若干便捷转换函数
这里优先暴露 v4 原生协议的消息模型、描述符和解析函数。
legacy JSON-RPC 兼容保留在 `astrbot_sdk.protocol.legacy_adapter` 子模块中,
供迁移和适配场景显式使用,而不是作为主协议根入口的一部分。
握手阶段由 `InitializeMessage` 发起,返回值不是另一条 initialize 消息,而是
`ResultMessage(kind="initialize_result")`,其 `output` 负载可解析为
@@ -23,29 +20,6 @@ from .descriptors import (
SessionRef,
Trigger,
)
from .legacy_adapter import (
LEGACY_ADAPTER_MESSAGE_EVENT,
LEGACY_CONTEXT_CAPABILITY,
LEGACY_HANDSHAKE_METADATA_KEY,
LEGACY_JSONRPC_VERSION,
LEGACY_PLUGIN_KEYS_METADATA_KEY,
LegacyAdapter,
LegacyErrorData,
LegacyErrorResponse,
LegacyMessage,
LegacyRequest,
LegacySuccessResponse,
LegacyToV4Message,
cancel_to_legacy_request,
event_to_legacy_notification,
initialize_to_legacy_handshake_response,
invoke_to_legacy_request,
legacy_message_to_v4,
legacy_request_to_invoke,
legacy_response_to_message,
parse_legacy_message,
result_to_legacy_response,
)
from .messages import (
CancelMessage,
ErrorPayload,
@@ -70,18 +44,6 @@ __all__ = [
"InitializeMessage",
"InitializeOutput",
"InvokeMessage",
"LEGACY_ADAPTER_MESSAGE_EVENT",
"LEGACY_CONTEXT_CAPABILITY",
"LEGACY_HANDSHAKE_METADATA_KEY",
"LEGACY_JSONRPC_VERSION",
"LEGACY_PLUGIN_KEYS_METADATA_KEY",
"LegacyAdapter",
"LegacyErrorData",
"LegacyErrorResponse",
"LegacyMessage",
"LegacyRequest",
"LegacySuccessResponse",
"LegacyToV4Message",
"MessageTrigger",
"PeerInfo",
"Permissions",
@@ -90,14 +52,5 @@ __all__ = [
"ScheduleTrigger",
"SessionRef",
"Trigger",
"cancel_to_legacy_request",
"event_to_legacy_notification",
"initialize_to_legacy_handshake_response",
"invoke_to_legacy_request",
"legacy_message_to_v4",
"legacy_request_to_invoke",
"legacy_response_to_message",
"parse_legacy_message",
"parse_message",
"result_to_legacy_response",
]

View File

@@ -2,6 +2,8 @@
from __future__ import annotations
import astrbot_sdk.protocol as protocol_module
from astrbot_sdk.protocol import (
CapabilityDescriptor,
CommandTrigger,
@@ -9,17 +11,19 @@ from astrbot_sdk.protocol import (
EventMessage,
HandlerDescriptor,
InitializeMessage,
LegacyAdapter,
LegacyRequest,
MessageTrigger,
PeerInfo,
ProtocolMessage,
ResultMessage,
ScheduleTrigger,
parse_legacy_message,
parse_message,
)
from astrbot_sdk.protocol.descriptors import BUILTIN_CAPABILITY_SCHEMAS
from astrbot_sdk.protocol.legacy_adapter import (
LegacyAdapter,
LegacyRequest,
parse_legacy_message,
)
class TestProtocolPackageExports:
@@ -55,8 +59,14 @@ class TestProtocolPackageExports:
assert isinstance(EventMessage(id="evt-1", phase="started"), EventMessage)
assert isinstance(ResultMessage(id="res-1", success=True), ResultMessage)
def test_legacy_exports_are_importable(self):
"""Legacy adapter helpers should also be available from package root."""
def test_protocol_root_does_not_reexport_legacy_helpers(self):
"""protocol root should stay focused on native v4 models."""
assert not hasattr(protocol_module, "LegacyAdapter")
assert not hasattr(protocol_module, "LegacyRequest")
assert not hasattr(protocol_module, "parse_legacy_message")
def test_legacy_exports_are_available_from_submodule(self):
"""Legacy adapter helpers remain available from the explicit submodule."""
legacy = parse_legacy_message({"jsonrpc": "2.0", "method": "handshake"})
assert isinstance(legacy, LegacyRequest)