feat: Enhance plugin configuration management and SDK integration
- Add support for configuration reload scopes in the plugin runtime. - Implement validation for SDK plugins to ensure required lifecycle methods are overridden. - Update the configuration update handling to include scope information. - Introduce tests for expression auto-check task and NapCat adapter SDK integration. - Refactor configuration management to support callbacks with variable arguments. - Improve plugin loading and error handling for configuration updates. - Ensure that plugins can manage their own configuration updates effectively.
This commit is contained in:
132
pytests/test_napcat_adapter_sdk.py
Normal file
132
pytests/test_napcat_adapter_sdk.py
Normal file
@@ -0,0 +1,132 @@
|
||||
"""NapCat 插件与新 SDK 对接测试。"""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List
|
||||
|
||||
import importlib
|
||||
import logging
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
PLUGINS_ROOT = PROJECT_ROOT / "plugins"
|
||||
SDK_ROOT = PROJECT_ROOT / "packages" / "maibot-plugin-sdk"
|
||||
|
||||
for import_path in (str(PLUGINS_ROOT), str(SDK_ROOT)):
|
||||
if import_path not in sys.path:
|
||||
sys.path.insert(0, import_path)
|
||||
|
||||
|
||||
class _FakeGatewayCapability:
|
||||
"""用于捕获消息网关状态上报的测试替身。"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""初始化测试替身。"""
|
||||
|
||||
self.calls: List[Dict[str, Any]] = []
|
||||
|
||||
async def update_state(
|
||||
self,
|
||||
gateway_name: str,
|
||||
*,
|
||||
ready: bool,
|
||||
platform: str = "",
|
||||
account_id: str = "",
|
||||
scope: str = "",
|
||||
metadata: Dict[str, Any] | None = None,
|
||||
) -> bool:
|
||||
"""记录一次状态上报请求。
|
||||
|
||||
Args:
|
||||
gateway_name: 网关组件名称。
|
||||
ready: 当前是否就绪。
|
||||
platform: 平台名称。
|
||||
account_id: 账号 ID。
|
||||
scope: 路由作用域。
|
||||
metadata: 附加元数据。
|
||||
|
||||
Returns:
|
||||
bool: 始终返回 ``True``,模拟 Host 接受状态更新。
|
||||
"""
|
||||
|
||||
self.calls.append(
|
||||
{
|
||||
"gateway_name": gateway_name,
|
||||
"ready": ready,
|
||||
"platform": platform,
|
||||
"account_id": account_id,
|
||||
"scope": scope,
|
||||
"metadata": metadata or {},
|
||||
}
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def _load_napcat_sdk_symbols() -> tuple[Any, Any, Any, Any]:
|
||||
"""动态加载 NapCat 插件测试所需的符号。
|
||||
|
||||
Returns:
|
||||
tuple[Any, Any, Any, Any]:
|
||||
依次返回网关名常量、配置类、插件类和运行时状态管理器类。
|
||||
"""
|
||||
|
||||
constants_module = importlib.import_module("napcat_adapter.constants")
|
||||
config_module = importlib.import_module("napcat_adapter.config")
|
||||
plugin_module = importlib.import_module("napcat_adapter.plugin")
|
||||
runtime_state_module = importlib.import_module("napcat_adapter.runtime_state")
|
||||
return (
|
||||
constants_module.NAPCAT_GATEWAY_NAME,
|
||||
config_module.NapCatServerConfig,
|
||||
plugin_module.NapCatAdapterPlugin,
|
||||
runtime_state_module.NapCatRuntimeStateManager,
|
||||
)
|
||||
|
||||
|
||||
def test_napcat_plugin_collects_duplex_message_gateway() -> None:
|
||||
"""NapCat 插件应声明新的双工消息网关组件。"""
|
||||
|
||||
napcat_gateway_name, _napcat_server_config, napcat_plugin_cls, _runtime_state_cls = _load_napcat_sdk_symbols()
|
||||
plugin = napcat_plugin_cls()
|
||||
components = plugin.get_components()
|
||||
gateway_components = [
|
||||
component
|
||||
for component in components
|
||||
if component.get("type") == "MESSAGE_GATEWAY"
|
||||
]
|
||||
|
||||
assert len(gateway_components) == 1
|
||||
gateway_component = gateway_components[0]
|
||||
assert gateway_component["name"] == napcat_gateway_name
|
||||
assert gateway_component["metadata"]["route_type"] == "duplex"
|
||||
assert gateway_component["metadata"]["platform"] == "qq"
|
||||
assert gateway_component["metadata"]["protocol"] == "napcat"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_runtime_state_reports_via_gateway_capability() -> None:
|
||||
"""NapCat 运行时状态应通过新的消息网关能力上报。"""
|
||||
|
||||
napcat_gateway_name, napcat_server_config_cls, _napcat_plugin_cls, runtime_state_cls = _load_napcat_sdk_symbols()
|
||||
gateway_capability = _FakeGatewayCapability()
|
||||
runtime_state_manager = runtime_state_cls(
|
||||
gateway_capability=gateway_capability,
|
||||
logger=logging.getLogger("test.napcat_adapter"),
|
||||
gateway_name=napcat_gateway_name,
|
||||
)
|
||||
|
||||
connected = await runtime_state_manager.report_connected(
|
||||
"10001",
|
||||
napcat_server_config_cls(connection_id="primary"),
|
||||
)
|
||||
await runtime_state_manager.report_disconnected()
|
||||
|
||||
assert connected is True
|
||||
assert gateway_capability.calls[0]["gateway_name"] == napcat_gateway_name
|
||||
assert gateway_capability.calls[0]["ready"] is True
|
||||
assert gateway_capability.calls[0]["platform"] == "qq"
|
||||
assert gateway_capability.calls[0]["account_id"] == "10001"
|
||||
assert gateway_capability.calls[0]["scope"] == "primary"
|
||||
assert gateway_capability.calls[1]["gateway_name"] == napcat_gateway_name
|
||||
assert gateway_capability.calls[1]["ready"] is False
|
||||
assert gateway_capability.calls[1]["platform"] == "qq"
|
||||
Reference in New Issue
Block a user