mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-16 01:40:15 +08:00
254 lines
8.6 KiB
Python
254 lines
8.6 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from astrbot_sdk.protocol.descriptors import CommandTrigger, HandlerDescriptor
|
|
from astrbot_sdk.protocol.legacy_adapter import (
|
|
LEGACY_CONTEXT_CAPABILITY,
|
|
LEGACY_HANDSHAKE_METADATA_KEY,
|
|
LegacyAdapter,
|
|
)
|
|
from astrbot_sdk.protocol.messages import (
|
|
EventMessage,
|
|
InitializeMessage,
|
|
PeerInfo,
|
|
ResultMessage,
|
|
)
|
|
|
|
|
|
class LegacyAdapterTest(unittest.TestCase):
|
|
def test_call_handler_roundtrip_preserves_handler_name_in_stream_notifications(
|
|
self,
|
|
) -> None:
|
|
adapter = LegacyAdapter()
|
|
|
|
invoke = adapter.legacy_to_v4(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"id": "call-1",
|
|
"method": "call_handler",
|
|
"params": {
|
|
"handler_full_name": "commands.demo:MyPlugin.handle",
|
|
"event": {"text": "/hello"},
|
|
"args": {},
|
|
},
|
|
}
|
|
)
|
|
|
|
self.assertEqual(invoke.capability, "handler.invoke")
|
|
self.assertEqual(invoke.input["handler_id"], "commands.demo:MyPlugin.handle")
|
|
|
|
started = adapter.event_to_legacy_notification(
|
|
EventMessage(id="call-1", phase="started")
|
|
)
|
|
delta = adapter.event_to_legacy_notification(
|
|
EventMessage(id="call-1", phase="delta", data={"text": "hi"})
|
|
)
|
|
completed = adapter.event_to_legacy_notification(
|
|
EventMessage(id="call-1", phase="completed", output={"text": "hi"})
|
|
)
|
|
response = adapter.result_to_legacy_response(
|
|
ResultMessage(id="call-1", success=True, output={"handled_by": "demo"})
|
|
)
|
|
|
|
self.assertEqual(started["method"], "handler_stream_start")
|
|
self.assertEqual(
|
|
delta["params"]["handler_full_name"], "commands.demo:MyPlugin.handle"
|
|
)
|
|
self.assertEqual(delta["params"]["data"], {"text": "hi"})
|
|
self.assertEqual(completed["method"], "handler_stream_end")
|
|
self.assertEqual(response["result"], {"handled_by": "demo"})
|
|
|
|
def test_call_context_function_maps_to_internal_capability(self) -> None:
|
|
adapter = LegacyAdapter()
|
|
message = adapter.legacy_to_v4(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"id": "ctx-1",
|
|
"method": "call_context_function",
|
|
"params": {
|
|
"name": "ConversationManager.new_conversation",
|
|
"args": {"unified_msg_origin": "session-1"},
|
|
},
|
|
}
|
|
)
|
|
|
|
self.assertEqual(message.capability, LEGACY_CONTEXT_CAPABILITY)
|
|
self.assertEqual(message.input["name"], "ConversationManager.new_conversation")
|
|
self.assertEqual(
|
|
message.input["args"],
|
|
{"unified_msg_origin": "session-1"},
|
|
)
|
|
|
|
legacy_request = adapter.invoke_to_legacy_request(message)
|
|
self.assertEqual(legacy_request["method"], "call_context_function")
|
|
self.assertEqual(
|
|
legacy_request["params"]["name"],
|
|
"ConversationManager.new_conversation",
|
|
)
|
|
|
|
def test_legacy_handler_stream_notifications_map_back_to_v4_events(self) -> None:
|
|
adapter = LegacyAdapter()
|
|
|
|
started = adapter.legacy_to_v4(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"method": "handler_stream_start",
|
|
"params": {
|
|
"id": "call-2",
|
|
"handler_full_name": "commands.demo:MyPlugin.handle",
|
|
},
|
|
}
|
|
)
|
|
delta = adapter.legacy_to_v4(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"method": "handler_stream_update",
|
|
"params": {
|
|
"id": "call-2",
|
|
"handler_full_name": "commands.demo:MyPlugin.handle",
|
|
"data": {"text": "partial"},
|
|
},
|
|
}
|
|
)
|
|
failed = adapter.legacy_to_v4(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"method": "handler_stream_end",
|
|
"params": {
|
|
"id": "call-2",
|
|
"handler_full_name": "commands.demo:MyPlugin.handle",
|
|
"error": {
|
|
"code": "cancelled",
|
|
"message": "调用被取消",
|
|
"hint": "",
|
|
"retryable": False,
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
self.assertEqual(started.phase, "started")
|
|
self.assertEqual(delta.phase, "delta")
|
|
self.assertEqual(delta.data, {"text": "partial"})
|
|
self.assertEqual(failed.phase, "failed")
|
|
self.assertEqual(failed.error.code, "cancelled")
|
|
|
|
def test_handshake_payload_maps_to_initialize_and_roundtrips(self) -> None:
|
|
adapter = LegacyAdapter(legacy_peer_name="legacy-plugin")
|
|
legacy_payload = {
|
|
"plugin_one.main": {
|
|
"name": "plugin_one",
|
|
"author": "tester",
|
|
"desc": "legacy",
|
|
"version": "0.1.0",
|
|
"repo": None,
|
|
"module_path": "plugin_one.main",
|
|
"root_dir_name": "plugin_one",
|
|
"reserved": False,
|
|
"activated": True,
|
|
"config": None,
|
|
"star_handler_full_names": [
|
|
"commands.plugin_one:SampleCommand.handle_plugin_one"
|
|
],
|
|
"display_name": "plugin_one",
|
|
"logo_path": None,
|
|
"handlers": [
|
|
{
|
|
"event_type": 3,
|
|
"handler_full_name": "commands.plugin_one:SampleCommand.handle_plugin_one",
|
|
"handler_name": "handle_plugin_one",
|
|
"handler_module_path": "commands.plugin_one:SampleCommand",
|
|
"desc": "",
|
|
"extras_configs": {"priority": 7},
|
|
}
|
|
],
|
|
}
|
|
}
|
|
|
|
initialize = adapter.legacy_to_v4(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"id": "handshake-1",
|
|
"result": legacy_payload,
|
|
}
|
|
)
|
|
|
|
self.assertIsInstance(initialize, InitializeMessage)
|
|
self.assertEqual(initialize.peer.name, "plugin_one")
|
|
self.assertEqual(
|
|
initialize.handlers[0].id,
|
|
"commands.plugin_one:SampleCommand.handle_plugin_one",
|
|
)
|
|
self.assertEqual(initialize.handlers[0].priority, 7)
|
|
self.assertEqual(
|
|
initialize.metadata[LEGACY_HANDSHAKE_METADATA_KEY],
|
|
legacy_payload,
|
|
)
|
|
|
|
roundtrip = adapter.initialize_to_legacy_handshake_response(
|
|
initialize,
|
|
request_id="handshake-1",
|
|
)
|
|
self.assertEqual(roundtrip["result"], legacy_payload)
|
|
|
|
def test_handshake_error_becomes_initialize_failure(self) -> None:
|
|
adapter = LegacyAdapter()
|
|
adapter.legacy_to_v4(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"id": "handshake-2",
|
|
"method": "handshake",
|
|
"params": {},
|
|
}
|
|
)
|
|
|
|
result = adapter.legacy_to_v4(
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"id": "handshake-2",
|
|
"error": {
|
|
"code": -32000,
|
|
"message": "boom",
|
|
},
|
|
}
|
|
)
|
|
|
|
self.assertIsInstance(result, ResultMessage)
|
|
self.assertEqual(result.kind, "initialize_result")
|
|
self.assertFalse(result.success)
|
|
self.assertEqual(result.error.code, "legacy_rpc_error")
|
|
|
|
def test_initialize_can_synthesize_legacy_handshake_payload(self) -> None:
|
|
adapter = LegacyAdapter()
|
|
initialize = InitializeMessage(
|
|
id="msg_001",
|
|
protocol_version="1.0",
|
|
peer=PeerInfo(name="v4-plugin", role="plugin", version="1.2.0"),
|
|
handlers=[
|
|
HandlerDescriptor(
|
|
id="commands.sample:MyPlugin.hello",
|
|
trigger=CommandTrigger(command="hello", description="hello"),
|
|
priority=3,
|
|
)
|
|
],
|
|
metadata={"plugin_id": "v4-plugin"},
|
|
)
|
|
|
|
payload = adapter.initialize_to_legacy_handshake_response(
|
|
initialize,
|
|
request_id="handshake-3",
|
|
)
|
|
star_payload = payload["result"]["v4-plugin.main"]
|
|
|
|
self.assertEqual(star_payload["name"], "v4-plugin")
|
|
self.assertEqual(
|
|
star_payload["handlers"][0]["handler_full_name"],
|
|
"commands.sample:MyPlugin.hello",
|
|
)
|
|
self.assertEqual(star_payload["handlers"][0]["extras_configs"]["priority"], 3)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|