proxy-playbook/docs/ARCHITECTURE.md

1.7 KiB
Raw Permalink Blame History

整体架构

核心流程

  1. 客户端 POST /v1/chat/completions 到本地端口
  2. 中间件做三件事:
    • 校验本地 API Key(Authorization: Bearer )
    • 读 body 里的 model,按前缀路由
    • 如果带前缀,把 model 改成去掉前缀后的上游模型名
  3. 根据 stream 字段选择转发方式:
    • stream=true → 打开上游 SSE,字节流实时转发
    • 非流式 → 缓冲上游完整响应后返回

模型前缀路由

前缀 ProviderKind Region
wbcn- / workbuddy-cn / codebuddy- WORKBUDDY_CN CN
wbintl- / workbuddy-intl / workbuddy- WORKBUDDY_INTL INTL
traecn- / trae-cn / trae- TRAE_CN CN
traeintl- / trae-intl TRAE_INTL INTL
其它 OPENAI_COMPATIBLE(Sub2API 透传) -

请求生命周期

POST /v1/chat/completions
  -> authorized()            // 401 if invalid key
  -> extractModel(rawBody)   // "traecn-glm-5.2"
  -> router.route(model)     // (TRAE_CN, CN)
  -> stripModelPrefix(model) // "glm-5.2"
  -> rewriteModelBody()      // 替换 body.model
  -> pooled = pool.next(kind, region, sessionKey)
  -> traeChatProxy.openStreamingChat(body, pooled?.accountId, region)
  -> respondOutputStream(...) // 逐块写上游字节

账号池

  • 从 CredentialRepository.accountsFor(service) 读取实时账号
  • 每个 ProviderKind 一个轮询游标(round-robin)
  • 会话粘性:X-Conversation-Id 或 body user 作为 key,同会话复用同一账号
  • 地区匹配:优先选择 credential.region == route.region,没有则回退全部

本地服务

  • GET /health → 存活检查
  • GET /v1/models → 透传 Sub2API 模型列表
  • POST /v1/chat/completions → 聊天代理