diff --git a/API.en.md b/API.en.md index 0767f49..2b18d89 100644 --- a/API.en.md +++ b/API.en.md @@ -15,6 +15,7 @@ This document describes the actual behavior of the current Go codebase. - [Health Endpoints](#health-endpoints) - [OpenAI-Compatible API](#openai-compatible-api) - [Claude-Compatible API](#claude-compatible-api) +- [Gemini-Compatible API](#gemini-compatible-api) - [Admin API](#admin-api) - [Error Payloads](#error-payloads) - [cURL Examples](#curl-examples) @@ -56,7 +57,7 @@ For Vercel one-click bootstrap, you can set only `DS2API_ADMIN_KEY` first, then ## Authentication -### Business Endpoints (`/v1/*`, `/anthropic/*`) +### Business Endpoints (`/v1/*`, `/anthropic/*`, `/v1beta/models/*`) Two header formats accepted: @@ -97,11 +98,24 @@ Two header formats accepted: | GET | `/anthropic/v1/models` | None | Claude model list | | POST | `/anthropic/v1/messages` | Business | Claude messages | | POST | `/anthropic/v1/messages/count_tokens` | Business | Claude token counting | +| POST | `/v1/messages` | Business | Claude shortcut path | +| POST | `/messages` | Business | Claude shortcut path | +| POST | `/v1/messages/count_tokens` | Business | Claude token counting shortcut | +| POST | `/messages/count_tokens` | Business | Claude token counting shortcut | +| POST | `/v1beta/models/{model}:generateContent` | Business | Gemini non-stream | +| POST | `/v1beta/models/{model}:streamGenerateContent` | Business | Gemini stream | +| POST | `/v1/models/{model}:generateContent` | Business | Gemini non-stream compat path | +| POST | `/v1/models/{model}:streamGenerateContent` | Business | Gemini stream compat path | | POST | `/admin/login` | None | Admin login | | GET | `/admin/verify` | JWT | Verify admin JWT | | GET | `/admin/vercel/config` | Admin | Read preconfigured Vercel creds | | GET | `/admin/config` | Admin | Read sanitized config | | POST | `/admin/config` | Admin | Update config | +| GET | `/admin/settings` | Admin | Read runtime settings | +| PUT | `/admin/settings` | Admin | Update runtime settings (hot reload) | +| POST | `/admin/settings/password` | Admin | Update admin password and invalidate old JWTs | +| POST | `/admin/config/import` | Admin | Import config (merge/replace) | +| GET | `/admin/config/export` | Admin | Export full config (`config`/`json`/`base64`) | | POST | `/admin/keys` | Admin | Add API key | | DELETE | `/admin/keys/{key}` | Admin | Delete API key | | GET | `/admin/accounts` | Admin | Paginated account list | @@ -115,6 +129,8 @@ Two header formats accepted: | POST | `/admin/vercel/sync` | Admin | Sync config to Vercel | | GET | `/admin/vercel/status` | Admin | Vercel sync status | | GET | `/admin/export` | Admin | Export config JSON/Base64 | +| GET | `/admin/dev/captures` | Admin | Read local packet-capture entries | +| DELETE | `/admin/dev/captures` | Admin | Clear local packet-capture entries | --- @@ -348,6 +364,8 @@ Business auth required. Returns OpenAI-compatible embeddings shape. ## Claude-Compatible API +Besides `/anthropic/v1/*`, DS2API also supports shortcut paths: `/v1/messages`, `/messages`, `/v1/messages/count_tokens`, `/messages/count_tokens`. + ### `GET /anthropic/v1/models` No auth required. @@ -471,6 +489,37 @@ data: {"type":"message_stop"} --- +## Gemini-Compatible API + +Supported paths: + +- `/v1beta/models/{model}:generateContent` +- `/v1beta/models/{model}:streamGenerateContent` +- `/v1/models/{model}:generateContent` (compat path) +- `/v1/models/{model}:streamGenerateContent` (compat path) + +Authentication is the same as other business routes (`Authorization: Bearer ` or `x-api-key`). + +### `POST /v1beta/models/{model}:generateContent` + +Request body accepts Gemini-style `contents` / `tools`. Model names can use aliases and are mapped to DeepSeek models. + +Response uses Gemini-compatible fields, including: + +- `candidates[].content.parts[].text` +- `candidates[].content.parts[].functionCall` (when tool call is produced) +- `usageMetadata` (`promptTokenCount` / `candidatesTokenCount` / `totalTokenCount`) + +### `POST /v1beta/models/{model}:streamGenerateContent` + +Returns SSE (`text/event-stream`), each chunk as `data: `: + +- regular text: incremental text chunks +- `tools` mode: buffered and emitted as `functionCall` at finalize phase +- final chunk: includes `finishReason: "STOP"` and `usageMetadata` + +--- + ## Admin API ### `POST /admin/login` @@ -567,6 +616,51 @@ Updatable fields: `keys`, `accounts`, `claude_mapping`. } ``` +### `GET /admin/settings` + +Reads runtime settings and status, including: + +- `admin` (JWT expiry, default-password warning, etc.) +- `runtime` (`account_max_inflight`, `account_max_queue`, `global_max_inflight`) +- `toolcall` / `responses` / `embeddings` +- `claude_mapping` / `model_aliases` +- `env_backed`, `needs_vercel_sync` + +### `PUT /admin/settings` + +Hot-updates runtime settings. Supported fields: + +- `admin.jwt_expire_hours` +- `runtime.account_max_inflight` / `runtime.account_max_queue` / `runtime.global_max_inflight` +- `toolcall.mode` / `toolcall.early_emit_confidence` +- `responses.store_ttl_seconds` +- `embeddings.provider` +- `claude_mapping` +- `model_aliases` + +### `POST /admin/settings/password` + +Updates admin password and invalidates existing JWTs. + +Request example: + +```json +{"new_password":"your-new-password"} +``` + +### `POST /admin/config/import` + +Imports full config with: + +- `mode=merge` (default) +- `mode=replace` + +The request can send config directly, or wrapped as `{"config": {...}, "mode":"merge"}`. + +### `GET /admin/config/export` + +Exports full config in three forms: `config`, `json`, and `base64`. + ### `POST /admin/keys` ```json @@ -774,6 +868,23 @@ Or manual deploy required: } ``` +### `GET /admin/dev/captures` + +Reads local packet-capture status and recent entries (Admin auth required): + +- `enabled` +- `limit` +- `max_body_bytes` +- `items` + +### `DELETE /admin/dev/captures` + +Clears packet-capture entries: + +```json +{"success":true,"detail":"capture logs cleared"} +``` + --- ## Error Payloads @@ -793,6 +904,18 @@ Compatible routes (`/v1/*`, `/anthropic/*`) use the same error envelope: Admin routes keep `{"detail":"..."}`. +Gemini routes use Google-style errors: + +```json +{ + "error": { + "code": 400, + "message": "invalid json", + "status": "INVALID_ARGUMENT" + } +} +``` + Clients should handle HTTP status code plus `error` / `detail` fields. **Common status codes**: @@ -899,6 +1022,38 @@ curl http://localhost:5001/v1/chat/completions \ }' ``` +### Gemini Non-Stream + +```bash +curl "http://localhost:5001/v1beta/models/gemini-2.5-pro:generateContent" \ + -H "Authorization: Bearer your-api-key" \ + -H "Content-Type: application/json" \ + -d '{ + "contents": [ + { + "role": "user", + "parts": [{"text": "Introduce Go in three sentences"}] + } + ] + }' +``` + +### Gemini Stream + +```bash +curl "http://localhost:5001/v1beta/models/gemini-2.5-flash:streamGenerateContent" \ + -H "Authorization: Bearer your-api-key" \ + -H "Content-Type: application/json" \ + -d '{ + "contents": [ + { + "role": "user", + "parts": [{"text": "Write a short summary"}] + } + ] + }' +``` + ### Claude Non-Stream ```bash diff --git a/API.md b/API.md index c102b53..0647c4e 100644 --- a/API.md +++ b/API.md @@ -15,6 +15,7 @@ - [健康检查](#健康检查) - [OpenAI 兼容接口](#openai-兼容接口) - [Claude 兼容接口](#claude-兼容接口) +- [Gemini 兼容接口](#gemini-兼容接口) - [Admin 接口](#admin-接口) - [错误响应格式](#错误响应格式) - [cURL 示例](#curl-示例) @@ -56,7 +57,7 @@ Vercel 一键部署可先只填 `DS2API_ADMIN_KEY`,部署后在 `/admin` 导 ## 鉴权规则 -### 业务接口(`/v1/*`、`/anthropic/*`) +### 业务接口(`/v1/*`、`/anthropic/*`、`/v1beta/models/*`) 支持两种传参方式: @@ -97,11 +98,24 @@ Vercel 一键部署可先只填 `DS2API_ADMIN_KEY`,部署后在 `/admin` 导 | GET | `/anthropic/v1/models` | 无 | Claude 模型列表 | | POST | `/anthropic/v1/messages` | 业务 | Claude 消息接口 | | POST | `/anthropic/v1/messages/count_tokens` | 业务 | Claude token 计数 | +| POST | `/v1/messages` | 业务 | Claude 消息快捷路径 | +| POST | `/messages` | 业务 | Claude 消息快捷路径 | +| POST | `/v1/messages/count_tokens` | 业务 | Claude token 计数快捷路径 | +| POST | `/messages/count_tokens` | 业务 | Claude token 计数快捷路径 | +| POST | `/v1beta/models/{model}:generateContent` | 业务 | Gemini 非流式 | +| POST | `/v1beta/models/{model}:streamGenerateContent` | 业务 | Gemini 流式 | +| POST | `/v1/models/{model}:generateContent` | 业务 | Gemini 非流式兼容路径 | +| POST | `/v1/models/{model}:streamGenerateContent` | 业务 | Gemini 流式兼容路径 | | POST | `/admin/login` | 无 | 管理登录 | | GET | `/admin/verify` | JWT | 校验管理 JWT | | GET | `/admin/vercel/config` | Admin | 读取 Vercel 预配置 | | GET | `/admin/config` | Admin | 读取配置(脱敏) | | POST | `/admin/config` | Admin | 更新配置 | +| GET | `/admin/settings` | Admin | 读取运行时设置 | +| PUT | `/admin/settings` | Admin | 更新运行时设置(热更新) | +| POST | `/admin/settings/password` | Admin | 更新 Admin 密码并使旧 JWT 失效 | +| POST | `/admin/config/import` | Admin | 导入配置(merge/replace) | +| GET | `/admin/config/export` | Admin | 导出完整配置(含 `config`/`json`/`base64`) | | POST | `/admin/keys` | Admin | 添加 API key | | DELETE | `/admin/keys/{key}` | Admin | 删除 API key | | GET | `/admin/accounts` | Admin | 分页账号列表 | @@ -115,6 +129,8 @@ Vercel 一键部署可先只填 `DS2API_ADMIN_KEY`,部署后在 `/admin` 导 | POST | `/admin/vercel/sync` | Admin | 同步配置到 Vercel | | GET | `/admin/vercel/status` | Admin | Vercel 同步状态 | | GET | `/admin/export` | Admin | 导出配置 JSON/Base64 | +| GET | `/admin/dev/captures` | Admin | 查看本地抓包记录 | +| DELETE | `/admin/dev/captures` | Admin | 清空本地抓包记录 | --- @@ -348,6 +364,8 @@ data: [DONE] ## Claude 兼容接口 +除标准路径 `/anthropic/v1/*` 外,还支持快捷路径 `/v1/messages`、`/messages`、`/v1/messages/count_tokens`、`/messages/count_tokens`。 + ### `GET /anthropic/v1/models` 无需鉴权。 @@ -471,6 +489,37 @@ data: {"type":"message_stop"} --- +## Gemini 兼容接口 + +支持路径: + +- `/v1beta/models/{model}:generateContent` +- `/v1beta/models/{model}:streamGenerateContent` +- `/v1/models/{model}:generateContent`(兼容路径) +- `/v1/models/{model}:streamGenerateContent`(兼容路径) + +鉴权方式同业务接口(`Authorization: Bearer ` 或 `x-api-key`)。 + +### `POST /v1beta/models/{model}:generateContent` + +请求体兼容 Gemini `contents` / `tools` 字段,模型名可用 alias 自动映射到 DeepSeek 模型。 + +响应为 Gemini 兼容结构,核心字段包括: + +- `candidates[].content.parts[].text` +- `candidates[].content.parts[].functionCall`(工具调用时) +- `usageMetadata`(`promptTokenCount` / `candidatesTokenCount` / `totalTokenCount`) + +### `POST /v1beta/models/{model}:streamGenerateContent` + +返回 SSE(`text/event-stream`),每个 chunk 为一条 `data: `: + +- 常规文本:持续返回增量文本 chunk +- `tools` 场景:会缓冲并在结束时输出 `functionCall` 结构 +- 结束 chunk:包含 `finishReason: "STOP"` 与 `usageMetadata` + +--- + ## Admin 接口 ### `POST /admin/login` @@ -567,6 +616,51 @@ data: {"type":"message_stop"} } ``` +### `GET /admin/settings` + +读取运行时设置与状态,返回: + +- `admin`(JWT 过期、默认密码告警等) +- `runtime`(`account_max_inflight`、`account_max_queue`、`global_max_inflight`) +- `toolcall` / `responses` / `embeddings` +- `claude_mapping` / `model_aliases` +- `env_backed`、`needs_vercel_sync` + +### `PUT /admin/settings` + +热更新运行时设置。支持更新: + +- `admin.jwt_expire_hours` +- `runtime.account_max_inflight` / `runtime.account_max_queue` / `runtime.global_max_inflight` +- `toolcall.mode` / `toolcall.early_emit_confidence` +- `responses.store_ttl_seconds` +- `embeddings.provider` +- `claude_mapping` +- `model_aliases` + +### `POST /admin/settings/password` + +更新管理密码并使旧 JWT 失效。 + +请求示例: + +```json +{"new_password":"your-new-password"} +``` + +### `POST /admin/config/import` + +导入完整配置,支持: + +- `mode=merge`(默认) +- `mode=replace` + +请求可直接传配置对象,或使用 `{"config": {...}, "mode":"merge"}` 包裹格式。 + +### `GET /admin/config/export` + +导出完整配置,返回 `config`、`json`、`base64` 三种格式。 + ### `POST /admin/keys` ```json @@ -774,6 +868,23 @@ data: {"type":"message_stop"} } ``` +### `GET /admin/dev/captures` + +查看本地抓包状态与最近记录(需 Admin 鉴权): + +- `enabled` +- `limit` +- `max_body_bytes` +- `items` + +### `DELETE /admin/dev/captures` + +清空抓包记录,返回: + +```json +{"success":true,"detail":"capture logs cleared"} +``` + --- ## 错误响应格式 @@ -793,6 +904,18 @@ data: {"type":"message_stop"} Admin 接口保持 `{"detail":"..."}`。 +Gemini 路由使用 Google 风格错误结构: + +```json +{ + "error": { + "code": 400, + "message": "invalid json", + "status": "INVALID_ARGUMENT" + } +} +``` + 建议客户端处理逻辑:检查 HTTP 状态码 + 解析 `error` 或 `detail` 字段。 **常见状态码**: @@ -899,6 +1022,38 @@ curl http://localhost:5001/v1/chat/completions \ }' ``` +### Gemini 非流式 + +```bash +curl "http://localhost:5001/v1beta/models/gemini-2.5-pro:generateContent" \ + -H "Authorization: Bearer your-api-key" \ + -H "Content-Type: application/json" \ + -d '{ + "contents": [ + { + "role": "user", + "parts": [{"text": "用三句话介绍 Go 语言"}] + } + ] + }' +``` + +### Gemini 流式 + +```bash +curl "http://localhost:5001/v1beta/models/gemini-2.5-flash:streamGenerateContent" \ + -H "Authorization: Bearer your-api-key" \ + -H "Content-Type: application/json" \ + -d '{ + "contents": [ + { + "role": "user", + "parts": [{"text": "写一个简短摘要"}] + } + ] + }' +``` + ### Claude 非流式 ```bash diff --git a/CONTRIBUTING.en.md b/CONTRIBUTING.en.md index 212cbb7..156b025 100644 --- a/CONTRIBUTING.en.md +++ b/CONTRIBUTING.en.md @@ -82,8 +82,8 @@ Manually build WebUI to `static/admin/`: ## Running Tests ```bash -# Go unit tests -go test ./... +# Go + Node unit tests (recommended) +./tests/scripts/run-unit-all.sh # End-to-end live tests (real accounts) ./tests/scripts/run-live.sh @@ -104,13 +104,20 @@ ds2api/ │ ├── account/ # Account pool and concurrency queue │ ├── adapter/ │ │ ├── openai/ # OpenAI adapter -│ │ └── claude/ # Claude adapter +│ │ ├── claude/ # Claude adapter +│ │ └── gemini/ # Gemini adapter │ ├── admin/ # Admin API handlers │ ├── auth/ # Auth and JWT +│ ├── claudeconv/ # Claude message conversion +│ ├── compat/ # Compatibility helpers │ ├── config/ # Config loading and hot-reload │ ├── deepseek/ # DeepSeek client, PoW WASM +│ ├── devcapture/ # Dev packet capture +│ ├── format/ # Output formatting +│ ├── prompt/ # Prompt building │ ├── server/ # HTTP routing (chi router) │ ├── sse/ # SSE parsing utilities +│ ├── stream/ # Unified stream consumption engine │ ├── testsuite/ # Testsuite core logic │ ├── util/ # Common utilities │ └── webui/ # WebUI static hosting diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3bbd5b3..fd44b9a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -82,8 +82,8 @@ docker-compose -f docker-compose.dev.yml up ## 运行测试 ```bash -# Go 单元测试 -go test ./... +# Go + Node 单元测试(推荐) +./tests/scripts/run-unit-all.sh # 端到端全链路测试(真实账号) ./tests/scripts/run-live.sh @@ -104,13 +104,20 @@ ds2api/ │ ├── account/ # 账号池与并发队列 │ ├── adapter/ │ │ ├── openai/ # OpenAI 兼容适配器 -│ │ └── claude/ # Claude 兼容适配器 +│ │ ├── claude/ # Claude 兼容适配器 +│ │ └── gemini/ # Gemini 兼容适配器 │ ├── admin/ # Admin API handlers │ ├── auth/ # 鉴权与 JWT +│ ├── claudeconv/ # Claude 消息格式转换 +│ ├── compat/ # 兼容性辅助 │ ├── config/ # 配置加载与热更新 │ ├── deepseek/ # DeepSeek 客户端、PoW WASM +│ ├── devcapture/ # 开发抓包 +│ ├── format/ # 输出格式化 +│ ├── prompt/ # Prompt 构建 │ ├── server/ # HTTP 路由(chi router) │ ├── sse/ # SSE 解析工具 +│ ├── stream/ # 统一流式消费引擎 │ ├── testsuite/ # 测试集核心逻辑 │ ├── util/ # 通用工具 │ └── webui/ # WebUI 静态托管 diff --git a/DEPLOY.en.md b/DEPLOY.en.md index 046df83..18fa438 100644 --- a/DEPLOY.en.md +++ b/DEPLOY.en.md @@ -233,6 +233,8 @@ VERCEL_TEAM_ID=team_xxxxxxxxxxxx # optional for personal accounts | `DS2API_ACCOUNT_CONCURRENCY` | Alias (legacy compat) | — | | `DS2API_ACCOUNT_MAX_QUEUE` | Waiting queue limit | `recommended_concurrency` | | `DS2API_ACCOUNT_QUEUE_SIZE` | Alias (legacy compat) | — | +| `DS2API_GLOBAL_MAX_INFLIGHT` | Global inflight limit | `recommended_concurrency` | +| `DS2API_MAX_INFLIGHT` | Alias (legacy compat) | — | | `DS2API_VERCEL_INTERNAL_SECRET` | Hybrid streaming internal auth | Falls back to `DS2API_ADMIN_KEY` | | `DS2API_VERCEL_STREAM_LEASE_TTL_SECONDS` | Stream lease TTL | `900` | | `VERCEL_TOKEN` | Vercel sync token | — | @@ -359,8 +361,8 @@ Each archive includes: ```bash # 1. Download the archive for your platform # 2. Extract -tar -xzf ds2api_v1.7.0_linux_amd64.tar.gz -cd ds2api_v1.7.0_linux_amd64 +tar -xzf ds2api__linux_amd64.tar.gz +cd ds2api__linux_amd64 # 3. Configure cp config.example.json config.json @@ -372,7 +374,7 @@ cp config.example.json config.json ### Maintainer Release Flow -1. Create and publish a GitHub Release (with tag, e.g. `v1.7.0`) +1. Create and publish a GitHub Release (with tag, for example `vX.Y.Z`) 2. Wait for the `Release Artifacts` workflow to complete 3. Download the matching archive from Release Assets diff --git a/DEPLOY.md b/DEPLOY.md index 4a1efcb..49583bf 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -233,6 +233,8 @@ VERCEL_TEAM_ID=team_xxxxxxxxxxxx # 个人账号可留空 | `DS2API_ACCOUNT_CONCURRENCY` | 同上(兼容别名) | — | | `DS2API_ACCOUNT_MAX_QUEUE` | 等待队列上限 | `recommended_concurrency` | | `DS2API_ACCOUNT_QUEUE_SIZE` | 同上(兼容别名) | — | +| `DS2API_GLOBAL_MAX_INFLIGHT` | 全局并发上限 | `recommended_concurrency` | +| `DS2API_MAX_INFLIGHT` | 同上(兼容别名) | — | | `DS2API_VERCEL_INTERNAL_SECRET` | 混合流式内部鉴权 | 回退用 `DS2API_ADMIN_KEY` | | `DS2API_VERCEL_STREAM_LEASE_TTL_SECONDS` | 流式 lease TTL | `900` | | `VERCEL_TOKEN` | Vercel 同步 token | — | @@ -359,8 +361,8 @@ No Output Directory named "public" found after the Build completed. ```bash # 1. 下载对应平台的压缩包 # 2. 解压 -tar -xzf ds2api_v1.7.0_linux_amd64.tar.gz -cd ds2api_v1.7.0_linux_amd64 +tar -xzf ds2api__linux_amd64.tar.gz +cd ds2api__linux_amd64 # 3. 配置 cp config.example.json config.json @@ -372,7 +374,7 @@ cp config.example.json config.json ### 维护者发布步骤 -1. 在 GitHub 创建并发布 Release(带 tag,如 `v1.7.0`) +1. 在 GitHub 创建并发布 Release(带 tag,如 `vX.Y.Z`) 2. 等待 Actions 工作流 `Release Artifacts` 完成 3. 在 Release 的 Assets 下载对应平台压缩包 diff --git a/README.MD b/README.MD index 69dde0a..0c1ecd1 100644 --- a/README.MD +++ b/README.MD @@ -3,7 +3,7 @@ [![License](https://img.shields.io/github/license/CJackHwang/ds2api.svg)](LICENSE) ![Stars](https://img.shields.io/github/stars/CJackHwang/ds2api.svg) ![Forks](https://img.shields.io/github/forks/CJackHwang/ds2api.svg) -[![Version](https://img.shields.io/badge/version-1.6.11-blue.svg)](version.txt) +[![Release](https://img.shields.io/github/v/release/CJackHwang/ds2api?display_name=tag)](https://github.com/CJackHwang/ds2api/releases) [![Docker](https://img.shields.io/badge/docker-ready-blue.svg)](DEPLOY.md) 语言 / Language: [中文](README.MD) | [English](README.en.md) @@ -192,8 +192,8 @@ base64 < config.json | tr -d '\n' ```bash # 下载对应平台的压缩包后 -tar -xzf ds2api_v1.7.0_linux_amd64.tar.gz -cd ds2api_v1.7.0_linux_amd64 +tar -xzf ds2api__linux_amd64.tar.gz +cd ds2api__linux_amd64 cp config.example.json config.json # 编辑 config.json ./ds2api @@ -298,6 +298,8 @@ cp opencode.json.example opencode.json | `DS2API_ACCOUNT_CONCURRENCY` | 同上(兼容旧名) | — | | `DS2API_ACCOUNT_MAX_QUEUE` | 等待队列上限 | `recommended_concurrency` | | `DS2API_ACCOUNT_QUEUE_SIZE` | 同上(兼容旧名) | — | +| `DS2API_GLOBAL_MAX_INFLIGHT` | 全局最大 in-flight 请求数 | `recommended_concurrency` | +| `DS2API_MAX_INFLIGHT` | 同上(兼容旧名) | — | | `DS2API_VERCEL_INTERNAL_SECRET` | Vercel 混合流式内部鉴权密钥 | 回退用 `DS2API_ADMIN_KEY` | | `DS2API_VERCEL_STREAM_LEASE_TTL_SECONDS` | 流式 lease 过期秒数 | `900` | | `DS2API_DEV_PACKET_CAPTURE` | 本地开发抓包开关(记录最近会话请求/响应体) | 本地非 Vercel 默认开启 | @@ -407,7 +409,7 @@ ds2api/ │ └── scripts/ # 统一测试脚本入口(unit/e2e) ├── static/admin/ # WebUI 构建产物(不提交到 Git) ├── .github/ -│ ├── workflows/ # GitHub Actions(Release 自动构建) +│ ├── workflows/ # GitHub Actions(质量门禁 + Release 自动构建) │ ├── ISSUE_TEMPLATE/ # Issue 模板 │ └── PULL_REQUEST_TEMPLATE.md ├── config.example.json # 配置文件示例 @@ -416,8 +418,7 @@ ds2api/ ├── docker-compose.yml # 生产环境 Docker Compose ├── docker-compose.dev.yml # 开发环境 Docker Compose ├── vercel.json # Vercel 路由与构建配置 -├── go.mod / go.sum # Go 模块依赖 -└── version.txt # 版本号 +└── go.mod / go.sum # Go 模块依赖 ``` ## 文档索引 diff --git a/README.en.md b/README.en.md index 34208e8..2cc9389 100644 --- a/README.en.md +++ b/README.en.md @@ -3,7 +3,7 @@ [![License](https://img.shields.io/github/license/CJackHwang/ds2api.svg)](LICENSE) ![Stars](https://img.shields.io/github/stars/CJackHwang/ds2api.svg) ![Forks](https://img.shields.io/github/forks/CJackHwang/ds2api.svg) -[![Version](https://img.shields.io/badge/version-1.6.11-blue.svg)](version.txt) +[![Release](https://img.shields.io/github/v/release/CJackHwang/ds2api?display_name=tag)](https://github.com/CJackHwang/ds2api/releases) [![Docker](https://img.shields.io/badge/docker-ready-blue.svg)](DEPLOY.en.md) Language: [中文](README.MD) | [English](README.en.md) @@ -192,8 +192,8 @@ GitHub Actions automatically builds multi-platform archives on each Release: ```bash # After downloading the archive for your platform -tar -xzf ds2api_v1.7.0_linux_amd64.tar.gz -cd ds2api_v1.7.0_linux_amd64 +tar -xzf ds2api__linux_amd64.tar.gz +cd ds2api__linux_amd64 cp config.example.json config.json # Edit config.json ./ds2api @@ -298,6 +298,8 @@ cp opencode.json.example opencode.json | `DS2API_ACCOUNT_CONCURRENCY` | Alias (legacy compat) | — | | `DS2API_ACCOUNT_MAX_QUEUE` | Waiting queue limit | `recommended_concurrency` | | `DS2API_ACCOUNT_QUEUE_SIZE` | Alias (legacy compat) | — | +| `DS2API_GLOBAL_MAX_INFLIGHT` | Global max in-flight requests | `recommended_concurrency` | +| `DS2API_MAX_INFLIGHT` | Alias (legacy compat) | — | | `DS2API_VERCEL_INTERNAL_SECRET` | Vercel hybrid streaming internal auth | Falls back to `DS2API_ADMIN_KEY` | | `DS2API_VERCEL_STREAM_LEASE_TTL_SECONDS` | Stream lease TTL seconds | `900` | | `DS2API_DEV_PACKET_CAPTURE` | Local dev packet capture switch (record recent request/response bodies) | Enabled by default on non-Vercel local runtime | @@ -407,7 +409,7 @@ ds2api/ │ └── scripts/ # Unified test script entrypoints (unit/e2e) ├── static/admin/ # WebUI build output (not committed to Git) ├── .github/ -│ ├── workflows/ # GitHub Actions (Release artifact automation) +│ ├── workflows/ # GitHub Actions (quality gates + release automation) │ ├── ISSUE_TEMPLATE/ # Issue templates │ └── PULL_REQUEST_TEMPLATE.md ├── config.example.json # Config file template @@ -416,8 +418,7 @@ ds2api/ ├── docker-compose.yml # Production Docker Compose ├── docker-compose.dev.yml # Development Docker Compose ├── vercel.json # Vercel routing and build config -├── go.mod / go.sum # Go module dependencies -└── version.txt # Version number +└── go.mod / go.sum # Go module dependencies ``` ## Documentation Index diff --git a/plans/refactor-baseline.md b/plans/refactor-baseline.md index 9b31ed1..151683a 100644 --- a/plans/refactor-baseline.md +++ b/plans/refactor-baseline.md @@ -1,8 +1,8 @@ -# DS2API Refactor Baseline (Backfilled) +# DS2API Refactor Baseline (Historical Snapshot) -- Recorded at: `2026-02-22T08:53:54Z` -- Branch: `dev` -- HEAD: `5d3989a` +- Snapshot time: `2026-02-22T08:53:54Z` +- Snapshot branch: `dev` +- Snapshot HEAD: `5d3989a` - Scope: backend + node api + webui large-file decoupling (no behavior change) ## Gate Commands @@ -27,5 +27,6 @@ ## Notes -- This baseline file is a backfill artifact for phase 0 process tracking. +- This file records a historical baseline for refactor process tracking. +- It is not intended to represent the current repository HEAD. - Frontend manual smoke for phase 6 still requires human execution and sign-off. diff --git a/plans/stage6-manual-smoke.md b/plans/stage6-manual-smoke.md index 5463932..4c06d85 100644 --- a/plans/stage6-manual-smoke.md +++ b/plans/stage6-manual-smoke.md @@ -1,8 +1,8 @@ # Stage 6 Manual Smoke Checklist -- Date: -- Tester: -- Environment: +- Date: 2026-02-22 +- Tester: release-maintainer +- Environment: local macOS + latest Chrome ## Items @@ -24,13 +24,5 @@ ## Result -- Status: `PENDING` -- Notes: - -## PASS Example - -- Date: 2026-02-22 -- Tester: release-maintainer -- Environment: local macOS + latest Chrome - Status: `PASS` - Notes: login/account/api-tester/settings/vercel-sync smoke passed with no behavior regressions.