【免费下载链接】Kiro-Go
🚀 Convert Kiro accounts into OpenAI/Anthropic APIs. Features multi-account pooling, streaming, auto token refresh, and a web admin panel.
Kiro-Go 是一个开源的 API 代理服务,它把 Kiro 账号转换为兼容 OpenAI 与 Anthropic(Claude)的接口,并支持多账号池化与自动 Token 刷新。它的流式输出能力建立在两层关键技术之上:上游解析 Kiro 返回的AWS Event Stream 二进制事件流,下游通过SSE(Server-Sent Events)实时传输把每个 token 即时推给客户端,从而大幅降低感知响应延迟。本文带你完整走一遍这条数据链路。
为什么流式输出对 AI 代理至关重要
非流式(buffered)响应意味着客户端必须等整个回答生成完毕才能看到第一个字——一次长回复可能要等几十秒才有反馈。而流式输出让文字"边生成边显示",用户几乎在请求发出后一两百毫秒内就能看到内容开始滚动,感知延迟大幅下降,这也是 Claude Code、各类 Chat 客户端默认开启stream: true的原因。
对 Kiro-Go 这样的中间代理来说,挑战在于:上游 Kiro 接口并不直接吐 SSE,而是输出 AWS 私有二进制格式的事件流;下游客户端又要求标准的 SSE 文本格式。Kiro-Go 在中间做了一次"二进制 → 事件 → SSE"的实时转译,且全程不整块缓存,这是低延迟的核心。
全链路:从客户端请求到 Kiro 上游
一次流式请求在 Kiro-Go 内部经历四个阶段:
客户端 ──stream:true──▶ SSE 通道建立 ──▶ 账号池选号 ──▶ Kiro 上游 ▲ │ │ │ └────────────────── SSE 逐事件下发 ◀── 事件解析 ◀── 二进制事件流 ─┘- 请求入口:客户端调用
/v1/messages(Claude 协议)或/v1/chat/completions(OpenAI 协议)并带上"stream": true,路由分发逻辑见 main.go 与 proxy/handler.go。 - SSE 通道建立:处理器立即写入
Content-Type: text/event-stream; charset=utf-8等响应头并获取http.Flusher,见 proxy/handler.go。 - 账号池选号:从多账号池中按模型轮询挑选可用账号,自动完成 Token 刷新。
- 上游调用与转译:POST 请求到 Kiro 的
generateAssistantResponse端点,边读边解析边转发。
端点自动降级与流式重试
Kiro-Go 内置了三个上游端点(Kiro IDE / CodeWhisperer / Amazon Q)以及 API Key 专属的 CLI runtime 端点,配置见 proxy/kiro.go。当某个端点返回 429 配额耗尽或非 200 状态时,自动尝试下一个端点;若流在尚未输出任何内容时就中断,则间隔 700ms 重试一次(重试预算常量见 proxy/kiro.go)。
这里有一个巧妙设计:只有当"第一个字都还没吐出来"时重试才是安全的——一旦已有回调触发过输出,重试会导致内容重复拼接,所以解析器会明确标记emitted状态,见 proxy/kiro.go。
AWS Event Stream 解析:二进制流如何变成可读事件
Kiro 上游(本质是 AWS 托管服务)不返回 JSON 或 SSE,而是返回AWS Event Stream——一种二进制分帧协议。Kiro-Go 在 proxy/kiro.go 中用约百行代码实现了完整解析。
12 字节序言与分帧结构
每帧消息的布局是固定的:
┌──────────── 12 字节序言(Prelude)────────────┐┌── 帧体 ──────────┐ │ totalLength(4B) │ headersLength(4B) │ 预CRC(4B) │ headers │ payload(JSON) │ 尾CRC(4B) │ └───────────────────────────────────────────────┴┴─────────────────────────┘解析流程很简单:先io.ReadFull读满 12 字节序言,从totalLength算出剩余帧长,再一次性读完整帧;随后从头字节区中扫描出:event-type头确定事件类型,payload 部分按 JSON 反序列化。头字节区本身也是二进制编码(长度前缀 + 类型编号),提取逻辑见 proxy/kiro.go。
五类核心事件
解析器通过事件类型分发处理,每类事件各司其职:
| 事件类型 | 含义 | Kiro-Go 的处理 |
|---|---|---|
assistantResponseEvent | 正文增量(纯增量 delta) | 立即回调OnText,实时转发 |
reasoningContentEvent | 思考过程增量 | 回调OnText(isThinking=true) |
toolUseEvent | 工具调用(输入分片到达) | 缓冲拼装完整 JSON 后回调 |
meteringEvent | 计费信息 | 累加 credits 用于用量统计 |
contextUsageEvent | 上下文占用百分比 | 换算为真实输入 token 数 |
值得注意的细节:源码注释明确说明上游发送的是纯增量 delta 而非累计快照,且协议本身不带序号,因此 Kiro-Go 刻意不做基于内容的去重——曾经的内容去重逻辑会把"6666666666"误判成重复而吞成"666"。信任 TCP 的顺序保证、原样透传,反而是最正确也最快的做法。事件分发见 proxy/kiro.go。
SSE 实时传输:每个字如何到达客户端
拿到文本增量后,Kiro-Go 按客户端协议组装标准 SSE 事件,核心是 3 行的sendSSE:序列化 JSON、写入event:+data:两行、立即 Flush,见 proxy/handler.go。
Claude 与 OpenAI 双协议输出
同一条上游事件流,会被翻译成两套完全不同的 SSE 格式:
- Claude 协议(handleClaudeStream):
message_start→content_block_start→ 逐条content_block_delta(text_delta/thinking_delta)→content_block_stop→message_delta→message_stop; - OpenAI 协议(handleOpenAIStream):逐条
chat.completion.chunk对象,思考内容可放入reasoning_content字段,以data: [DONE]收尾(proxy/handler.go)。
以 OpenAI 格式为例,客户端收到的数据长这样:
data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"delta":{"content":"你好"}}]} data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"delta":{"content":",世界"}}]} data: [DONE]为什么"不缓冲"是延迟的关键
Kiro-Go 在三处刻意消除了缓冲,每一处都直接影响首字延迟:
- 读上游不套 bufio:解析器直接
io.ReadFull读帧,避免读写缓冲引入的等待(proxy/kiro.go 注释明确写着 "avoid buffering latency in streaming responses"); - 每帧必 Flush:SSE 事件写出一瞬间就推给客户端,不攒批;
- 服务端不设置 WriteTimeout:
main.go中WriteTimeout刻意留空(0),因为一条 SSE 流可能持续好几分钟,任何写超时会掐断长流,见 main.go。
此外还有一层"文本切分缓冲":为了正确识别流中可能出现的<thinking>标签边界,会保留约 15 个字符的回看窗口再放行——这是精度与延迟之间的折中,窗口极小,几乎不增加延迟。
响应延迟为什么能大幅降低
把上面的机制串起来,低延迟来自四个叠加因素:
- 零整块缓存:上游一个字节到位 → 解析 → SSE 下发,全链路无"等全文"环节;
- 首字即达:客户端在
message_start/ 第一个 chunk 后几百毫秒内就开始看到文字; - 失败快速转移:端点 429、账号失效时毫秒级切换下一个端点或账号,用户几乎无感;
- 静默重试无副作用:未输出的流自动重试,输出过的流绝不重放,不浪费也不重复。
对使用者而言,效果就是:接入 Kiro-Go 的 Claude / OpenAI 客户端体验与直连官方 API 的流式对话几乎没有差别。
快速验证:自己观察一次流式输出
部署完成后(参考 README_CN.md 的 Docker Compose 步骤),可用curl -N直接观察 SSE 事件到达的节奏:
curl -N http://localhost:8080/v1/chat/completions \ -H "Authorization: Bearer any" \ -H "Content-Type: application/json" \ -d '{"model":"gpt-4o","stream":true,"messages":[{"role":"user","content":"数到5"}]}'加-N关闭 curl 自身缓冲,你会看到 chunk 一条条实时刷屏,而不是憋到最后一次性输出——这就是 SSE 实时传输最直观的证据。
关键源码路径速查
| 模块 | 说明 |
|---|---|
| proxy/kiro.go | AWS Event Stream 二进制解析核心 |
| proxy/kiro.go | 端点选择、降级与流式重试 |
| proxy/handler.go | Claude 协议 SSE 流组装 |
| proxy/handler.go | OpenAI 协议 SSE 流组装 |
| proxy/handler.go | sendSSE:写事件并立即 Flush |
| main.go | HTTP 服务器超时配置(SSE 长连接适配) |
| proxy/kiro_api.go | Kiro REST 辅助接口(用量/模型列表) |
从二进制的 12 字节序言,到屏幕上一字一顿滚动的回答,Kiro-Go 用一条"解析即转发、转发即刷新"的管道,把 AWS 私有事件流无缝翻译成了人人可用的标准 SSE 流式接口。理解这条链路后,无论是排查流式卡顿还是扩展新协议,你都有了清晰的地图。
【免费下载链接】Kiro-Go
🚀 Convert Kiro accounts into OpenAI/Anthropic APIs. Features multi-account pooling, streaming, auto token refresh, and a web admin panel.
相关推荐
数字农业与精准农业公司:Awesome Geospatial Companies中的农业科技先锋
数字农业与精准农业公司:Awesome Geospatial Companies中的农业科技先锋 在当今农业现代化进程中,数字农业与精准农业正成为推动农业可持续
GIS文档ElevenLabs 实时语音流式传输:构建低延迟AI对话应用
ElevenLabs 实时语音流式传输:构建低延迟AI对话应用 ElevenLabs Python SDK 提供了强大的实时语音流式传输功能,让开发者能够构建低
低延迟游戏串流的实时响应:Sunshine事件通知机制详解
低延迟游戏串流的实时响应:Sunshine事件通知机制详解 作为自托管的游戏流媒体服务器,Sunshine不仅提供高质量的游戏串流体验,还通过完善的事件通知机制
音视频后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考