ForcePilot/backend/package/yuxi/channel/gateway/validation.py

111 lines
3.2 KiB
Python
Raw Normal View History

from functools import wraps
from typing import Any
from pydantic import BaseModel, ConfigDict, Field, ValidationError
from yuxi.channel.gateway.protocol import GatewayErrorCode, RpcRequest, RpcResponse
class ErrorShape(BaseModel):
code: str
message: str = ""
data: Any | None = None
retryable: bool = False
retryAfterMs: int | None = None
class RequestFrameSchema(BaseModel):
type: str = "request"
id: str
method: str
params: dict | None = None
sessionId: str | None = None
class ResponseFrameSchema(BaseModel):
type: str = "response"
id: str
ok: bool = True
result: dict | None = None
error: ErrorShape | None = None
class EventFrameSchema(BaseModel):
type: str = "event"
event: str
data: dict | None = None
timestamp: float = 0.0
seq: int | None = None
stateVersion: int | None = None
class StartAccountParams(BaseModel):
model_config = ConfigDict(extra="allow")
channel_type: str = Field(..., min_length=1, max_length=50)
account_id: str = Field(default="default", min_length=1, max_length=100)
config: dict = Field(default_factory=dict)
class StopAccountParams(BaseModel):
model_config = ConfigDict(extra="allow")
channel_type: str = Field(..., min_length=1, max_length=50)
account_id: str = Field(default="default", min_length=1, max_length=100)
force: bool = False
class SendMessageParams(BaseModel):
model_config = ConfigDict(extra="allow")
channel_type: str = Field(..., min_length=1, max_length=50)
account_id: str = Field(default="default", min_length=1, max_length=100)
target_id: str = Field(..., min_length=1, max_length=200)
text: str = Field(..., min_length=1, max_length=4096)
msg_type: str = Field(default="text")
media_url: str | None = None
extra: dict = Field(default_factory=dict)
class ProbeParams(BaseModel):
model_config = ConfigDict(extra="allow")
channel_type: str = Field(..., min_length=1, max_length=50)
account_id: str = Field(default="default", min_length=1, max_length=100)
class DiagnoseParams(BaseModel):
model_config = ConfigDict(extra="allow")
channel_type: str = Field(..., min_length=1, max_length=50)
account_id: str = Field(default="default", min_length=1, max_length=100)
class RepairParams(BaseModel):
model_config = ConfigDict(extra="allow")
channel_type: str = Field(..., min_length=1, max_length=50)
step_id: str = Field(..., min_length=1, max_length=100)
account_id: str = Field(default="default", min_length=1, max_length=100)
def validate_params(schema_cls: type[BaseModel]):
def decorator(func):
@wraps(func)
async def wrapper(request: RpcRequest, *args, **kwargs):
try:
validated = schema_cls(**(request.params or {}))
except ValidationError as e:
return RpcResponse(
id=request.id,
ok=False,
error_code=GatewayErrorCode.INVALID_PARAMS,
error_message=f"参数校验失败: {e}",
)
request._validated_params = validated
return await func(request, *args, **kwargs)
return wrapper
return decorator