0e9b53dc79
- accounts page gains a #keys DataTable below the accounts table showing each API key's usage today: Key | Today | Tokens | Req, sorted by cost - data comes from the Sub2API admin dashboard api-keys-trend (requests, tokens, key names) plus api-keys-usage (today_actual_cost), derived from the configured logs url and reusing the same admin API key - key names use the same stable per-key colors as the logs page - --once prints the same panel after the accounts snapshot; failures or a missing token surface in the status line without touching accounts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
192 lines
7.2 KiB
Markdown
192 lines
7.2 KiB
Markdown
# shusub2
|
||
|
||
- 文档层级:客户端工具
|
||
- 应用性质:客户端 TUI
|
||
- 源码来源:repo 原生
|
||
- 运行关系:客户端工具
|
||
- 部署模型:无
|
||
- 对应服务:无
|
||
- 对应 stack:无
|
||
- Secret 边界:账号页无 secret;请求日志页可选持有 Sub2API admin API key(仅存本机 `~/.config/shusub2/logs-token`,0600)
|
||
- 分发方式:`uvx` / `uv tool install`。
|
||
- 包名:`shusub2`
|
||
- 命令名:`shusub2`
|
||
- 本地状态路径:`~/.config/shusub2/`
|
||
- 目标 API:`cliproxy-codex-quota` 的 `/api/tui/accounts`、可选 `sub2api-status` `/api/status`、可选 Sub2API `/api/v1/admin/usage`(请求日志页,默认 `sub2apicn.shujk.top`)。
|
||
- 备注:账号页不需要 SSH、数据库访问、API key、OAuth credentials 或 plaintext env;请求日志页需要 Sub2API admin API key。
|
||
|
||
Terminal UI for the token-safe Sub2API account feed exposed by
|
||
`cliproxy-codex-quota`, plus an optional request-logs page backed by the
|
||
Sub2API admin usage API.
|
||
|
||
## Quick Start
|
||
|
||
Run once from a public Git repo with `uvx`:
|
||
|
||
```bash
|
||
uvx --from git+https://gitea.shujk.top/shujakuin/shusub2.git shusub2 \
|
||
--api-url https://codex.server2.shujk.top/1232131231313123/api/tui/accounts
|
||
```
|
||
|
||
Bootstrap a new machine from `uvx`: save the API URL, install `shusub2` as a
|
||
user command, then run it later as `shusub2`:
|
||
|
||
```bash
|
||
uvx --from git+https://gitea.shujk.top/shujakuin/shusub2.git shusub2 \
|
||
--api-url https://codex.server2.shujk.top/1232131231313123/api/tui/accounts \
|
||
--install
|
||
shusub2
|
||
```
|
||
|
||
Install as a user command:
|
||
|
||
```bash
|
||
uv tool install git+https://gitea.shujk.top/shujakuin/shusub2.git
|
||
shusub2 --api-url https://codex.server2.shujk.top/1232131231313123/api/tui/accounts --save-config
|
||
```
|
||
|
||
Configure the default public API URL for `shusub2`:
|
||
|
||
```bash
|
||
mkdir -p ~/.config/shusub2
|
||
chmod 700 ~/.config/shusub2
|
||
printf '%s\n' 'https://codex.server2.shujk.top/1232131231313123/api/tui/accounts' > ~/.config/shusub2/api-url
|
||
chmod 600 ~/.config/shusub2/api-url
|
||
shusub2
|
||
```
|
||
|
||
Environment variables override the config file:
|
||
|
||
- `SHUSUB2_API_URL`
|
||
- `SUB2API_QUOTA_TUI_API_URL`
|
||
- `SHUSUB2_API_URL_FILE`
|
||
- `SHUSUB2_STATUS_URL`
|
||
- `SHUSUB2_STATUS_URL_FILE`
|
||
- `SHUSUB2_LOGS_URL`
|
||
- `SHUSUB2_LOGS_URL_FILE`
|
||
- `SHUSUB2_LOGS_TOKEN`
|
||
- `SHUSUB2_LOGS_TOKEN_FILE`
|
||
- `SHUSUB2_LOGS_REFRESH_SECONDS`
|
||
- `SHUSUB2_LOGS_LIMIT`
|
||
- `SHUSUB2_VERSION_CHECK_URL`
|
||
- `SHUSUB2_VERSION_CHECK_TIMEOUT`
|
||
- `SHUSUB2_NO_VERSION_CHECK`
|
||
|
||
## Request Logs Page
|
||
|
||
Press `l` on the accounts page to open the request logs page; press `a` to go
|
||
back. `shusub2 --logs` starts directly on the logs page, and
|
||
`shusub2 --once --logs` prints one logs snapshot to stdout.
|
||
|
||
The logs page reads the latest requests (default 100, `--logs-limit`) from the
|
||
Sub2API admin usage API and refreshes every 60 seconds by default
|
||
(`--logs-refresh-seconds` / `SHUSUB2_LOGS_REFRESH_SECONDS`). Columns:
|
||
|
||
```text
|
||
Key | Account | Model | Effort | Type | Tokens | Cost | First | Latency | Tok/s | Time
|
||
```
|
||
|
||
`Type` is the Sub2API `request_type` (`sync` / `stream` / `ws_v2` / `cyber`).
|
||
`Tokens` is input + output + cache write + cache read; the detail line below
|
||
the table shows the per-bucket breakdown, actual cost, first-token latency,
|
||
decode speed, upstream model mapping, user, and request id.
|
||
|
||
`Effort` is the request's `reasoning_effort` (`-` when absent). `First` is the
|
||
first-token latency and `Latency` the total duration, both shown in seconds.
|
||
`Tok/s` is the decode throughput computed as
|
||
`output_tokens / (latency - first_token)`; it shows
|
||
`-` when there is no output or no positive decode window. In the TUI each
|
||
API key name is rendered in a stable per-key color so rows from the same
|
||
key are easy to group visually (`--once --logs` output stays plain text).
|
||
|
||
The logs URL defaults to `https://sub2apicn.shujk.top/api/v1/admin/usage` and
|
||
can be overridden with `--logs-url` / `SHUSUB2_LOGS_URL` /
|
||
`~/.config/shusub2/logs-url`.
|
||
|
||
The page needs a Sub2API **admin API key** (generated in the Sub2API web UI
|
||
under Settings). Configure it once:
|
||
|
||
```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
|
||
```
|
||
|
||
or via `SHUSUB2_LOGS_TOKEN`. The key is sent as the `x-api-key` header and is
|
||
never written anywhere else by the client. Without a token the logs page stays
|
||
empty and shows a configuration hint; the accounts page keeps working without
|
||
any secret.
|
||
|
||
## Local Development
|
||
|
||
```bash
|
||
cd apps/sub2api-quota-tui
|
||
uv run shusub2
|
||
```
|
||
|
||
Run inside zellij:
|
||
|
||
```bash
|
||
zellij action new-pane --name sub2api-quota -- \
|
||
bash -lc 'cd /home/shujakuin/infra/apps/sub2api-quota-tui && uv run shusub2'
|
||
```
|
||
|
||
Configuration:
|
||
|
||
- `--api-url` / `SUB2API_QUOTA_TUI_API_URL`
|
||
- `--status-url` / `SHUSUB2_STATUS_URL`
|
||
- `--logs-url` / `SHUSUB2_LOGS_URL`
|
||
- `--logs-token` / `SHUSUB2_LOGS_TOKEN`
|
||
- `--logs-refresh-seconds` / `SHUSUB2_LOGS_REFRESH_SECONDS`
|
||
- `--logs-limit` / `SHUSUB2_LOGS_LIMIT`
|
||
- `--save-config`
|
||
- `--install`
|
||
- `--refresh-seconds` / `SUB2API_QUOTA_TUI_REFRESH_SECONDS`
|
||
- `--timeout` / `SUB2API_QUOTA_TUI_TIMEOUT`
|
||
|
||
The TUI reads `/api/tui/accounts` and can optionally read `sub2api-status`
|
||
`/api/status` for channel monitor health. The accounts page does not need SSH,
|
||
database access, API keys, OAuth credentials, or plaintext env files. The
|
||
optional request logs page authenticates to the Sub2API admin usage API with
|
||
an admin API key stored only in `~/.config/shusub2/logs-token` (0600) or
|
||
`SHUSUB2_LOGS_TOKEN`.
|
||
|
||
When `--status-url` is omitted, `shusub2` infers a sibling `/api/status` URL
|
||
from account URLs ending in `/api/tui/accounts`, so the public Codex endpoint
|
||
automatically enables monitor availability. On startup it also checks the
|
||
public Gitea repo for a newer package version and prints a short upgrade hint
|
||
when one is available.
|
||
|
||
Below the accounts table, a per-key panel shows today's usage for each
|
||
API key (`Key | Today | Tokens | Req`, sorted by cost, key names in the
|
||
same per-key colors as the logs page). It combines the Sub2API admin
|
||
`dashboard/api-keys-trend` and `dashboard/api-keys-usage` endpoints and
|
||
needs the same admin API key as the logs page; without a token the panel
|
||
stays empty and the status line shows a hint. `--once` prints the same
|
||
panel after the accounts table when a token is configured.
|
||
|
||
Accounts page columns are ordered for scanning inside zellij:
|
||
|
||
```text
|
||
Name | Provider | Group | Daily | Today | Tokens | Req | Kind | 5h | 7d | Reset | Status | Availability
|
||
```
|
||
|
||
`Provider` distinguishes `openai` and `anthropic` accounts from the public
|
||
`platform` field returned by the API.
|
||
|
||
`Daily` is shown as `used/limit` when Sub2API has `quota_daily_*` fields in
|
||
`accounts.extra`; otherwise it is `-`.
|
||
|
||
`Group` is the derived Sub2API tier alias group. Higher tiers win when multiple
|
||
aliases exist: `id < slow < fast < sfast`. The table shows `sfast` first, then
|
||
`fast`, `slow`, `id`, and ungrouped accounts.
|
||
|
||
When `--status-url` is configured, the status line shows channel monitor
|
||
health, and the selected account detail shows the matching monitor status when
|
||
one exists. Monitor binding first uses the shared `base_url_hash` emitted by
|
||
the account API and `sub2api-status`; name-token matching remains only as a
|
||
fallback for older status payloads.
|
||
|
||
`Availability` is derived from the bound channel monitor. Accounts without a
|
||
matching monitor show `-`.
|