ForcePilot/backend/package/yuxi/channels/protocols/session_router.py
Kris f8a985aad8 feat(channels): 新增会话路由、错误分类与聊天能力支持
1. 新增ChannelStreamingProtocol协议的打字指示器、消息编辑支持和 fallback 发送方法
2. 重构SDK导入顺序,调整normalizer和retry的导入位置
3. 新增错误分类模块,实现异常类型归类逻辑
4. 新增SessionRouter抽象基类,实现基础会话路由逻辑
5. 增强重试SDK,添加总超时、熔断和指标回调支持
2026-05-13 16:20:54 +08:00

65 lines
2.2 KiB
Python

from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
from yuxi.channels.models import SessionScope
if TYPE_CHECKING:
from yuxi.channels.models import ChannelMessage
class SessionRouter(ABC):
def __init__(self, channel_type: str, account_id: str = "default"):
self.channel_type = channel_type
self.account_id = account_id
@abstractmethod
def resolve_thread_key(self, message: ChannelMessage) -> str:
"""解析消息对应的线程键"""
@abstractmethod
def resolve_chat_id(self, message: ChannelMessage) -> str:
"""解析聊天ID"""
@abstractmethod
def resolve_session_scope(self, message: ChannelMessage) -> SessionScope:
"""解析会话范围级别"""
@abstractmethod
def normalize_target(self, target: str) -> str:
"""标准化目标地址"""
def resolve_agent_route(self, message: ChannelMessage) -> str:
thread_key = self.resolve_thread_key(message)
scope = self.resolve_session_scope(message)
return f"agent:main:{thread_key}:{scope.value}"
def _build_key(self, scope: str, type_str: str, id_str: str) -> str:
return f"{self.channel_type}:{self.account_id}:{scope}:{type_str}:{id_str}"
class BaseSessionRouter(SessionRouter):
def normalize_target(self, target: str) -> str:
if target.startswith(f"{self.channel_type}:"):
return target
return f"{self.channel_type}:{target}"
def resolve_thread_key(self, message: ChannelMessage) -> str:
identity = message.identity
chat_type = message.chat_type.value if hasattr(message.chat_type, "value") else str(message.chat_type)
return self._build_key("chat", chat_type, identity.channel_chat_id)
def resolve_chat_id(self, message: ChannelMessage) -> str:
return message.identity.channel_chat_id
def resolve_session_scope(self, message: ChannelMessage) -> SessionScope:
from yuxi.channels.models import ChatType
chat_type = message.chat_type
if chat_type == ChatType.DIRECT:
return SessionScope.DIRECT
if chat_type == ChatType.THREAD:
return SessionScope.THREAD
return SessionScope.GROUP