Refactor protocol and transport modules to use type hints for improved clarity and consistency

- Updated Codec class to use abstract methods for encoding and decoding envelopes.
- Changed Envelope class to use Dict and Optional for payload and error fields.
- Refined error handling in RPCError class with Optional type hints for details.
- Enhanced manifest validation logic with type hints for better type safety.
- Improved plugin loading mechanism with consistent type annotations.
- Updated RPCClient to utilize Optional for codec and connection attributes.
- Refactored transport classes to use Optional for server attributes and socket paths.
This commit is contained in:
DrSmoothl
2026-03-11 00:07:13 +08:00
parent 7f1e79ea28
commit 69219e36f7
19 changed files with 273 additions and 253 deletions

View File

@@ -1,35 +1,40 @@
"""MsgPack 编解码器"""
from typing import Any
from abc import ABC, abstractmethod
from typing import Any, Dict
import msgpack
from .envelope import Envelope
class Codec:
class Codec(ABC):
"""消息编解码器基类"""
@abstractmethod
def encode_envelope(self, envelope: Envelope) -> bytes:
raise NotImplementedError
...
@abstractmethod
def decode_envelope(self, data: bytes) -> Envelope:
raise NotImplementedError
...
def encode(self, obj: dict[str, Any]) -> bytes:
raise NotImplementedError
@abstractmethod
def encode(self, obj: Dict[str, Any]) -> bytes:
...
def decode(self, data: bytes) -> dict[str, Any]:
raise NotImplementedError
@abstractmethod
def decode(self, data: bytes) -> Dict[str, Any]:
...
class MsgPackCodec(Codec):
"""MsgPack 编解码器"""
def encode(self, obj: dict[str, Any]) -> bytes:
def encode(self, obj: Dict[str, Any]) -> bytes:
return msgpack.packb(obj, use_bin_type=True)
def decode(self, data: bytes) -> dict[str, Any]:
def decode(self, data: bytes) -> Dict[str, Any]:
result = msgpack.unpackb(data, raw=False)
if not isinstance(result, dict):
raise ValueError(f"期望解码为 dict实际为 {type(result)}")

View File

@@ -5,9 +5,8 @@
"""
from enum import Enum
from typing import Any
from pydantic import BaseModel, Field
from typing import Any, Dict, List, Optional
import time
@@ -62,8 +61,8 @@ class Envelope(BaseModel):
timestamp_ms: int = Field(default_factory=lambda: int(time.time() * 1000), description="发送时间戳(ms)")
timeout_ms: int = Field(default=30000, description="相对超时(ms)")
generation: int = Field(default=0, description="Runner generation 编号")
payload: dict[str, Any] = Field(default_factory=dict, description="业务数据")
error: dict[str, Any] | None = Field(default=None, description="错误信息(仅 response)")
payload: Dict[str, Any] = Field(default_factory=dict, description="业务数据")
error: Optional[Dict[str, Any]] = Field(default=None, description="错误信息(仅 response)")
def is_request(self) -> bool:
return self.message_type == MessageType.REQUEST
@@ -74,7 +73,7 @@ class Envelope(BaseModel):
def is_event(self) -> bool:
return self.message_type == MessageType.EVENT
def make_response(self, payload: dict[str, Any] | None = None, error: dict[str, Any] | None = None) -> "Envelope":
def make_response(self, payload: Optional[Dict[str, Any]] = None, error: Optional[Dict[str, Any]] = None) -> "Envelope":
"""基于当前请求创建对应的响应信封"""
return Envelope(
protocol_version=self.protocol_version,
@@ -87,7 +86,7 @@ class Envelope(BaseModel):
error=error,
)
def make_error_response(self, code: str, message: str = "", details: dict | None = None) -> "Envelope":
def make_error_response(self, code: str, message: str = "", details: Optional[Dict[str, Any]] = None) -> "Envelope":
"""基于当前请求创建错误响应"""
return self.make_response(
error={
@@ -122,15 +121,15 @@ class ComponentDeclaration(BaseModel):
name: str = Field(description="组件名称")
component_type: str = Field(description="组件类型: action/command/tool/event_handler")
plugin_id: str = Field(description="所属插件 ID")
metadata: dict[str, Any] = Field(default_factory=dict, description="组件元数据")
metadata: Dict[str, Any] = Field(default_factory=dict, description="组件元数据")
class RegisterComponentsPayload(BaseModel):
"""plugin.register_components 请求 payload"""
plugin_id: str = Field(description="插件 ID")
plugin_version: str = Field(default="1.0.0", description="插件版本")
components: list[ComponentDeclaration] = Field(default_factory=list, description="组件列表")
capabilities_required: list[str] = Field(default_factory=list, description="所需能力列表")
components: List[ComponentDeclaration] = Field(default_factory=list, description="组件列表")
capabilities_required: List[str] = Field(default_factory=list, description="所需能力列表")
# ─── 调用消息 ──────────────────────────────────────────────────────
@@ -138,7 +137,7 @@ class RegisterComponentsPayload(BaseModel):
class InvokePayload(BaseModel):
"""plugin.invoke_* 请求 payload"""
component_name: str = Field(description="要调用的组件名称")
args: dict[str, Any] = Field(default_factory=dict, description="调用参数")
args: Dict[str, Any] = Field(default_factory=dict, description="调用参数")
class InvokeResultPayload(BaseModel):
@@ -152,7 +151,7 @@ class InvokeResultPayload(BaseModel):
class CapabilityRequestPayload(BaseModel):
"""cap.* 请求 payload插件 -> Host 能力调用)"""
capability: str = Field(description="能力名称,如 send.text, db.query")
args: dict[str, Any] = Field(default_factory=dict, description="调用参数")
args: Dict[str, Any] = Field(default_factory=dict, description="调用参数")
class CapabilityResponsePayload(BaseModel):
@@ -166,7 +165,7 @@ class CapabilityResponsePayload(BaseModel):
class HealthPayload(BaseModel):
"""plugin.health 响应 payload"""
healthy: bool = Field(description="是否健康")
loaded_plugins: list[str] = Field(default_factory=list, description="已加载的插件列表")
loaded_plugins: List[str] = Field(default_factory=list, description="已加载的插件列表")
uptime_ms: int = Field(default=0, description="运行时长(ms)")
@@ -176,7 +175,7 @@ class ConfigUpdatedPayload(BaseModel):
"""plugin.config_updated 事件 payload"""
plugin_id: str = Field(description="插件 ID")
config_version: str = Field(description="新配置版本")
config_data: dict[str, Any] = Field(default_factory=dict, description="配置内容")
config_data: Dict[str, Any] = Field(default_factory=dict, description="配置内容")
# ─── 关停 ──────────────────────────────────────────────────────────

View File

@@ -4,6 +4,7 @@
"""
from enum import Enum
from typing import Any, Dict, Optional
class ErrorCode(str, Enum):
@@ -38,13 +39,13 @@ class ErrorCode(str, Enum):
class RPCError(Exception):
"""RPC 调用异常"""
def __init__(self, code: ErrorCode, message: str = "", details: dict | None = None):
def __init__(self, code: ErrorCode, message: str = "", details: Optional[Dict[str, Any]] = None):
self.code = code
self.message = message or code.value
self.details = details or {}
super().__init__(f"[{code.value}] {self.message}")
def to_dict(self) -> dict:
def to_dict(self) -> Dict[str, Any]:
return {
"code": self.code.value,
"message": self.message,
@@ -52,7 +53,7 @@ class RPCError(Exception):
}
@classmethod
def from_dict(cls, data: dict) -> "RPCError":
def from_dict(cls, data: Dict[str, Any]) -> "RPCError":
code = ErrorCode(data.get("code", "E_UNKNOWN"))
return cls(
code=code,