Chat Provider Client
GodeX 需要在提供商特定逻辑(规约、钩子、能力声明)和实际与上游 API 通信的原始 HTTP 传输层之间有一个清晰的边界。ChatProviderClient 正好占据了这个边界。它接收提供商名称、base URL、API 密钥和可选的超时时间,暴露两个方法 -- request() 和 stream() -- 这两个方法委托给生成的 ChatApi 类,并将每个错误包装为带有适当领域码的 ProviderError。
这一层的存在使得提供商实现永远不需要处理原始 fetch 错误或 SSE 解析。客户端吸收了超时检测、响应体提取和状态码分类的复杂性,因此每个提供商规约只需声明它支持什么,而不需要关心 HTTP 如何工作。
概览
| 组件 | 文件 | 用途 |
|---|---|---|
ChatProviderClient | chat-provider-client.ts | 带错误包装的类型化 HTTP 客户端 |
ChatApi | chat-api.ts | 装饰器生成的 API 类(@post 方法) |
chatApi 工厂 | chat-api.ts:42-53 | 创建带有 Bearer 认证和超时的 ChatApi 实例 |
wrapProviderError | chat-provider-client.ts:47-96 | 将未知错误转换为 ProviderError |
assertProviderChatRequest | chat-request-guard.ts | 在发送前验证修补后的请求形状 |
| 示例客户端 | example/client.ts | 参考实现 |
类图
ChatProviderClient
构造函数(chat-provider-client.ts:22-25)通过 chatApi 工厂创建一个 ChatApi 实例,传入 baseURL、apiKey 和 timeout。提供商名称被存储用于错误上下文。
request(body)
发送非流式 Chat Completions 请求(chat-provider-client.ts:27-33):
- 调用
this.api.chatCompletions(body)。 - 失败时,调用
wrapProviderError(err, this.provider)并抛出结果。
stream(body)
发送流式 Chat Completions 请求(chat-provider-client.ts:35-44):
- 在请求体上强制设置
stream: true。 - 调用
this.api.streamChatCompletions(body)。 - 失败时,以与
request()相同的方式包装错误。
ChatApi 和 chatApi 工厂
ChatApi 是一个装饰器生成的类(chat-api.ts:23-40),有两个方法:
| 方法 | 端点 | 结果处理 |
|---|---|---|
chatCompletions | POST chat/completions | 默认 JSON 提取 |
streamChatCompletions | POST chat/completions | 用于 SSE 解析的 JsonStreamResultExtractor |
chatApi 工厂(chat-api.ts:42-53)构造一个 Fetcher,带有:
- 来自选项的
baseURL - 来自选项的
timeout Authorization: Bearer {apiKey}头部
JsonStreamResultExtractor(stream-result-extractor.ts:13-17)使用一个 DoneDetector 来检查 [DONE] SSE 哨兵值,以判断流何时终止。
错误包装
wrapProviderError 函数(chat-provider-client.ts:47-96)将错误分类为领域码:
错误码分类
| HTTP 状态码 | 领域码 | 含义 |
|---|---|---|
| 408 | PROVIDER_UPSTREAM_TIMEOUT | 请求超时(fetch 层或上游) |
| 429 | PROVIDER_UPSTREAM_RATE_LIMIT | 触及上游速率限制 |
| 500-599 | PROVIDER_UPSTREAM_SERVER_ERROR | 上游服务器错误 |
| 其他 | PROVIDER_UPSTREAM_ERROR | 通用上游故障 |
| 无响应 | PROVIDER_UPSTREAM_ERROR | 网络层故障(DNS、连接被拒绝等) |
对于 ExchangeError 实例,包装器还尝试将响应体提取为 JSON 并读取 error.message 字段以获取可读消息(chat-provider-client.ts:62-83)。如果解析失败,safeResponseJson 会优雅地返回 null(chat-provider-client.ts:113-122)。
请求生命周期
示例提供商
src/providers/example/client.ts 处的示例提供商展示了最小使用模式。createExampleProviderEdge(client.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钩子
参考资料
- src/providers/shared/chat-provider-client.ts --
ChatProviderClient、wrapProviderError - src/providers/shared/chat-api.ts --
ChatApi、chatApi工厂 - src/providers/shared/stream-result-extractor.ts --
JsonStreamResultExtractor、DoneDetector - src/providers/shared/chat-request-guard.ts --
assertProviderChatRequest - src/providers/example/client.ts -- 示例提供商 edge 工厂
- src/providers/example/spec.ts -- 示例提供商规约
- src/error/codes.ts -- 提供商错误领域码