{"id":48486830,"url":"https://github.com/doudou-start/airgate-openai","last_synced_at":"2026-05-29T01:03:57.160Z","repository":{"id":341802054,"uuid":"1171516230","full_name":"DouDOU-start/airgate-openai","owner":"DouDOU-start","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-05T03:45:46.000Z","size":889,"stargazers_count":1,"open_issues_count":1,"forks_count":3,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-05T05:34:09.372Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DouDOU-start.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-03T10:12:49.000Z","updated_at":"2026-05-05T03:45:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"a006678e-f675-4cb3-aee0-5cc43477128e","html_url":"https://github.com/DouDOU-start/airgate-openai","commit_stats":null,"previous_names":["doudou-start/airgate-openai"],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/DouDOU-start/airgate-openai","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DouDOU-start%2Fairgate-openai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DouDOU-start%2Fairgate-openai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DouDOU-start%2Fairgate-openai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DouDOU-start%2Fairgate-openai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DouDOU-start","download_url":"https://codeload.github.com/DouDOU-start/airgate-openai/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DouDOU-start%2Fairgate-openai/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32654618,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-07T10:03:17.361Z","updated_at":"2026-05-24T09:04:51.596Z","avatar_url":"https://github.com/DouDOU-start.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eAirGate OpenAI\u003c/h1\u003e\n\n  \u003cp\u003e\u003cstrong\u003eOpenAI / ChatGPT / Anthropic 协议三合一网关插件\u003c/strong\u003e\u003c/p\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"https://github.com/DouDOU-start/airgate-openai/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/DouDOU-start/airgate-openai?style=flat-square\" alt=\"release\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/DouDOU-start/airgate-openai/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/DouDOU-start/airgate-openai/ci.yml?branch=master\u0026style=flat-square\u0026label=CI\" alt=\"ci\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/DouDOU-start/airgate-openai/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/DouDOU-start/airgate-openai?style=flat-square\" alt=\"license\" /\u003e\u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Go-1.25-00ADD8?style=flat-square\u0026logo=go\" alt=\"go\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/React-19-61DAFB?style=flat-square\u0026logo=react\" alt=\"react\" /\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n---\n\nAirGate OpenAI 不是又一个\"OpenAI 转发服务\"，而是 [airgate-core](https://github.com/DouDOU-start/airgate-core) 的旗舰网关插件，也是 [airgate-sdk](https://github.com/DouDOU-start/airgate-sdk) 的官方参考实现。它在一个 gRPC 子进程里同时承载：\n\n- **OpenAI Responses / Chat Completions API** 转发（Codex 核心端点）\n- **ChatGPT OAuth 浏览器授权账号** 接入（PKCE + WebSocket 桥接）\n- **Anthropic Messages API** 协议翻译（Claude → Responses 一步直转）\n\n它解决一个具体问题：**用一套账号池同时服务 OpenAI、Codex CLI、Claude Code 三种客户端**，而不需要在 core 里为每一种协议各塞一份代码。插件可以**独立发版、独立 release、独立装卸、独立热更**，core 不重启、其他插件不受影响。\n\n## ✨ 核心特性\n\n- **🔌 双账号类型** — `apikey`（任何 Responses 兼容服务）与 `oauth`（浏览器登录 ChatGPT，自动刷新 token），插件按账号类型选择上游协议\n- **🔄 Anthropic 协议翻译** — Claude 客户端的 `/v1/messages` 一步直转为 Responses API 请求，SSE 流再回译为 Anthropic 事件，工具调用 / 推理 token / stop_reason 全保留\n- **🌐 双协议入口** — 同一个 `/v1/responses` 同时支持 HTTP/SSE 与 WebSocket；OAuth 账号走 WebSocket 上行，再以 SSE 写回客户端\n- **🎯 模型降级与重试** — Anthropic 转发链路在模型不存在 / 被拒时自动降级到映射表里的下一个候选\n- **🧠 上下文裁剪** — 历史消息超窗时按规则截断，避免上游 400\n- **🪄 系统提示词预设** — 内置 default / simple / nsfw / cc 四套 Codex 提示词，按账号选择\n- **💼 账号前端 Widget** — 自带创建/编辑账号表单（OAuth 引导面板、字段提示、状态展示），由 core 自动嵌入管理后台\n- **📦 一键发版** — git tag 触发 release workflow，矩阵构建 4 个平台（linux/darwin × amd64/arm64），自动注入版本号、上传 sha256\n\n## 🧩 接入位置\n\n```text\n                  ┌──────────────────────────────────────┐\n                  │           AirGate Core               │\n                  │      (账号 / 计费 / 管理后台)        │\n                  └────────────┬─────────────────────────┘\n                               │ go-plugin (gRPC)\n                               ▼\n                  ┌──────────────────────────────────────┐\n                  │      airgate-openai (本仓库)         │\n                  │                                      │\n                  │   ┌──────────┐    ┌──────────────┐   │\n                  │   │ HTTP/SSE │    │  WebSocket   │   │\n                  │   │   入口   │    │     入口     │   │\n                  │   └────┬─────┘    └──────┬───────┘   │\n                  │        ├─ apikey ────────┤           │\n                  │        └─ oauth ─────────┤           │\n                  │                          │           │\n                  │     ┌────────────────────▼────────┐  │\n                  │     │     Anthropic 协议翻译      │  │\n                  │     │ (request convert / decode)  │  │\n                  │     └──────────────┬──────────────┘  │\n                  └────────────────────┼─────────────────┘\n                                       ▼\n                       OpenAI / ChatGPT / 兼容平台\n```\n\n**请求生命周期**：\n\n```text\n客户端请求 ──► Core 鉴权 ──► Plugin.Forward()\n                                                  │\n                                          ┌───────┴───────┐\n                                          ▼               ▼\n                                  Anthropic 翻译     原生 Responses\n                                   (convert)         (forwardAPIKey\n                                          │           / forwardOAuth)\n                                          ▼               │\n                                     上游 AI API ◄────────┘\n                                          │\n                                          ▼\n                                     ForwardResult\n                                  ┌───────┴───────┐\n                              标准用量/成本   账号状态反馈\n                              Core 入库扣费   Core 更新账号\n```\n\n`Forward()` 拿到 core 传入的账号，识别请求是 Anthropic Messages、OpenAI 原生还是 Images API，再分发到 `forwardAPIKey`（HTTP/SSE 直连）或 `forwardOAuth`（WebSocket 桥接）。插件负责协议适配、上游请求和平台标准用量/成本计算，core 负责鉴权、账号选择、入库与按用户倍率扣费。\n\n## 🚦 路由\n\n由 `metadata.go` 声明、`Routes()` 返回，core 启动时自动注册到网关：\n\n| 方法 | 路径 | 说明 |\n|------|------|------|\n| POST | `/v1/responses` | Responses API（Codex 核心端点）|\n| POST | `/v1/chat/completions` | Chat Completions API |\n| POST | `/v1/messages` | Anthropic Messages API（协议翻译）|\n| POST | `/v1/messages/count_tokens` | Anthropic Count Tokens（兼容回退）|\n| GET  | `/v1/models` | 模型列表 |\n| POST | `/v1/images/generations` | Images API（文生图） |\n| POST | `/v1/images/edits` | Images API（图生图 / 编辑） |\n| WS   | `/v1/responses` | Responses API（WebSocket）|\n\n另外提供不带 `/v1` 前缀的别名路由（`POST /responses`、`POST /chat/completions`、`POST /messages`、`GET /models`、`WS /responses` 等），方便客户端直接填站点根地址。\n\n## 🔑 账号类型\n\n| Key | 标签 | 凭证字段 | 适用场景 |\n|---|---|---|---|\n| `apikey` | API Key | `api_key` + `base_url`（可选）| 所有提供 Responses 标准接口的服务 |\n| `oauth`  | OAuth 登录 | `access_token` / `refresh_token` / `chatgpt_account_id`（授权后自动填充）| 浏览器登录 ChatGPT 个人账号 |\n\n账号字段定义同样从 `metadata.go` 派生，通过 `Info()` 上报给 core，前端表单 Widget 自动渲染。\n\n## 🛠 技术栈\n\n| 层 | 技术 |\n|---|---|\n| 后端 | Go 1.25 · gRPC · gjson/sjson（零 struct）· gorilla/websocket |\n| 前端 | React 19 · Vite · TypeScript（账号表单 Widget） |\n| 插件协议 | hashicorp/go-plugin (gRPC) |\n| 上游协议 | OpenAI Responses / Chat Completions · ChatGPT WebSocket · Anthropic Messages |\n| 发布 | GitHub Actions · 矩阵构建 4 平台二进制 · GitHub Release |\n\n## 🚀 安装与开发\n\n### 方式 1：安装到 core（推荐）\n\n打开 core 管理后台 → **插件管理** → 三种方式任选：\n\n```text\n1. 插件市场 → 点击「安装」               （从 GitHub Release 自动拉取，匹配当前架构）\n2. 上传安装 → 拖入二进制文件              （适合内部环境 / 自建二进制）\n3. GitHub 安装 → 输入 DouDOU-start/airgate-openai\n```\n\nmarket 会**定时从 GitHub API 同步**最新 release（默认 6h，使用 ETag 不消耗 API 配额），新 tag push 后通常几分钟内即可在市场看到。\n\n### 方式 2：源码运行（开发）\n\n需要 Go 1.25+、Node 22+，以及兄弟目录 [`airgate-sdk`](https://github.com/DouDOU-start/airgate-sdk) 与 [`airgate-core`](https://github.com/DouDOU-start/airgate-core)：\n\n```bash\ngit clone https://github.com/DouDOU-start/airgate-sdk.git\ngit clone https://github.com/DouDOU-start/airgate-core.git\ngit clone https://github.com/DouDOU-start/airgate-openai.git\ncd airgate-openai\n\nmake install        # 装 web 依赖与 Go 模块\nmake build          # 完整构建：web/dist → backend/webdist → bin/gateway-openai\nmake manifest       # 重新生成 plugin.yaml\nmake ci             # 与 CI 完全一致的本地检查（lint + test + vet + build）\n```\n\n把本插件以 dev 模式挂到 core，热重载不重启 core：\n\n```yaml\n# airgate-core/backend/config.yaml\nplugins:\n  dev:\n    - name: gateway-openai\n      path: /absolute/path/to/airgate-openai/backend\n```\n\n然后 `cd airgate-core/backend \u0026\u0026 go run ./cmd/server`，core 会通过 `go run .` 启动本插件，握手 gRPC，依次调用 `Init → Start → RegisterRoutes`。\n\n### 方式 3：不依赖 core 的端到端调试\n\n```bash\ncd backend \u0026\u0026 go run ./cmd/devserver   # 启动本地 devserver（模拟 core）\ncd backend \u0026\u0026 go run ./cmd/chat        # 启动交互式测试客户端（SSE / WS 双协议）\n```\n\n更多命令见 `make help`。\n\n## 🔄 Anthropic 协议翻译\n\n```text\nAnthropic JSON 请求\n  → anthropic_convert.go    一步直转为 Responses API JSON（保留工具、reasoning、system）\n  → anthropic_forward.go    转发到上游（含模型降级重试）\n  → anthropic_response.go   Responses SSE → Anthropic SSE 回译\n  → anthropic_model_map.go  Claude ↔ OpenAI 模型映射表\n  → anthropic_util.go       工具名缩短、stop_reason 转换\n```\n\n设计上避开\"先把 Anthropic 转成 Chat Completions 再转 Responses\"的两步走 —— 直接一步转换，零中间结构体，全部用 gjson/sjson 操作 JSON。\n\n## 🏗 项目结构\n\n```text\nairgate-openai/\n├── backend/                              # Go 后端（插件主体）\n│   ├── main.go                           # gRPC 插件入口\n│   ├── cmd/\n│   │   ├── chat/                         # 交互式测试客户端（SSE / WS 双协议）\n│   │   ├── devserver/                    # 开发服务器（模拟 core）\n│   │   └── genmanifest/                  # plugin.yaml 生成器\n│   └── internal/\n│       ├── gateway/                      # 网关核心逻辑\n│       │   ├── gateway.go                # GatewayPlugin 接口实现\n│       │   ├── metadata.go               # 插件元信息（运行时单源）\n│       │   ├── forward.go                # 三模式转发分发 + apikey/oauth 转发\n│       │   ├── anthropic_convert.go      # Anthropic → Responses 请求一步直转\n│       │   ├── anthropic_response.go     # Responses → Anthropic 响应回译\n│       │   ├── anthropic_forward.go      # Anthropic 转发入口、模型降级重试\n│       │   ├── anthropic_model_map.go    # Claude ↔ OpenAI 模型映射\n│       │   ├── anthropic_count_tokens.go # count_tokens 兼容回退\n│       │   ├── anthropic_context_guard.go# Anthropic 历史裁剪\n│       │   ├── request.go                # 请求检测、URL 构建、预处理\n│       │   ├── stream.go                 # SSE 流式响应处理\n│       │   ├── ws.go / ws_handler.go     # WebSocket 连接与事件解析\n│       │   ├── transport_pool.go         # HTTP transport 复用池\n│       │   ├── headers.go                # 认证头、白名单、Codex 标识\n│       │   ├── oauth.go / oauth_handler.go # OAuth 授权流程（PKCE）\n│       │   └── assets.go                 # WebAssetsProvider，embed webdist\n│       ├── model/registry.go             # 集中模型规格定义（含单价）\n│       └── resources/                    # 嵌入资源（系统提示词预设）\n├── web/                                  # 前端（账号表单 Widget）\n│   └── src/components/AccountForm.tsx\n├── .github/workflows/\n│   ├── ci.yml                            # push/PR 触发，复用 make ci\n│   └── release.yml                       # v* tag 触发，矩阵构建 4 平台二进制\n├── plugin.yaml                           # genmanifest 自动生成\n└── Makefile\n```\n\n## 🔧 设计要点\n\n- **`metadata.go` 是运行时真相**，`plugin.yaml` 仅为分发产物（`make manifest` 重生）。账号表单、路由、模型列表、依赖声明全部从 `metadata.go` 派生\n- **零 struct JSON 处理** —— 全程使用 gjson/sjson；上游 schema 经常变，零 struct 让兼容性维护成本最低\n- **Anthropic 翻译只做单向**：请求 Anthropic → Responses，响应 Responses → Anthropic，不引入第三种中间格式\n- **transport 复用**：HTTP transport 由 `transport_pool` 按 base_url 分桶，避免每次都新建连接\n- **版本单一来源**：`PluginVersion` 是 `var`，发版时由 `-ldflags` 在编译期注入 git tag —— git tag = release 版本 = 已安装 tab 显示的版本，永不偏离\n\n## 📦 发版\n\n正式发版**只需要打 git tag，不要手工改版本号字段**：\n\n```bash\ngit tag v0.2.0\ngit push origin v0.2.0\n```\n\n[release.yml](.github/workflows/release.yml) 会自动：\n\n1. 矩阵构建 4 个平台二进制（linux/darwin × amd64/arm64）\n2. 通过 `-ldflags \"-X .../gateway.PluginVersion=${version}\"` 把 git tag（去掉 `v` 前缀）注入到二进制\n3. 上传到 GitHub Release，资产命名 `gateway-openai-{os}-{arch}`，附带 `.sha256`\n4. airgate-core 插件市场会通过 GitHub API 自动同步新版本\n\n## 🤝 贡献 / 反馈\n\n- Bug / Feature: [Issues](https://github.com/DouDOU-start/airgate-openai/issues)\n- 主仓库: [airgate-core](https://github.com/DouDOU-start/airgate-core)\n- 插件 SDK: [airgate-sdk](https://github.com/DouDOU-start/airgate-sdk)\n\n## 📜 License\n\nMIT — 详见 [LICENSE](LICENSE)。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoudou-start%2Fairgate-openai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoudou-start%2Fairgate-openai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoudou-start%2Fairgate-openai/lists"}