This commit is contained in:
+16
-13
@@ -5,7 +5,7 @@
|
||||
## 1. 全局行为
|
||||
|
||||
- 默认监听 `${LISTEN_ADDR:-:8080}`,API 前缀为 `/api/v1/`。
|
||||
- `GET /health/live` 始终返回 `200 {"status":"ok"}`;`GET /health/ready` 在 SQLite 可用时返回 `200 {"status":"ok","appServer":bool}`,数据库不可用时返回 `503 {"error":string}`。`appServer` 表示至少一个账号的 app-server 已完成初始化。
|
||||
- `GET /health/live` 始终返回 `200 {"status":"ok"}`;`GET /health/ready` 在 SQLite 可用时返回 `200 {"status":"ok","cpa":bool}`,数据库不可用时返回 `503 {"error":string}`。`cpa` 表示 `CLIPROXY_API_BASE_URL` 与 `CLIPROXY_API_MANAGEMENT_KEY` 均已配置,不代表每个 authIndex 都可用。
|
||||
- JSON 请求体最多读取 1 MiB,拒绝未知字段;业务错误统一为 `{"error":string}`。未匹配 API 返回 `404 {"error":"接口不存在"}`。
|
||||
- 所有响应带 `X-Content-Type-Options: nosniff`、`X-Frame-Options: DENY`、`Referrer-Policy: same-origin` 和同源 CSP。
|
||||
- `GET /api/v1/system/status`、`POST /api/v1/setup`、`POST /api/v1/auth/login` 匿名可用;初始化完成后,`GET`/`HEAD /api/v1/accounts` 和 `GET`/`HEAD /api/v1/dashboard` 也提供已标记为公开账号的匿名只读总览。匿名总览会隐藏邮箱、认证方式、账号配置校验和内部错误字段;未公开账号对匿名请求按不存在处理。其余 API 要求有效 `session` cookie,非 `GET`/`HEAD` 请求还要求 `X-Requested-With: codex-helper`,否则分别返回 401 或 403。当前 dispatcher 只对部分路由显式限制 HTTP method;下文使用“任意方法”或“非 `GET`”的地方是对实际兼容行为的记录。
|
||||
@@ -17,7 +17,7 @@
|
||||
### Account
|
||||
|
||||
```text
|
||||
{id, displayName, email:string|null, planType:string|null,
|
||||
{id, displayName, authIndex?:string, email:string|null, planType:string|null,
|
||||
expectedKind:"any"|"personal"|"team", publicVisible:bool,
|
||||
actualKind:"unknown"|"personal"|"team",
|
||||
validationStatus:"pending"|"matched"|"mismatch"|"unknown",
|
||||
@@ -40,14 +40,14 @@
|
||||
fetchedAt, stale, lastError?}
|
||||
```
|
||||
|
||||
时间字段为 Unix 秒。`currentCycle` 是按当前仍有效的最长限额窗口计算的当前重置周期;`totalTokens` 由 `account/usage/read` 的每日 Token bucket 汇总,受每日粒度影响,无法精确切分周期起止日期内的单日数据。`summary.peakDailyTokens` 是同一当前重置周期内每日 Token bucket 的最大值,不再直接采用 app-server 未限定口径的峰值摘要;没有有效窗口或周期内没有每日数据时为 `null`。app-server 未提供的其他摘要字段可以是 `null`;列表应返回数组而非 `null`。
|
||||
`resetCredits` 仅在 app-server 返回可用重置卡且 `availableCount > 0` 时出现;`expiresAt` 是已返回卡片的去重到期时间列表,服务端未提供卡片详情时可以为空。公开账号的匿名 Dashboard 也会返回该字段;邮箱、认证方式和内部错误字段仍会隐藏。
|
||||
登录态 Dashboard 的 `account.authMode` 在 CPA 同步成功时为 `cliproxyapi`;匿名响应将其隐藏。`/wham/profiles/me` 读取失败时限额同步仍可成功:同一进程内保留上次成功的 summary、usage 和据此重算的 currentCycle;没有旧值时 summary 字段为 `null`、usage 为空数组且 currentCycle 缺省。时间字段为 Unix 秒。`currentCycle` 是按当前仍有效的最长限额窗口计算的当前重置周期;`totalTokens` 由 CPA 代请求 `/wham/profiles/me` 得到的每日 Token bucket 汇总,受每日粒度影响,无法精确切分周期起止日期内的单日数据。`summary.peakDailyTokens` 是同一当前重置周期内每日 Token bucket 的最大值;没有有效窗口或周期内没有每日数据时为 `null`。上游未提供的其他摘要字段可以是 `null`;列表应返回数组而非 `null`。
|
||||
`resetCredits` 仅在 `/wham/usage` 或可选详情接口返回可用重置卡且 `availableCount > 0` 时出现;`expiresAt` 是可用卡片的去重到期时间列表,详情接口失败或服务端未提供详情时可以为空。公开账号的匿名 Dashboard 也会返回该字段;邮箱、认证方式和内部错误字段仍会隐藏。
|
||||
|
||||
## 3. 系统、初始化与会话
|
||||
|
||||
| 方法与路径 | 鉴权 | 行为 |
|
||||
| --- | --- | --- |
|
||||
| `GET /api/v1/system/status` | 匿名 | `200 {initialized,version,appServer}`。`version` 为镜像构建时注入的应用版本,未注入时默认为 `0.3.0`。 |
|
||||
| `GET /api/v1/system/status` | 匿名 | `200 {initialized,version,cpa}`。`cpa` 表示 CPA 环境变量已配置;`version` 为镜像构建时注入的应用版本,未注入时默认为 `0.3.0`。 |
|
||||
| `POST /api/v1/setup` | 匿名、仅未初始化 | body `{username,password,timezone}`;用户名至少 3 位、密码至少 10 位,否则 400;时区有效时写入,否则使用默认 UTC。事务创建唯一管理员和通用设置,设置 session,返回 `201 {ok:true}`;已初始化返回 409。 |
|
||||
| `POST /api/v1/auth/login` | 匿名 | body `{username,password}`;未初始化返回 409,错误凭据返回 401,成功设置 session 并返回 `200 {ok:true}`,限流返回 429。 |
|
||||
| `任意方法 /api/v1/auth/me` | session;非 `GET`/`HEAD` 还需来源头 | `200 {username}`。前端使用 `GET`。 |
|
||||
@@ -59,12 +59,10 @@
|
||||
|
||||
| 方法与路径 | 请求与响应 |
|
||||
| --- | --- |
|
||||
| `GET /api/v1/accounts` | 初始化后匿名可读;匿名只返回 `publicVisible=true` 的账号,按 ID 升序;匿名响应隐藏 `email`、`expectedKind`、`actualKind`、`validationStatus`、`possibleDuplicate` 和创建/更新时间。登录后返回全部账号及完整字段。 |
|
||||
| `POST /api/v1/accounts` | body `{displayName,expectedKind,publicVisible}`;空名称默认为 `新账号`,空类型默认为 `any`,`publicVisible` 省略时默认为 `false`;成功返回 `201 Account`。 |
|
||||
| `PUT /api/v1/accounts/{id}` | body `{displayName,expectedKind?,publicVisible?}`;名称不能为空,省略类型或 `publicVisible` 时分别保留旧值;成功返回 `200 {ok:true}`。 |
|
||||
| `DELETE /api/v1/accounts/{id}` | 停止该账号进程,删除账号及级联历史,再删除对应凭据目录;成功返回 `200 {ok:true}`。 |
|
||||
| `POST /api/v1/accounts/{id}/login/device` | 启动并初始化 app-server,调用 `account/login/start` 的 `chatgptDeviceCode` 流程;返回含 `verificationUrl`、`userCode` 和 `loginId` 的结果。 |
|
||||
| `POST /api/v1/accounts/{id}/logout` | 调用 `account/logout` 并将连接状态置为 false;返回 `200 {ok:true}`。 |
|
||||
| `GET /api/v1/accounts` | 初始化后匿名可读;匿名只返回 `publicVisible=true` 的账号,按 ID 升序;匿名响应清空 `authIndex`,并隐藏 `email`、`expectedKind`、`actualKind`、`validationStatus`、`possibleDuplicate` 和创建/更新时间。登录后返回全部账号及完整字段。 |
|
||||
| `POST /api/v1/accounts` | body `{displayName?,authIndex,expectedKind?,publicVisible?}`;`authIndex` 必填、去除首尾空白、在本地唯一,并且必须在 CPA 中唯一匹配未禁用的 Codex auth;CPA transient unavailable/error 不阻止额度读取。空名称优先采用 CPA label/name,否则为 `新账号`,空类型默认为 `any`,`publicVisible` 省略时默认为 `false`。后端在持久化前完成上游验证和快照读取,成功返回 `201 Account`,失败不留下账号。 |
|
||||
| `PUT /api/v1/accounts/{id}` | body `{displayName,authIndex?,expectedKind?,publicVisible?}`;名称不能为空,省略字段保留旧值。修改 `authIndex` 时先验证 CPA auth 和完整快照,失败保留原绑定;成功时原账号的本地 Token 历史、限额快照和提醒记录被原子清除,避免不同 CPA 身份串数据,并返回 `200 {ok:true}`。 |
|
||||
| `DELETE /api/v1/accounts/{id}` | 删除 Codex Helper 中的账号绑定及级联历史,不删除 CLIProxyAPI 凭据;成功返回 `200 {ok:true}`。 |
|
||||
| `POST /api/v1/accounts/{id}/sync` | 同步指定账号;成功 `200 {ok:true}`,上游失败 502。 |
|
||||
| `GET`/`HEAD /api/v1/dashboard?accountId={id}` | 初始化后匿名可读公开账号,返回内存中的 `Dashboard`;匿名访问未公开账号返回 404,匿名响应隐藏邮箱、认证方式和内部错误字段,但保留重置卡信息。登录后可读取全部账号。省略或无效的零值 ID 使用账号 1,前端使用 `GET`。 |
|
||||
| `任意非读方法 /api/v1/dashboard?accountId={id}` | 要求 session;非 `GET`/`HEAD` 还需来源头。保持兼容的读取行为,省略或无效的零值 ID 使用账号 1。 |
|
||||
@@ -104,8 +102,13 @@
|
||||
| 方法与路径 | 行为 |
|
||||
| --- | --- |
|
||||
| `POST /api/v1/maintenance/cleanup` | 按当前保留天数删除旧限额快照、通知和每日用量,返回 `200 {deleted}`。 |
|
||||
| `任意方法 /api/v1/maintenance/backup` | 使用 SQLite `VACUUM INTO` 生成包含已提交 WAL 数据的一致性快照,并以 `codex-helper.db` 下载;非 `GET`/`HEAD` 还需来源头,前端使用 `GET`。快照不含 `/data/secret.key` 或 Codex 凭据目录。 |
|
||||
| `任意方法 /api/v1/maintenance/backup` | 使用 SQLite `VACUUM INTO` 生成包含已提交 WAL 数据的一致性快照,并以 `codex-helper.db` 下载;非 `GET`/`HEAD` 还需来源头,前端使用 `GET`。快照不含 `/data/secret.key`,也不包含外部 CLIProxyAPI 的 Codex 凭据。 |
|
||||
|
||||
## 7. 外部协议边界
|
||||
|
||||
每个账号通过 JSONL stdio 与 `codex app-server` 通信。当前使用的方法为 `initialize`、`account/read`、`account/login/start`、`account/logout`、`account/rateLimits/read` 和 `account/usage/read`,并响应 `account/login/completed`、`account/updated`、`account/rateLimits/updated` 通知。官方协议说明见 [Codex App Server](https://learn.chatgpt.com/docs/app-server);本项目以 Dockerfile 固定的 Codex CLI 版本、当前解析代码和测试作为兼容基线。
|
||||
Codex Helper 只通过 CLIProxyAPI Management API 访问 Codex 数据:
|
||||
|
||||
- `GET /v0/management/auth-files?auth_index=...`:验证 authIndex,读取非秘密账号元数据和 ID token claims。
|
||||
- `POST /v0/management/api-call`:由 CPA 按 authIndex 注入 OAuth token,代请求 `GET https://chatgpt.com/backend-api/wham/usage`、`GET https://chatgpt.com/backend-api/wham/profiles/me` 和可选的 `GET https://chatgpt.com/backend-api/wham/rate-limit-reset-credits`。
|
||||
|
||||
CPA base URL 和 management key 只来自服务端环境变量;management key、OAuth token、认证文件和原始上游错误正文不得进入 API 响应或日志。`/wham/*` 是内部接口,本项目以 CPA 协议、当前解析代码和测试作为兼容基线。
|
||||
|
||||
Reference in New Issue
Block a user