多家族、多渠道、故障转移的 AI 协议代理
像鹦鹉学舌一样,把下游客户端的请求转发到多个上游,自动挑最快的、故障切到备用。 双家族(Anthropic / OpenAI)、三种入口协议、多种上游协议,还能家族内互转。
Parrot 的核心价值:一个进程管住所有 AI 家族的上游复用。你手上有一堆 Claude OAuth 账号、ChatGPT Plus OAuth 账号、第三方 GLM / Codex Coding Plan,不想维护 3 套代理 + 3 套统计 + 3 个 TG Bot;Parrot 把它们统一抽象成「渠道」,配上评分调度、故障转移、会话亲和、OAuth 自动刷新、Telegram 图形面板。
多家族 · 多入口
| 入口 | 协议 | 对接客户端 |
|---|---|---|
POST /v1/messages |
Anthropic Messages API | Claude Code CLI、OpenClaw、任何 Anthropic SDK |
POST /v1/chat/completions |
OpenAI Chat Completions | 大部分 OpenAI SDK / 三方工具 |
POST /v1/responses |
OpenAI Responses API | Codex CLI、新版 OpenAI SDK |
POST /v1/images/generate |
Parrot 图片生成 | 用 Parrot API Key 调 ChatGPT/Codex 图片生成 |
POST /v1/images/edit |
Parrot 图片编辑 | 单图修改 / 重绘 / 风格化 |
三类上游渠道
| 渠道 | 类型 | 说明 |
|---|---|---|
| 🅰 Anthropic OAuth | Claude Code 官方账户 | 完整 CC 伪装(指纹 / CCH / 工具名混淆 / cache 断点),与 cc-proxy 同源移植 |
| 🅾 OpenAI OAuth (Codex) | ChatGPT Plus/Pro/Enterprise | 对接 chatgpt.com/backend-api/codex/responses,SSE 聚合、rate-limit 头自动解析 |
| 🔀 第三方 API 渠道 | 智谱 / 天翼云 / 京东云 / 讯飞星辰 / 任何 Anthropic 或 OpenAI 兼容服务 | 可开关 CC 伪装;按 protocol 决定走哪种请求构造器 |
家族内互转:/v1/chat/completions 下游请求可以打到 openai-responses 上游,反之亦然(SSE 双向状态机 + CapabilityGuard 兜底不兼容字段)。
图片生成 / 修改:提供 Parrot 简化图片接口 POST /v1/images/generate 和 POST /v1/images/edit,内部复用 OpenAI OAuth 账号走 ChatGPT Codex Responses + image_generation tool;下游只需要 Parrot API Key、提示词、可选分辨率即可生成图片,编辑接口额外提交单张输入图。图片权限与普通文本 API 独立,API Key 默认不允许图片接口,需要在 TG 面板显式开启。
运行时保护
- 四段超时独立:
connect/firstByte/idle(chunk 间)/total(硬上限),任一超时都不会拖死整个请求 - 首包锁:发任何字节给下游前是"可切换"区;首字节发出后锁渠道,异常转 SSE error 事件收尾
- 故障转移:按智能排序依次试候选,
upstream_stream_only渠道(如 OAuth Codex)对非流式下游自动走 SSE 聚合 - 错误阶梯冷却:
[1, 3, 5, 10, 15, 0]分钟,成功一次清零;OAuth 渠道带宽容次数(oauthGraceCount: 3)避免偶发抖动误冷却;并带两层爆发保护(阶梯推进最小间隔cooldownLadderMinIntervalSeconds+ 永久冷却最小累计cooldownPermanentMinAgeSeconds),挡住客户端秒级重试把渠道打穿 - 渠道并发限制(v0.2.0):每个渠道可配
maxConcurrent,同一时刻只放行这么多个在途请求;其余候选进 FIFO 排队直到有位置或queueWaitSeconds超时(429);TG 主菜单 overview 实时显示在途 / 排队 / 追踪渠道数 - 会话亲和:双层指纹 =
hash(api_key | ip | 倒数两条消息);session 级 TTL 30min、client 级 soft 回退 TTL 120min(无历史也能命中最近用过的渠道) - OAuth 配额监控:Claude 账户拉
/api/oauth/usage;OpenAI 账户解析 Codexrate-limit响应头;阈值自动禁用/恢复 - 评分调度:滑动窗口 EMA 延迟 + 失败惩罚;带 20% 探索率避免赢家通吃
- 模型映射 & 入口默认模型:三条入口(anthropic / openai-chat / openai-responses)各自独立维护
别名 → 真实模型表和默认模型;下游客户端发别名、代理改写成真实名再走调度,上游发新模型时改 TG bot 即生效,无需重启客户端 - 出站网络设置:支持在 TG「系统设置 → 网络设置」里配置 DNS 与 SOCKS5。DNS 默认
8.8.8.8,首次启动可从系统 DNS 同步一次;DNS 支持普通 IP/域名、DoT(dot://...)和 DoH(https://.../dns-query),DNS 服务器域名本身用系统 DNS 解析避免套娃。启用 SOCKS5 后所有出站 HTTP 请求走 SOCKS5,代理地址若为域名则使用配置 DNS 解析,保存前会检测并二次确认。内置「网络检测」后台监控,可按间隔检测 DNS / SOCKS5 / 渠道 TCP 连通性 / OpenAI、Claude、Cloudflare 核心上游,并在失败/恢复边沿各通知一次。 - 图片日志与缓存:图片调用写入独立
image_logs.db,不污染文本请求日志;可选缓存生成结果到images/,支持保留天数 / 空间上限清理。API 响应不暴露本地缓存路径,TG 管理员可在最近图片日志中点按钮查看缓存图片。
Telegram 图形管理面板
发 /start 进主菜单,全图形化配置(文末详述)。
提供 4 种部署方式,推荐一键脚本。
bash <(curl -Ls https://raw.githubusercontent.com/danger-dream/Parrot/main/deploy.sh)脚本会:
- 显示项目信息 + 检查 / 引导安装 Docker + Docker Compose
- 交互式收集:安装目录(默认
/opt/parrot)/ TG Bot Token / Admin Telegram User ID / 监听端口 - 生成
docker-compose.yml+ 最小data/config.json docker compose pull && up -d,并验证/health+ TG Bot polling
完成后到 Telegram 找你的 bot 发 /start,剩下的渠道 / OAuth / API Key 全在图形界面里配。
mkdir -p parrot/data && cd parrot
# 拿 compose 模板
curl -Lo docker-compose.yml https://raw.githubusercontent.com/danger-dream/Parrot/main/docker-compose.yml
# 写最小 config.json(首次启动 server 会自动补全其余默认字段)
cat > data/config.json <<'EOF'
{
"listen": { "host": "0.0.0.0", "port": 22122 },
"telegram": {
"botToken": "<你的 bot token>",
"adminIds": [<你的 Telegram user id>]
}
}
EOF
docker compose up -d
docker compose logs -fmkdir -p ./data
# 先写 ./data/config.json(见方式二)
docker run -d \
--name parrot \
--restart unless-stopped \
-p 22122:22122 \
-e TZ=Asia/Shanghai \
-e ANTHROPIC_PROXY_DATA_DIR=/app/data \
-v "$PWD/data:/app/data" \
ghcr.io/danger-dream/parrot:latest
ANTHROPIC_PROXY_DATA_DIR是老环境变量名,为向后兼容保留;后续会加PARROT_DATA_DIR别名。
git clone https://github.com/danger-dream/Parrot
cd Parrot
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
# 编辑 config.json(首次启动会自动生成模板)
./venv/bin/python server.py# Anthropic 协议入口(Claude 家族)
curl http://<server>:22122/v1/messages \
-H "x-api-key: ccp-你的Key" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [{ "role": "user", "content": "Hello" }]
}'
# OpenAI Chat 协议入口(GPT 家族)
curl http://<server>:22122/v1/chat/completions \
-H "Authorization: Bearer ccp-你的Key" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4",
"messages": [{ "role": "user", "content": "Hello" }]
}'
# OpenAI Responses 协议入口(Codex 原生)
curl http://<server>:22122/v1/responses \
-H "Authorization: Bearer ccp-你的Key" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4",
"input": [{ "role": "user", "content": "Hello" }]
}'
# 图片生成(需要该 API Key 开启 allowImages)
curl http://<server>:22122/v1/images/generate \
-H "Authorization: Bearer ccp-你的Key" \
-H "Content-Type: application/json" \
-d '{
"prompt": "一只赛博朋克鹦鹉站在霓虹灯牌前,电影感海报",
"size": "1024x1024"
}'
# 图片编辑 / 修改(单图,image 可传 data URL、裸 base64 或 http(s) URL)
curl http://<server>:22122/v1/images/edit \
-H "Authorization: Bearer ccp-你的Key" \
-H "Content-Type: application/json" \
-d '{
"prompt": "把画面改成蓝紫色赛博朋克风格,保持主体不变",
"image": "data:image/png;base64,...",
"size": "1024x1024"
}'官方 SDK 接入:把 baseURL 指向 http://<server>:22122/v1,apiKey 填 Parrot 生成的下游 Key,即可直接用 openai / anthropic 官方 Python / Node SDK。图片接口是 Parrot 简化接口,不是 OpenAI 标准 Images API;请直接请求 /v1/images/generate / /v1/images/edit。
┌────────────────────────────────────────────────────────────────┐
│ 下游客户端(Anthropic SDK / OpenAI SDK / Codex CLI / Claude Code CLI)│
└──────────────┬──────────────┬──────────────┬──────────────────┘
│ │ │
POST /v1/messages /v1/chat/... /v1/responses
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────────────┐
│ FastAPI 入口 + auth + 日志落盘 │
└──────────────────────────┬───────────────────────────────┘
│ ingress_protocol =
│ anthropic | chat | responses
▼
┌──────────────────────────────────────────────────────────┐
│ scheduler.schedule │
│ 1. 按 ingress 家族硬过滤(anthropic 家族 ↔ openai 家族)│
│ 2. 筛选 enabled + 非冷却 + 支持模型的渠道 │
│ 3. 会话亲和(fingerprint = key+ip+msg[-2:] 的 hash) │
│ 4. 评分排序(EMA 延迟 + 失败惩罚 + 20% 探索率) │
└──────────────────────────┬───────────────────────────────┘
│ candidates: [(channel, model), ...]
▼
┌──────────────────────────────────────────────────────────┐
│ failover.run_failover (顺序尝试 + 首包锁) │
│ ingress=anthropic → AnthropicOAuth / ApiChannel │
│ ingress=chat → OpenAIApiChannel / OpenAIOAuth │
│ ingress=responses → 同上(responses 优先) │
│ 跨变体时走 chat↔responses 双向 SSE 状态机 │
│ upstream_stream_only 渠道对非流式请求用 SSE 聚合器兜底 │
└──────────────────────────┬───────────────────────────────┘
│
┌───────────────────┼───────────────────────┐
▼ ▼ ▼
🅰 Anthropic OAuth 🅾 OpenAI OAuth 🔀 Third-party API
(Claude Code CC伪装) (chatgpt.com/codex) (智谱/天翼云/京东云/讯飞…)
│ │ │
▼ ▼ ▼
api.anthropic.com chatgpt.com/backend-api third-party endpoints
详细设计见 docs/ 目录(12 篇)和 docs/openai/ 子目录(10 篇)。
完整兼容 Anthropic Messages API。鉴权通过 x-api-key 或 Authorization: Bearer <key>。
- 流式(
stream: true,默认):SSE - 非流式:JSON
- 错误:Anthropic 标准错误格式
完整兼容 OpenAI Chat Completions API。鉴权通过 Authorization: Bearer <key>。
完整兼容 OpenAI Responses API。支持 previous_response_id 续写(本地 store)、reasoning.effort、Codex 工具调用等。
Parrot 简化图片生成接口。鉴权通过 Authorization: Bearer <key> 或 x-api-key;该 API Key 必须开启 allowImages。
请求体:
{
"prompt": "要生成的图片描述",
"size": "1024x1024"
}字段说明:
prompt:必填,图片提示词。size:选填;不传时 Parrot 不会给上游传size,由上游默认决定。Parrot 不做固定白名单,按上游能力处理。
Parrot 简化图片编辑接口。用于单张图片修改 / 重绘 / 风格化;同样需要 API Key 开启 allowImages。
JSON 请求体:
{
"prompt": "如何修改这张图片",
"image": "data:image/png;base64,...",
"size": "1024x1024"
}也支持 multipart/form-data:
prompt:必填。image:上传文件,或字符串形式的 data URL / 裸 base64 / http(s) URL。size:选填。
当前编辑接口定位是单图编辑;多图拼接 / 复杂参考图组合不作为第一版兼容目标。
图片接口成功响应示例:
{
"id": "...",
"object": "parrot.image.generate",
"created": 1777049201,
"action": "generate",
"model": "gpt-5.4-mini",
"image_model": "gpt-image-2",
"account": "openai-account@example.com",
"data": [
{
"b64_json": "...",
"revised_prompt": "...",
"output_format": "png",
"size": "1024x1024",
"bytes": 391542
}
],
"usage": { "input_tokens": 123, "output_tokens": 45 },
"cached": true,
"duration_ms": 80692
}注意:
- 返回图片放在
data[].b64_json,下游需要自行保存为文件或转发给用户。 - 即使开启缓存,API 响应也不会返回服务器本地缓存路径,避免泄露部署路径。
- 上游已经成功生成图片后,如果本地缓存写入失败,请求仍按成功返回,只是
cached=false。
返回当前所有启用渠道聚合的可用模型(按 API Key 白名单过滤),Anthropic 标准格式。 配置了模型映射的别名也会在这里一同列出(条件:别名所在入口的家族对该 Key 放行,且别名指向的真实模型本身对该 Key 可见),这样下游客户端直接拉列表就能看到最新别名。
运维健康检查(无鉴权):
{
"status": "ok", // ok | degraded | error
"channels": { "total": 13, "enabled": 13, "oauth": 7, "api": 6 },
"affinity_bound": 64,
"device_id": "...",
"version": "parrot"
}发 /start 进入主菜单:
[📈 统计汇总] [📋 最近日志]
[🔐 管理 OAuth] [🔀 管理渠道]
[🔁 模型映射] [⚖️ 负载均衡]
[⚙ 系统设置] [❓ 帮助]
- 时间:今天 / 3 天 / 7 天 / 本月
- 维度:汇总(两家族分段)/ 按渠道 / 按模型 / 按 Key
- 汇总视图:先 🅰 Anthropic 段(overall + 按渠道 Top3 + 按模型 Top3),后 🅾 OpenAI 段(同上,完整含重试/亲和);底部跨家族按 Key Top + 最近调用(带家族图标)+ 未命中样本
- 专题视图:按渠道 / 按模型 Top10,每条前缀 🅰/🅾 家族图标
15 条最新请求,每条一个 📄 #N 详情 按钮点进详情页(完整重试链 + 请求/响应 body)。
添加向导(4 步 + 测试面板)、渠道详情、编辑、测试模型(单/全部)。
Base URL 自适应(v0.5.0+):默认填上游域名即可,代理按协议追加
/v1/messages、/v1/chat/completions、/v1/responses。若上游接口挂在非标准路径(如智谱 Coding Plan 的https://open.bigmodel.cn/api/coding/paas/v4/chat/completions),直接把完整调用路径贴进来,向导会自动拆分为baseUrl + apiPath存储,协议不匹配时给出交互式选择(采用识别到的协议 / 坚持当前协议清空路径 / 返回修改)。
- ➕ 新增账户:第一步选 Claude / OpenAI;Claude 支持 PKCE 登录 + 粘贴 JSON;OpenAI 粘贴 refresh_token
- 每条账户显示:状态图标 / 过期时间 / 5h 7d 用量 / 月度统计 / 冷却中的模型
- 详情页:两家族统一布局(提供者 / 计划 / 过期 / 上次刷新 / 使用量 / 月度)
- 操作:刷新 Token / 刷新用量 / 清模型错误 / 清亲和绑定 / 启停 / 删除
- 底部批量:🔄 刷新全部用量 / 🧹 清除所有账户错误(有冷却才显示)
- 图片生成入口:OAuth 列表底部提供「🖼 图片生成」,用于配置图片模型、缓存、图片专用账号禁用列表和最近图片日志。
发送 /keys 管理下游代理 Key。列表直接显示完整 Key(单击即复制);每个 Key 可设模型白名单(多选勾选);删除二次确认。图片生成 / 编辑权限由 allowImages 单独控制,默认关闭,需要在 Key 详情页点击「🖼 允许图片接口」后才能调用 /v1/images/generate / /v1/images/edit。
从「🔐 管理 OAuth」列表底部进入,用于管理 Parrot 图片接口的运行参数与日志:
- 功能开关、主模型
mainModel、图片工具模型toolModel。 - 图片专用账号禁用列表,只影响图片生成 / 编辑,不影响普通 OpenAI OAuth 文本请求。
- 图片缓存开关、缓存路径、保留天数、缓存空间上限。
- 图片调用统计、账号 Top 5、最近调用列表。
- 当缓存开启且图片文件仍存在时,最近成功调用会显示「看图 #id」按钮,管理员可直接把缓存图片发回 Telegram 查看。
smart智能调度:按滑动窗口评分 + 探索率排序order顺序调度:按 config 渠道定义顺序依次尝试priority优先级调度:按用户在 TG 菜单保存的 Anthropic / OpenAI 协议队列依次尝试- 亲和优先于负载均衡:绑定目标仍可用就继续用;不可用时才由当前算法选接班渠道。
三条入口(anthropic / openai-chat / openai-responses)各自独立维护:
- 默认模型:body 缺失
model字段时的兜底;点「✏ 设置默认」直接弹真实模型按钮列表选一下即可 - 别名映射:下游传别名 → 代理改写成真实模型名再走调度(只解一层,无递归)
- 新增映射:先输入别名,再从真实模型按钮列表里选(家族过滤 + 分页 10/页);校验不能与真实模型重名、不能与已有别名冲突
- 条目详情页:点任一已有映射可进入详情页,支持「🏷 修改别名 / 🎯 修改真实 / 🗑 删除」三种操作,修改别名用原子替换保证中间状态不影响线上流量
白名单校验和 /v1/models 列表采用映射后的真实名——API Key 只需授权真模型即可,别名自动跟随。
超时 / 错误阶梯(含阶梯推进最小间隔、永久最小累计两项爆发保护)/ 评分参数 / 亲和参数 / CCH 模式 / 配额监控 / 通知设置 / 首包黑名单 / ⚡ 渠道并发限制。所有设置均热加载,无需重启。
通过 Telegram 主动告知运维关键事件。所有事件可在「⚙ 系统设置」→「🔔 通知设置」单独开关。
| 事件 | 触发条件 | 默认 |
|---|---|---|
| 🔴 渠道永久冻结 | 某 (渠道,模型) 连续失败到永久冷却(首次) | ✅ |
| ✅ 渠道恢复 | 永久 / 长冷却被清除(手动 / probe / 成功一次) | ✅ |
| ⚠ 配额禁用 | OAuth 任一指标 ≥ 阈值被自动禁用 | ✅ |
| ✅ 配额恢复 | 全部指标 < 阈值且 resets_at 已过,自动启用 | ✅ |
| 🔄 OAuth Token 刷新成功 | 后台主动刷新 / 手动触发 | ✅ |
| ❌ OAuth Token 刷新失败 | refresh_token 失效,标 auth_error | ✅ |
| 🚨 无可用渠道告警 | 请求模型在所有渠道都不可用(503) | ✅ |
节流:无可用渠道告警 同 model 5 分钟内最多发一次。
config.json 是唯一配置来源,运行时自动持久化(tmp + os.replace 原子写 + 3 份备份轮转)。
完整字段说明见 docs/02-config-schema.md 和 docs/openai/02-config-schema.md。关键字段速查:
quotaMonitor.enabled默认关闭 —— 启用后每 N 秒拉一次每个 OAuth 账号的 usage(Claude 走/api/oauth/usage,OpenAI 走 Codex 探测头),频繁请求可能被风控盯上。
apiKeys.*.allowImages默认关闭 —— 新建或历史 API Key 不会自动获得图片生成 / 编辑能力,必须在 TG「🔑 管理 API Key」里显式开启。
images.cacheRetentionDays=0表示不按时间清理;images.cacheMaxBytes=0表示不按空间清理。相对cachePath会落在数据目录下,Parrot 会阻止相对路径逃逸。
不可热加载字段(改后需重启容器):listen.host / listen.port / stateDbPath / logDir / telegram.botToken / telegram.adminIds。
所有持久化数据集中在 <安装目录>/data/:config.json / state.db / image_logs.db / logs/ / images/ / .anthropic_proxy_ids.json。
cd <安装目录>
docker compose up -d # 启动
docker compose stop # 停止
docker compose restart # 重启
docker compose ps # 状态
docker compose down # 停止 + 删容器(数据保留在 ./data)cd <安装目录>
docker compose pull
docker compose up -d或重跑一次一键脚本(选
Upgrade模式),等价。
cd <安装目录>
docker compose logs -f # 实时
docker compose logs --tail 100 # 最近 100 条
docker compose logs --since 1h # 最近 1 小时按月分库在 data/logs/YYYY-MM.db(SQLite)。在 TG Bot「📋 最近日志」查看;或宿主机直接 sqlite3 <安装目录>/data/logs/2026-04.db。
图片生成 / 编辑调用使用独立日志库 data/image_logs.db,包含主调用表和账号尝试表;不会改动或污染普通文本请求日志。
图片缓存默认关闭。开启后,生成 / 编辑结果会保存到 data/images/(或 images.cachePath 指定的位置),并按 images.cacheRetentionDays 和 images.cacheMaxBytes 自动清理。缓存路径只在服务端内部使用,API 响应不会暴露本地文件路径;管理员可在 TG「🖼 图片生成」最近调用中点击「看图 #id」查看仍存在的缓存图片。
data/state.db(SQLite):performance_stats / channel_errors / cache_affinities / oauth_quota_cache / openai_response_store。永久保留。
每次配置修改都自动轮转 3 份备份(位于 data/ 目录):
data/config.json
data/config.json.bak.1 (上一版)
data/config.json.bak.2
data/config.json.bak.3 (最老)
如果走「方式四:源码运行」并自己写了 systemd unit,则按该 unit 名管理:
systemctl start/stop/restart/status <你的unit名>
journalctl -u <你的unit名> -f数据文件默认在源码目录下(不设 ANTHROPIC_PROXY_DATA_DIR 时回退到 BASE_DIR)。
Parrot/
├── README.md ← 本文档
├── DESIGN.md ← 设计方案总纲
├── docs/ ← 12 篇 Anthropic 侧设计文档
│ └── openai/ ← 10 篇 OpenAI 扩展设计文档
├── Dockerfile ← 多阶段镜像构建
├── docker-compose.yml ← 默认 compose 模板(GHCR 镜像)
├── docker-entrypoint.sh ← root→app 降权入口
├── .dockerignore
├── deploy.sh ← 一键部署脚本(交互式)
├── .github/workflows/
│ └── docker-publish.yml ← GitHub Actions:push → 构建多架构镜像 → GHCR
├── server.py ← FastAPI 入口
├── requirements.txt
├── data/ ← 运行时持久化(容器挂载点;源码模式不存在)
│ ├── config.json ← 唯一配置文件
│ ├── state.db ← 运行时状态(永久)
│ ├── image_logs.db ← 图片生成/编辑调用日志
│ ├── logs/YYYY-MM.db ← 按月分库业务日志
│ ├── images/ ← 图片缓存(开启后)
│ └── .anthropic_proxy_ids.json ← device_id 持久化
└── src/
├── config.py ← 配置加载/保存/热加载
├── auth.py ← 下游 API Key 验证
├── errors.py ← 标准错误响应
├── state_db.py ← state.db 读写
├── log_db.py ← 按月日志库读写 + 跨月聚合(支持 family 过滤)
├── image_db.py ← 图片调用日志 + 账号尝试统计
├── public_ip.py
├── fingerprint.py ← 会话亲和指纹(按 Anthropic 标准字段归一化)
├── affinity.py
├── scorer.py
├── cooldown.py ← OAuth 渠道带 grace count
├── scheduler.py ← 按 ingress 家族过滤 + 亲和 + 评分
├── failover.py ← 故障转移 + upstream_stream_only SSE 聚合
├── blacklist.py
├── probe.py
├── oauth_manager.py ← 多 OAuth 账户管理(Claude + OpenAI)
├── upstream.py ← httpx client + SSE 工具 + 家族 Builder
├── notifier.py
├── transform/
│ ├── cc_mimicry.py ← Claude CC 伪装(与 cc-proxy 同源)
│ └── standard.py
├── channel/
│ ├── base.py ← upstream_stream_only 抽象
│ ├── oauth_channel.py ← Anthropic OAuth 渠道
│ ├── openai_oauth_channel.py ← OpenAI Codex OAuth 渠道
│ ├── api_channel.py ← Anthropic 协议第三方 API 渠道
│ └── registry.py
├── oauth/
│ └── openai.py ← OpenAI OAuth refresh + 限额头解析
├── openai/ ← OpenAI 协议子树(4700+ 行)
│ ├── handler.py ← chat/completions + responses 入口
│ ├── images_simple.py ← Parrot 简化图片生成/编辑接口
│ ├── store.py ← previous_response_id 本地 store
│ ├── channel/api_channel.py ← OpenAI 兼容第三方 API 渠道
│ └── transform/ ← chat↔responses 双向 SSE 状态机 + guard
└── telegram/
├── bot.py
├── ui.py ← 含 family_of / family_tag helpers
└── menus/
├── main.py
├── status_menu.py ← 两家族分段 + 最快渠道 Top 5
├── stats_menu.py ← 家族化汇总 + 专题 + Key 家族拆分
├── logs_menu.py
├── channel_menu.py
├── oauth_menu.py ← 支持 Claude + OpenAI 双家族管理
├── apikey_menu.py ← API Key 权限 / 图片权限
├── image_menu.py ← 图片生成配置 / 日志 / 缓存查看
├── system_menu.py
└── help_menu.py
用官方 openai SDK(Python 2.32+ / Node 6.34+)端到端跑的测试矩阵:
| 场景 | Python | Node | 备注 |
|---|---|---|---|
| chat.completions 非流式 + 逻辑推理 | ✅ | ✅ | 走 SSE 聚合路径 |
| chat.completions 流式 + 编码题 | ✅ | ✅ | 真正 SSE 透传 |
| responses 非流式 + 多轮 function calling | ✅ | ✅ | 2 轮完成 3 个 tool 调用 |
| responses 流式 + reasoning.effort=medium | ✅ | ✅ | 9 种事件类型全齐 |
| messages 流式 + CC 伪装 (Claude) | ✅ | ✅ | 走 cc-proxy 同源伪装 |
| images/generate 真实生成 | ✅ | - | 走 ChatGPT/Codex image_generation tool |
| images/edit 单图编辑 | ✅ | - | data URL 输入图 + 图片缓存 |
测试脚本见本 repo tests/ 目录。
- error:无启用渠道 → 加至少一个渠道(TG bot「🔀 渠道管理」或「🔐 管理 OAuth」)
- degraded:有渠道但全部冷却 → 「🔀 渠道管理」→「🧹 清全部错误」,或 TG bot 的「🔐 管理 OAuth」→「🧹 清除所有账户错误」
该模型在所有启用渠道里都不存在。检查:
- 模型名拼写
- 渠道是否被禁用 / 配额禁用 / auth_error
- 对 OpenAI OAuth:
gpt-5.2-codex对 ChatGPT 账号(Plus/Pro/Enterprise)不支持,会被自动剔除;这种情况返回 404
该 Key 设了模型白名单但请求模型不在里面。去 TG bot「🔑 管理 API Key」→ 编辑 Key 的允许模型。
该 API Key 没有开启图片权限。去 TG bot「🔑 管理 API Key」→ 点进该 Key →「🖼 允许图片接口」。
没有可用于图片生成的 OpenAI OAuth 账号。检查:
- 是否至少添加了一个 OpenAI OAuth 账号,且账号有
chatgpt_account_id。 - 账号是否被停用、认证失败、配额禁用,或在「🖼 图片生成」里被图片模块单独禁用。
- 账号是否处于图片模块独立冷却中。
「看图 #id」按钮只在以下条件同时满足时显示:
- 图片缓存已开启。
- 该调用成功。
image_logs.db里记录了缓存路径。- 本地缓存文件还没有被保留天数 / 空间上限清理掉。
docker compose logs --tail 50 看最近日志:
Conflict: terminated by other getUpdates request→ 有多个实例在拉同一 botInvalid bot token→ 检查config.json的telegram.botToken
refresh_token 已失效。在 TG bot「🔐 管理 OAuth」→ 点该账户 →「🔄 刷新 Token」;若还是失败则删除后重新添加。
已修复(v0.x 起)。如升级后仍遇到,检查 OAuth 渠道的 upstream_stream_only 属性是否为 True(源码部署场景)。
「📋 最近日志」→ 找到那条 → 点「📄 #N」→ 重试链会显示每次尝试的渠道 + outcome + 错误原因。
项目原名 AnthropicProxy,在支持 OpenAI 之后改名为 Parrot(取自「鹦鹉学舌」,贴切于协议代理的本质)。
- 旧仓库
danger-dream/AnthropicProxy已通过 GitHub 自动跳转到本仓库 - 旧镜像
ghcr.io/danger-dream/anthropicproxy暂时与新镜像并存(7-14 天后下线) - 环境变量
ANTHROPIC_PROXY_DATA_DIR为了向后兼容保持不变;后续会加PARROT_DATA_DIR别名
MIT — 见 LICENSE
{ "listen": { "host": "0.0.0.0", "port": 22122 }, "apiKeys": { "default": { "key": "ccp-xxx", "allowedModels": [], "allowImages": false } }, "oauthAccounts": [ { "email": "xxx@example.com", "provider": "claude", "access_token": "...", "refresh_token": "...", "expired": "..." }, { "email": "yyy@example.com", "provider": "openai", "access_token": "...", "refresh_token": "...", "plan_type": "plus", "chatgpt_account_id": "..." } ], "channels": [ { "name": "智谱 Max", "type": "api", "protocol": "anthropic", "baseUrl": "https://...", "apiKey": "...", "models": [{"real": "GLM-5", "alias": "glm-5"}], "cc_mimicry": true, "enabled": true }, { "name": "OpenAI 3P", "type": "api", "protocol": "openai-responses", "baseUrl": "https://...", "apiKey": "...", "models": [...], "enabled": true }, // 非标准路径上游:baseUrl 只留主机,apiPath 放完整调用路径,运行时 = baseUrl + apiPath { "name": "智谱 Coding", "type": "api", "protocol": "openai-chat", "baseUrl": "https://open.bigmodel.cn", "apiPath": "/api/coding/paas/v4/chat/completions", "apiKey": "...", "models": [...], "enabled": true } ], "images": { "enabled": true, "mainModel": "gpt-5.4-mini", "toolModel": "gpt-image-2", "disabledAccounts": [], "cacheEnabled": false, "cachePath": "images", "cacheRetentionDays": 0, "cacheMaxBytes": 1073741824, "accountCooldownSeconds": 300, "requestTimeoutSeconds": 180, "maxPromptChars": 4000, "maxInputImageBytes": 20971520, "dbPath": "image_logs.db" }, "timeouts": { "connect": 10, "firstByte": 30, "idle": 120, "total": 600 }, "concurrency": { "enabled": true, "queueWaitSeconds": 30, "defaultMaxConcurrent": 0 }, "errorWindows": [1, 3, 5, 10, 15, 0], "oauthGraceCount": 3, "cooldownLadderMinIntervalSeconds": 30, // 阶梯推进最小间隔;防秒级重试把渠道打穿 "cooldownPermanentMinAgeSeconds": 300, // 永久冷却最小累计;防爆发式失败误判为永久 "affinity": { "ttlMinutes": 30, "cleanupIntervalSeconds": 300, "clientTtlMinutes": 120 }, "scoring": { "emaAlpha": 0.25, "recentWindow": 50, "defaultScore": 3000, "errorPenaltyFactor": 8, "staleMinutes": 15, "staleFullDecayMinutes": 30, "explorationRate": 0.2 }, "quotaMonitor": { "enabled": false, "intervalSeconds": 60, "disableThresholdPercent": 95, "resumeThresholdPercent": 95 }, "accessRefreshThrottleSeconds": 180, "modelMapping": { "anthropic": { "claude-new-alias": "claude-sonnet-4-6" }, "openai-chat": { "gpt-5.5": "gpt-5.4" }, "openai-responses": { "gpt-5.5-codex": "gpt-5.4" } }, "ingressDefaultModel": { "anthropic": "claude-sonnet-4-6", "openai-chat": "gpt-5.4", "openai-responses": "gpt-5.4" }, "providers": { "openai": { "forceCodexCLI": true, "enableTLSFingerprint": false, "isolateSessionId": true, "defaultModels": ["gpt-5.2", "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.4", "gpt-5.5"] } }, "notifications": { "enabled": true, "events": { ... } }, "channelSelection": "smart", "loadBalancing": { "initialized": false, "priorityOrders": { "anthropic": [], "openai": [] } }, "cchMode": "disabled", "telegram": { "botToken": "...", "adminIds": [123] } }