Files
shusub2/README.md
T

221 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# shusub2
- 文档层级:客户端工具
- 应用性质:客户端 TUI
- 源码来源:repo 原生
- 运行关系:客户端工具
- 部署模型:无
- 对应服务:无
- 对应 stack:无
- Secret 边界:本地用户配置
- 目标 APIPricing Monitor `GET /api/ui-data?view=workspace`
- 分发方式:`uvx` / `uv tool install`
- 包名:`shusub2`
- 命令名:`shusub2`
- 本地状态路径:`~/.config/shusub2/`
- 默认数据源:Pricing Monitor `GET /api/ui-data?view=workspace`
`shusub2` 是 Sub2API 聚合运维 TUI。默认模式只读取 server2 Pricing Monitor
后台生成的内存 snapshot,不直接访问 Accounts helper、`sub2api-status`、Sub2API
admin API、PostgreSQL、SSH 或 pricing upstream。每次数据刷新只请求一次 workspace
projectionDashboard、Accounts、Sources、Requests 和 Errors 共用同一份进程内缓存。后台 snapshot
读取之外,默认启动仍会进行一次短超时的 Gitea 版本检查;使用
`--no-version-check``SHUSUB2_NO_VERSION_CHECK=1` 可关闭它。
## Quick Start
已安装时直接运行:
```bash
shusub2
```
默认 workspace URL 是 Tailscale HTTPS 入口:
```text
https://price.tailbeb9ad.ts.net/api/ui-data?view=workspace
```
覆盖并保存 workspace URL
```bash
shusub2 \
--workspace-url https://price.tailbeb9ad.ts.net/api/ui-data?view=workspace \
--save-config
```
从 Gitea 安装为用户命令:
```bash
uv tool install git+https://gitea.shujk.top/shujakuin/shusub2.git
shusub2
```
也可以一次性运行:
```bash
uvx --from git+https://gitea.shujk.top/shujakuin/shusub2.git shusub2
```
## Data Contract
Pricing Monitor 在后台按固定节奏采集并裁剪数据。普通 workspace HTTP 读取只复制
最近一次内存 snapshot,不触发 SSH、生产 SQL、旧 helper refresh 或 pricing source
refresh。组件失败时服务端保留对应 last-good 数据,并在 `components` / `state` 中标记
`stale``partial` 和更新时间。
Workspace 当前提供以下有界 projection
- `accounts`:账号摘要、quota window、当日用量和 provider/group/status 字段。
- `status`channel monitor 摘要。
- `sources`Pricing Monitor 已有的脱敏 source 余额与健康状态。
- `traffic.requests`:仅 server6 的最近有界请求样本。
- `traffic.errors`server6/server4 的有界逐条错误事件,保留节点、时间、key/account、结构化错误类别和状态链路,不做错误分组或 per-row count。
- `traffic.keys`:仅 server6 按 `Asia/Shanghai` 自然日聚合的 key 使用量,payload 同时携带统计日期和时区。
投影允许展示 account/key 名称、稳定 ID、model、instance 和运维状态,但不包含 API
key 原文、access/refresh token、cookie、密码、数据库凭据或请求/响应正文。ID 始终按
字符串处理,避免 JavaScript 或 Python 客户端误损失大整数精度。
## Interface
默认首页是紧凑 Dashboard。页面信息架构为:
```text
Dashboard | Accounts | Sources | Requests | Errors
```
快捷键:
- `a`:聚焦 Accounts,或从独立页面打开 Accounts。
- `p`:打开 Sources。
- `k`:在 Dashboard 聚焦 Key usage。
- `l`:聚焦 Requests,或从独立页面打开 Requests。
- `e`:聚焦 Errors,或从独立页面打开 Errors。
- `d`:从独立页面返回 Dashboard。
- `/`:聚焦当前页面 filterDashboard filter 同时作用于全部表。
- `r`:重新读取 workspace snapshot。该操作不会要求服务端立即采集上游。
窄终端中的长 key、account 和 model 使用横向滚动,不截短原字段。独立页面可通过
以下参数启动:
```bash
shusub2 --accounts
shusub2 --sources # --pricing 保留为兼容别名
shusub2 --requests # --logs 保留为兼容别名
shusub2 --errors
```
加上 `--once` 可输出对应 snapshot 并退出:
```bash
shusub2 --once --requests
```
Accounts 只在 canonical 名称 `{family}-quota-{source}`
`{family}-quotaonly-{source}` 与唯一健康 source 精确匹配时显示 CNY 余额。不会根据
provider、URL、display name 或模糊文本推断;source 为 error/stale 时保留名称和状态,
但不伪造 CNY 数值。
Requests 展示 server6 的 key、account、model、token bucket、actual cost、first-token latency、
duration 和 decode throughput。Errors 展示 server6/server4 的逐条 instance、事件时间、status path、key、
account、model、phase/type/owner,不显示聚合次数。Key usage、Requests 和对应 account 当天用量只采用
server6Errors 保留双节点。所有 workspace Traffic 都使用服务器声明的 `Asia/Shanghai` 自然日,不依赖客户端本地日期或滚动
24 小时窗口;每个 Traffic projection 显式携带日期、时区和 `[00:00, 次日 00:00)` 边界。
## Legacy Direct
`--legacy-direct` 仅用于迁移对账和故障诊断。它恢复旧拓扑:
- Accounts helper `/api/tui/accounts`
- `sub2api-status` `/api/status`
- Pricing Monitor `view=accounts`
- Sub2API admin usage/key/error API
```bash
shusub2 --legacy-direct --accounts
shusub2 --legacy-direct --requests
```
显式传入空 `--workspace-url ''` 也会进入 legacy direct 模式。legacy Requests、Errors
和 Key usage 需要 Sub2API admin API key;默认 workspace 模式不会读取该凭据文件。legacy
Key usage 也固定按 `Asia/Shanghai` 当日查询;legacy Errors 的 `--errors-time-range` 保留为与
上游诊断 API 对账的独立兼容参数,不能代表 workspace 的当天 Traffic 口径。
legacy token 仅允许放在 `SHUSUB2_LOGS_TOKEN` 或权限为 `0600`
`~/.config/shusub2/logs-token`
```bash
mkdir -p ~/.config/shusub2
chmod 700 ~/.config/shusub2
printf '%s\n' '<sub2api-admin-api-key>' > ~/.config/shusub2/logs-token
chmod 600 ~/.config/shusub2/logs-token
```
## Configuration
Workspace-first 配置:
- `--workspace-url` / `SHUSUB2_WORKSPACE_URL` /
`SHUSUB2_WORKSPACE_URL_FILE`
- `--refresh-seconds` / `SUB2API_QUOTA_TUI_REFRESH_SECONDS`
- `--timeout` / `SUB2API_QUOTA_TUI_TIMEOUT`
- `--accounts` / `--sources` / `--requests` / `--errors`
- `--once`
- `--save-config`
- `--install`
- `--version-check-url` / `SHUSUB2_VERSION_CHECK_URL`
- `--no-version-check` / `SHUSUB2_NO_VERSION_CHECK`
Legacy-only 配置:
- `--legacy-direct`
- `--api-url` / `SUB2API_QUOTA_TUI_API_URL`
- `--status-url` / `SHUSUB2_STATUS_URL`
- `--pricing-url` / `SHUSUB2_PRICING_URL`
- `--logs-url` / `SHUSUB2_LOGS_URL`
- `--logs-token` / `SHUSUB2_LOGS_TOKEN`
- `--errors-cn-url` / `SHUSUB2_ERRORS_CN_URL`
- `--errors-us-url` / `SHUSUB2_ERRORS_US_URL`
- `--logs-limit``--errors-limit``--errors-time-range`
URL config 文件默认位于 `~/.config/shusub2/`。环境变量优先于 config 文件。
## Local Development
```bash
cd apps/sub2api-quota-tui
uv run shusub2
```
运行完整测试和静态检查:
```bash
uv run python -m unittest discover -s tests -p 'test_*.py' -v
uv run python -m py_compile sub2api_quota_tui.py
uv lock --check
```
## Maintenance Notes
Workspace adapter 只负责把 server projection 映射为现有渲染模型,不得在普通刷新中
重新引入 legacy HTTP 请求。新增 projection 字段时应同时验证:字段 allowlist、字符串 ID、
finite number、payload 上限、单请求 cache、错误聚合次数和 legacy fallback。
`cliproxy-codex-quota``sub2api-status` 当前仍可作为 Aggregation Hub 的过渡采集输入和
双读对照,但不再是默认 TUI 客户端直连依赖。移除这些过渡输入前,必须先完成 server2
聚合字段对账和 AstrBot `view=alerts` 连续性验证。
## Tests And Release
发布遵循本仓库 `client-tui-gitea-uv` 流程:完成 scoped diff 审阅和测试后,将
`apps/sub2api-quota-tui/` 同步到独立 Gitea 仓库,再通过 git source 执行
`uv tool install --force`。安装后检查 `uv-receipt.toml`,确保来源仍是 Gitea git URL
而不是本地目录。
## Secret Boundary
默认 workspace 模式不需要任何客户端 secret,也不读取 legacy token 文件。服务端
workspace 不聚合原始凭据或请求/响应正文。legacy direct 模式的 admin API key 仅保存在
本机用户配置或进程环境中,不得写入仓库、文档、日志或测试 fixture。