ForcePilot/backend/package/yuxi/gateway/protocol/handshake.py
Kris fee71576a2 feat(gateway): add core gateway protocol implementation
新建了完整的网关协议模块,包含版本协商、基础类型定义、信道请求模型、错误码规范、通信帧结构以及握手流程,实现了完整的客户端-服务端通信协议基础框架
2026-05-12 00:54:15 +08:00

76 lines
2.1 KiB
Python

from __future__ import annotations
import uuid
from typing import Literal
from pydantic import BaseModel, Field
from yuxi.gateway.protocol.version import negotiate_version
class ConnectParams(BaseModel):
min_protocol: int = 1
max_protocol: int = 1
client_id: str = ""
client_version: str = ""
client_platform: str = ""
auth_token: str | None = None
caps: list[str] = Field(default_factory=list)
client_display_name: str = ""
client_device_family: str = ""
client_model_identifier: str = ""
client_mode: str = "default"
client_instance_id: str = ""
commands: list[str] = Field(default_factory=list)
permissions: dict[str, bool] = Field(default_factory=dict)
path_env: str = ""
role: str = ""
scopes: list[str] = Field(default_factory=list)
locale: str = ""
user_agent: str = ""
class HelloFeatures(BaseModel):
methods: list[str] = Field(default_factory=list)
events: list[str] = Field(default_factory=list)
class HelloOk(BaseModel):
type: Literal["hello-ok"] = "hello-ok"
protocol: int
server_version: str
server_id: str
session_id: str
features: HelloFeatures = Field(default_factory=HelloFeatures)
snapshot: dict | None = None
dm_policy: str = "pairing"
group_policy: str = "allowlist"
conn_id: str = ""
max_payload: int = 1048576
max_buffered_bytes: int = 10485760
tick_interval_ms: int = 5000
async def handle_handshake(params: ConnectParams) -> HelloOk:
protocol = negotiate_version(params.min_protocol, params.max_protocol)
if protocol is None:
raise ValueError("Protocol version negotiation failed")
session_id = str(uuid.uuid4())
conn_id = f"conn-{session_id[:8]}"
return HelloOk(
protocol=protocol,
server_version="1.0.0",
server_id="forcepilot-gateway",
session_id=session_id,
conn_id=conn_id,
features=HelloFeatures(
methods=["channel.status", "channel.start", "channel.stop", "chat.send", "chat.abort"],
events=["channel.status_change", "tick", "chat", "channel.logout", "config.reload"],
),
)