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:
@@ -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)}")
|
||||
|
||||
@@ -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="配置内容")
|
||||
|
||||
|
||||
# ─── 关停 ──────────────────────────────────────────────────────────
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user