Skip to content

Chat Provider Client

GodeX 需要在提供商特定逻辑(规约、钩子、能力声明)和实际与上游 API 通信的原始 HTTP 传输层之间有一个清晰的边界。ChatProviderClient 正好占据了这个边界。它接收提供商名称、base URL、API 密钥和可选的超时时间,暴露两个方法 -- request()stream() -- 这两个方法委托给生成的 ChatApi 类,并将每个错误包装为带有适当领域码的 ProviderError

这一层的存在使得提供商实现永远不需要处理原始 fetch 错误或 SSE 解析。客户端吸收了超时检测、响应体提取和状态码分类的复杂性,因此每个提供商规约只需声明它支持什么,而不需要关心 HTTP 如何工作。

概览

组件文件用途
ChatProviderClientchat-provider-client.ts带错误包装的类型化 HTTP 客户端
ChatApichat-api.ts装饰器生成的 API 类(@post 方法)
chatApi 工厂chat-api.ts:42-53创建带有 Bearer 认证和超时的 ChatApi 实例
wrapProviderErrorchat-provider-client.ts:47-96将未知错误转换为 ProviderError
assertProviderChatRequestchat-request-guard.ts在发送前验证修补后的请求形状
示例客户端example/client.ts参考实现

类图

ChatProviderClient

构造函数(chat-provider-client.ts:22-25)通过 chatApi 工厂创建一个 ChatApi 实例,传入 baseURLapiKeytimeout。提供商名称被存储用于错误上下文。

request(body)

发送非流式 Chat Completions 请求(chat-provider-client.ts:27-33):

  1. 调用 this.api.chatCompletions(body)
  2. 失败时,调用 wrapProviderError(err, this.provider) 并抛出结果。

stream(body)

发送流式 Chat Completions 请求(chat-provider-client.ts:35-44):

  1. 在请求体上强制设置 stream: true
  2. 调用 this.api.streamChatCompletions(body)
  3. 失败时,以与 request() 相同的方式包装错误。

ChatApi 和 chatApi 工厂

ChatApi 是一个装饰器生成的类(chat-api.ts:23-40),有两个方法:

方法端点结果处理
chatCompletionsPOST chat/completions默认 JSON 提取
streamChatCompletionsPOST chat/completions用于 SSE 解析的 JsonStreamResultExtractor

chatApi 工厂(chat-api.ts:42-53)构造一个 Fetcher,带有:

  • 来自选项的 baseURL
  • 来自选项的 timeout
  • Authorization: Bearer {apiKey} 头部

JsonStreamResultExtractorstream-result-extractor.ts:13-17)使用一个 DoneDetector 来检查 [DONE] SSE 哨兵值,以判断流何时终止。

错误包装

wrapProviderError 函数(chat-provider-client.ts:47-96)将错误分类为领域码:

错误码分类

HTTP 状态码领域码含义
408PROVIDER_UPSTREAM_TIMEOUT请求超时(fetch 层或上游)
429PROVIDER_UPSTREAM_RATE_LIMIT触及上游速率限制
500-599PROVIDER_UPSTREAM_SERVER_ERROR上游服务器错误
其他PROVIDER_UPSTREAM_ERROR通用上游故障
无响应PROVIDER_UPSTREAM_ERROR网络层故障(DNS、连接被拒绝等)

对于 ExchangeError 实例,包装器还尝试将响应体提取为 JSON 并读取 error.message 字段以获取可读消息(chat-provider-client.ts:62-83)。如果解析失败,safeResponseJson 会优雅地返回 nullchat-provider-client.ts:113-122)。

请求生命周期

示例提供商

src/providers/example/client.ts 处的示例提供商展示了最小使用模式。createExampleProviderEdgeclient.ts:11-26)使用 EXAMPLE_PROVIDER_SPEC 和可选的传输覆盖调用 createProviderEdge。在实际提供商中,传输函数将是 ChatProviderClient 实例上的方法,而不是直接注入的。

ChatRequestGuard

在发送之前,chat-request-guard.ts:5-27 处的 assertProviderChatRequest 验证请求对象具有非空的 model 字符串和 messages 数组。每个提供商的 patchRequest 钩子都调用此守卫,以便在请求到达网络层之前尽早捕获格式错误的请求。

交叉引用

  • ProviderSpec 契约 -- 声明 chatApi 消费的端点和认证配置的规约
  • Provider Hooks -- 在 ChatProviderClient 接收请求体之前运行的 patchRequest 钩子

参考资料