diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..10a1222 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +.git/ +.github/ +target/ +data/ +config/config.toml +.emrg/ +docs/ +*.md +.DS_Store diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..2514fba --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,50 @@ +name: Docker Publish + +on: + push: + branches: [main] + tags: ['v*'] + +env: + IMAGE_NAME: ghcr.io/${{ github.repository }} + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=tag + type=sha,prefix=,format=short + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Cargo.lock b/Cargo.lock index 817bb67..f6f3d28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,7 +60,7 @@ dependencies = [ [[package]] name = "aitokenpool" -version = "0.5.0" +version = "0.5.1" dependencies = [ "aes-gcm", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index e85b266..5489031 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aitokenpool" -version = "0.5.0" +version = "0.5.1" edition = "2021" description = "AI Token 共享池 — 企业 key 池 + 公共共享市场" license = "MIT" diff --git a/README.md b/README.md index 203061e..c80a163 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ AITokenPool 是一个开源的 **AI Token 共享平台**:企业版(内部 ke ## 状态 -后端 + 前端已全部实现,当前版本 **v0.5.0**(102/102 测试全绿): +后端 + 前端已全部实现,当前版本 **v0.5.1**(102/102 测试全绿): - ✅ **P0-A(v0.2.0)**:后端骨架 + TOML 配置(`Config::validate`:points_per_unit>0 / plan→provider 存在 / endpoints≥1 / protocol 枚举)+ SQLite 数据层(幂等迁移 v4 + demo/admin/ops 种子)+ 认证(argon2 + Bearer API Key)+ API Key 端点 - ✅ **P0-B(v0.2.1)**:网关转发(OpenAI Chat Completions + Anthropic Messages)+ 路由故障转移(粘性 / 健康冷却 / 3 次切换上限)+ 计量账本(点数计算、90/10 分成、事务性 settle) @@ -29,6 +29,7 @@ AITokenPool 是一个开源的 **AI Token 共享平台**:企业版(内部 ke - ✅ **P3-A(v0.4.0)**:网关三协议互转——OpenAI Chat / OpenAI Responses / Anthropic 任一端点可调用只暴露其他协议的 plan(自动转换,同协议透传零损耗)+ 新增 `/v1/responses` 端点 - ✅ **P3-A 补充(v0.4.1)**:`GET /v1/models` OpenAI 兼容模型列表(认证可选,带 Bearer 附加 available_keys;`/models` 别名) - ✅ **P3-B(v0.5.0)**:流式 SSE 跨协议转换——openai/anthropic/responses 任意协议的 `stream:true` 请求可转发到任意协议上游,响应流事件实时互转(openai delta ↔ anthropic content_block_delta ↔ responses output_text.delta,含工具调用/thinking 增量与流内 usage 计量;responses→anthropic 流式暂延后) +- ✅ **发布(v0.5.1)**:GitHub Actions Docker 发布——`main` push / `v*` tag 自动构建推送 GHCR 镜像 `ghcr.io/argszero/aitokenpool`(buildx + gha 缓存) `ui/` 已由纯静态原型升级为**对接真实 API**(登录、钱包、市场、共享、交易、设置、管理、运营全部真实数据),由后端 `ServeDir` 静态托管,无需单独部署前端。 @@ -52,6 +53,8 @@ docker compose up -d --build # 构建 + 启动 open http://localhost:8080/ # 浏览器访问 ``` +> 已发布镜像:`docker pull ghcr.io/argszero/aitokenpool:latest` + > ⚠️ **生产必须设置 `ATP_MASTER_KEY`**(32 字节 hex 主密钥,用于加密上游 key): > > ```bash @@ -71,7 +74,7 @@ open http://localhost:8080/ # 浏览器访问 ## API 端点(Bearer 认证) -- `GET /healthz` → `{"status":"ok","version":"0.5.0"}` +- `GET /healthz` → `{"status":"ok","version":"0.5.1"}` - `POST /api/auth/login` → `{api_key}`;`GET /api/me` → `{id,email,name,role}` - `POST|GET /api/api-keys`(key 脱敏 `atk_live_****xxxx`);`DELETE /api/api-keys/:id`(撤销) - `POST /v1/chat/completions` / `POST /anthropic/v1/messages` / `POST /v1/responses`(网关,三协议互转,非流式 + 流式 SSE 跨协议转换);`GET /v1/models`(OpenAI 兼容模型列表,认证可选)