将 Rust 版上游可用模型抓取逻辑收敛到 Python 版行为,统一后台自动抓模 与管理员 provider-query 的模型发现路径,消除标准 /models、固定模型目录、 Antigravity、Vertex AI 等 provider 在两端实现上的分叉。 核心变更: - 在 aether-model-fetch 中引入统一抓模策略层 - 覆盖标准 /models、Vertex API Key、Vertex Service Account、 Antigravity fetchAvailableModels、固定模型目录五类抓模路径 - 将 provider-query 与后台自动抓模都切换到共享抓模入口,避免重复拼接 URL、headers 和 provider 特判逻辑 标准模型抓取对齐: - 按 Python 语义调整抓模优先级: openai:chat > openai:cli > openai:compact claude:chat > claude:cli gemini:chat > gemini:cli - 从抓模候选中移除 openai:responses - 为 openai:cli/openai:compact、claude:cli、gemini:* 补齐 Python 同款 User-Agent / 浏览器指纹请求头 - Claude 抓模保留 after_id 分页语义 - Gemini 抓模统一为 v1beta/models?key=... 语义 provider-query 对齐: - 返回结果改为按 model id 聚合,并合并/排序 api_formats - 最终模型列表按 model id 排序,行为与 Python 保持一致 - 固定目录 provider(codex/kiro/claude_code/gemini_cli)不再依赖活跃 endpoint,即使无 endpoint 也能返回预设模型目录 - Antigravity 多 key 查询改为按账户可用性 + tier 排序,首个成功结果即 停止,并接入 provider 级缓存 - 仅配置 openai:responses 的 provider 不再被视为抓模成功路径 自动抓模对齐: - 自动抓模成功时写入 allowed_models、upstream_models cache,并同步 upstream_metadata - upstream_metadata 合并逻辑对齐 Python,对 quota_by_model 做模型级合并, 并保留已有 reset_time - 自动抓模失败时不覆盖已有 allowed_models - 固定目录 provider 在无 endpoint 场景下也可成功更新 allowed_models Antigravity 对齐: - 使用 POST /v1internal:fetchAvailableModels 抓取可用模型 - 按 Python 规则处理 URL fallback 和 429/404/408/5xx fallback 状态 - 强制要求 auth_config.project_id - 过滤 Python 黑名单模型 - 解析并持久化 upstream_metadata.antigravity.quota_by_model Vertex AI 对齐: - API Key 模式仅抓取 publishers/google/models - Service Account 模式新增 JWT token exchange,并按 Python region 顺序 抓取 google + anthropic publishers - 模型 owned_by / display_name / api_format 推断与 Python 对齐 - 软 404 处理行为与 Python 收敛 Gemini CLI / 固定目录对齐: - Gemini CLI 改为返回 Python 预设模型目录 - 在可用时通过 loadCodeAssist 补充 plan_type/project_id 元数据 - Codex/Kiro/Claude Code 改为共享固定模型目录实现 测试: - 扩展 aether-model-fetch 单元测试,覆盖格式优先级、openai:responses 排除、 请求头、Claude 分页、Gemini query auth、固定目录与 metadata 合并 - 调整 provider-query 控制面测试到 Python 语义 - 新增自动抓模运行时测试,覆盖固定目录成功、Antigravity metadata 合并、 失败保留旧 allowed_models 验证: - cargo nextest run -p aether-model-fetch --lib - cargo nextest run -p aether-gateway control::admin::provider_query model_fetch::runtime::tests
Aether
一站式 AI 基础设施平台
支持 Claude / OpenAI / Gemini 及其 CLI 客户端的统一接入、格式转换、正/反向代理, 致力于成为用户驱动AI服务的底座
简介
Aether 是一个自托管的 AI API 网关,为团队和个人提供多租户管理、智能负载均衡、成本配额控制和健康监控能力。通过统一的 API 入口,可以无缝对接 Claude、OpenAI、Gemini 等主流 AI 服务及其 CLI 工具。
页面预览: https://fawney19.github.io/Aether/
部署
Docker Compose(推荐:预构建镜像)
# 1. 克隆代码
git clone https://github.com/fawney19/Aether.git
cd Aether
# 2. 配置环境变量
cp .env.example .env
./generate_keys.sh # 生成密钥, 并将生成的密钥填入 .env
# 3. 部署 / 更新(自动执行数据库迁移)
docker compose pull && docker compose up -d
# 4. 升级前备份 (可选)
docker compose exec postgres pg_dump -U postgres aether | gzip > backup_$(date +%Y%m%d_%H%M%S).sql.gz
Docker Compose(本地构建镜像)
# 1. 克隆代码
git clone https://github.com/fawney19/Aether.git
cd Aether
# 2. 配置环境变量
cp .env.example .env
./generate_keys.sh # 生成密钥, 并将生成的密钥填入 .env
# 3. 部署 / 更新(自动构建、启动、迁移)
git pull
./deploy.sh
本地开发
# 启动依赖
docker compose -f docker-compose.build.yml up -d postgres redis
# 后端
./dev.sh
# 前端
cd frontend && npm install && npm run dev
./dev.sh 现在只保留一种本地模式:
| 角色 | 本地地址 | 说明 |
|---|---|---|
| Rust frontdoor | 默认 http://localhost:8084 |
aether-gateway,本地唯一公开入口;实际端口由 APP_PORT 控制 |
本地默认链路是:
client -> rust frontdoor (aether-gateway) -> execution_runtime/provider transport
其中:
aether-gateway负责公开入口、健康检查、格式转换、本地执行 runtime,以及当前已迁到 Rust 的 frontdoor/control/background 路径。./dev.sh不再启动 Python 宿主;未下沉到 Rust 的 legacy 路由会直接失败。./dev.sh默认把AETHER_GATEWAY_VIDEO_TASK_TRUTH_SOURCE_MODE设为rust-authoritative,避免本地还依赖 Python sync report 语义。
Aether Proxy (可选)
Aether Proxy 是配套的正向代理节点,部署在海外 VPS 上,为墙内的 Aether 实例中转 API 流量。或者部署在其他服务器为指定的提供商、账号、Key使用不同的节点访问。支持 TUI 向导一键配置、systemd 服务管理、TLS 加密、DNS 缓存及连接池调优。
- Docker Compose 部署或下载预编译二进制直接运行
- 通过
aether-proxy setup完成交互式配置,自动注册为系统服务 - 详细文档见 apps/aether-proxy/README.md
环境变量
部署建议直接参考对应示例文件:
- Docker Compose:根目录
.env.example - systemd 二进制部署:deploy/systemd/aether-gateway.env.example
当前主链路真正要关注的是这组变量:
APP_PORT:aether-gateway唯一监听端口,固定绑定0.0.0.0:${APP_PORT}DATABASE_URL/REDIS_URL:aether-gateway直接读取的共享后端连接串JWT_SECRET_KEY/ENCRYPTION_KEY:认证和敏感数据加密所需密钥API_KEY_PREFIX:用户和管理员新建 API Key 时使用的前缀,默认skPAYMENT_CALLBACK_SECRET:支付回调公开入口的共享密钥;未配置时相关路由保持禁用ADMIN_USERNAME/ADMIN_PASSWORD/ADMIN_EMAIL:首次启动时自举首个本地管理员CORS_ORIGINS/CORS_ALLOW_CREDENTIALS:前端跨域来源控制;如果要跨域带登录 Cookie,CORS_ORIGINS不能写*AETHER_GATEWAY_DEPLOYMENT_TOPOLOGY=single-node|multi-nodeAETHER_GATEWAY_NODE_ROLE=all|frontdoor|backgroundRUST_LOG:Rust 日志过滤,例如aether_gateway=info、aether_gateway=debug,sqlx=warn- 如果使用仓库内置的数据栈 compose,再额外配置
DB_PASSWORD/REDIS_PASSWORD
systemd 的 .env 必须保持简单 KEY=VALUE 形式,不要写 export、${VAR} 或命令替换。
Q&A
Q: 如何开启/关闭请求体记录?
管理员在 系统设置 中配置日志记录的详细程度:
| 级别 | 记录内容 |
|---|---|
| Base | 基本请求信息 |
| Headers | Base + 请求头 |
| Full | Headers + 请求体 |
Q: 更新出问题如何回滚?
有备份的情况(推荐):
# Docker Compose:
# 1. 切回旧镜像 tag / digest
# 2. 恢复 Postgres 备份
# 3. 再启动 app
# systemd:
# 1. 把 /opt/aether/current 切回旧 release
# 2. systemctl restart aether-gateway
# 3. 如果升级包含数据库结构变更,再恢复 Postgres 备份
可以在升级前通过
docker inspect ghcr.io/fawney19/aether:latest --format '{{index .RepoDigests 0}}'记录当前镜像 digest,方便回滚时使用。
没有备份的情况:
当前不应该再依赖旧的 alembic downgrade 路线。aether-gateway 启动时执行的是 Rust / sqlx 迁移;如果本次发布带来了不可逆的数据结构变化,没有备份就不能保证安全回滚。因此升级前强烈建议先备份 Postgres。
许可证
本项目采用 Aether 非商业开源许可证。允许个人学习、教育研究、非盈利组织及企业内部非盈利性质的使用;禁止用于盈利目的。商业使用请联系获取商业许可。

