dsh-client-ui-cpa-quota 0.7.2 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/README.zh.md +2 -2
- package/lib/client.js +20 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ Hover the ring next to the selected model for matching accounts, providers, plan
|
|
|
46
46
|
- Supports multiple CLIProxyAPI instances and accounts, filtering the hover tooltip to the selected model while the settings panel always shows everything.
|
|
47
47
|
- Orders windows as `5-hour → weekly → monthly → daily`; the ring uses the first available window in that order.
|
|
48
48
|
- Queries Codex, Claude, Antigravity, Gemini CLI, Kimi, and xAI/Grok through their upstream quota APIs; other CPA providers still expose account status and recent activity.
|
|
49
|
-
- **In-use account detection**: CPA's per-request usage queue feeds a local 7-day ledger, so the tooltip shows the accounts actually
|
|
49
|
+
- **In-use account detection**: CPA's per-request usage queue feeds a local 7-day ledger, so the tooltip shows the accounts that actually served the selected model within the current refresh cycle (sorted by last use, with an "in use" badge and request/token totals) and collapses the rest under "Other accounts". The in-use window follows the card's refresh interval.
|
|
50
50
|
- Account probes run through a bounded pool with a per-request timeout — one hung upstream can never stall the refresh cycle.
|
|
51
51
|
- Keeps the last successful snapshot across transient refresh failures and reuses rings across DSH screen remounts.
|
|
52
52
|
- Colors: green ≥20% remaining, amber <20%, red exhausted/error, gray loading or missing a management key.
|
|
@@ -182,7 +182,7 @@ Point the plugin's manual instance input at the mock to see a full five-account
|
|
|
182
182
|
- **Where are my keys stored?** In this browser's `localStorage` only. Quota requests go straight from the browser to each instance; the DSH host never sees your keys.
|
|
183
183
|
- **Switching browsers?** Use **Export config / Import config** on the card to move instances and keys between browsers. The exported JSON is plaintext — store it carefully.
|
|
184
184
|
- **Tooltip shows every account?** The tooltip filters accounts by what each one actually serves, using CPA's own per-auth model registry first, then the model name and the DSH provider id as fallbacks. Only when a model matches no registry entry and no family signal can it be pinned down does the tooltip list the remaining usable accounts — and it says so when it does.
|
|
185
|
-
- **Tooltip shows fewer accounts than before?** The in-use filter is on by default: accounts that served the selected model
|
|
185
|
+
- **Tooltip shows fewer accounts than before?** The in-use filter is on by default: accounts that served the selected model within the current refresh cycle are pinned with an "in use" badge, the rest collapse under "Other accounts". Turn off "只显示使用中的账号" on the card to see every candidate again.
|
|
186
186
|
- **"usage stats off" badge?** Enable usage statistics in your CPA config (`usage-statistics-enabled: true`) — the in-use detection reads CPA's per-request usage queue and needs that toggle on. Everything else works without it.
|
|
187
187
|
|
|
188
188
|
## Community
|
package/README.zh.md
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
- 支持多个 CLIProxyAPI 实例和多个账号:悬浮卡片按当前模型过滤,设置面板始终展示全部。
|
|
47
47
|
- 窗口按 `5 小时 → 每周 → 每月 → 每日` 排序;圆环优先使用第一个可用窗口。
|
|
48
48
|
- 支持 Codex、Claude、Antigravity、Gemini CLI、Kimi、xAI/Grok;其它 CPA 厂商至少显示账号状态和近期请求活动。
|
|
49
|
-
- **使用中账号识别**:CPA 的逐请求用量队列喂给本地 7
|
|
49
|
+
- **使用中账号识别**:CPA 的逐请求用量队列喂给本地 7 天账本,悬浮卡片显示当前刷新周期内真正服务过当前模型的账号(按最后使用排序,带「使用中」徽章与请求/Token 统计),其余折叠进「其它账号」。窗口跟随卡片的刷新间隔。
|
|
50
50
|
- 账号探测走有界并发池并带单请求超时——一个挂起的上游绝不会卡住整个刷新周期。
|
|
51
51
|
- 刷新失败时保留上一次成功数据;DSH 切屏重挂载模型按钮时复用圆环,避免闪烁。
|
|
52
52
|
- 颜色含义:绿色 ≥20% 剩余,黄色 <20%,红色已耗尽/错误,灰色加载中或未配置密钥。
|
|
@@ -182,7 +182,7 @@ node tests/mock-cpa.mjs # 可选:在 http://127.0.0.1:8317 起一个假 CP
|
|
|
182
182
|
- **密钥存在哪?** 只存当前浏览器的 `localStorage`。额度请求由浏览器直达各实例,DSH 宿主完全接触不到你的密钥。
|
|
183
183
|
- **换浏览器?** 用卡片里的「导出配置 / 导入配置」在浏览器之间迁移实例与密钥。导出的 JSON 是明文,注意保管。
|
|
184
184
|
- **悬浮卡片显示了全部账号?** 卡片按每个账号「实际服务什么模型」过滤,优先读 CPA 的每账号模型注册表(auth-files/models),模型名和 DSH 提供方 id 只作兜底。仅当某个模型在注册表里无记录、且无法从名称判断归属时,才会列出剩余可用账号,并在卡片里注明。
|
|
185
|
-
- **悬浮卡片账号变少了?**
|
|
185
|
+
- **悬浮卡片账号变少了?** 「只显示使用中」开关默认开启:当前刷新周期内实际服务过当前模型的账号会置顶并带「使用中」徽章,其余折叠在「其它账号」里。关掉卡片上的开关即可回到全量候选视图。
|
|
186
186
|
- **「用量统计未开启」徽章?** 在 CPA 配置里开启 `usage-statistics-enabled: true`——使用中识别读取的是 CPA 的逐请求用量队列,需要这个开关;不开也不影响其它功能。
|
|
187
187
|
|
|
188
188
|
## 社区
|
package/lib/client.js
CHANGED
|
@@ -49,6 +49,9 @@ window.__ModuleLoader__.load({
|
|
|
49
49
|
const USAGE_LEDGER_MAX_AGE = 7 * 24 * 60 * 60 * 1000;
|
|
50
50
|
const USAGE_LEDGER_MAX_EVENTS = 4000;
|
|
51
51
|
const USAGE_ACTIVE_WINDOW = 24 * 60 * 60 * 1000;
|
|
52
|
+
/** In-use window follows the card's refresh interval (set by applyConfig)
|
|
53
|
+
* so "in use" means "served within the current refresh cycle". */
|
|
54
|
+
let usageWindowMs = USAGE_ACTIVE_WINDOW;
|
|
52
55
|
const USAGE_STATS_TTL = 10 * 60 * 1000;
|
|
53
56
|
const LS_ACTIVE_ONLY = "dsh-cpa-quota:active-only";
|
|
54
57
|
const W5H = 5 * 60 * 60;
|
|
@@ -1478,6 +1481,16 @@ window.__ModuleLoader__.load({
|
|
|
1478
1481
|
* records are dropped. */
|
|
1479
1482
|
function pollUsageEvents(instance, base, entries) {
|
|
1480
1483
|
const ledger = usageLedgerFor(base);
|
|
1484
|
+
// One-time migration: ledger events recorded by PRE-0.7.2 builds were
|
|
1485
|
+
// keyed by the auth-file NAME; re-key them to the rendered display
|
|
1486
|
+
// name so the in-use match covers history too. Idempotent.
|
|
1487
|
+
const nameByFile = new Map(entries.map((e) => [text(e.name), accountDisplayName(e)]));
|
|
1488
|
+
let migrated = false;
|
|
1489
|
+
for (const ev of ledger.ev) {
|
|
1490
|
+
const mapped = nameByFile.get(ev.a);
|
|
1491
|
+
if (mapped !== undefined && mapped !== ev.a) { ev.a = mapped; migrated = true; }
|
|
1492
|
+
}
|
|
1493
|
+
if (migrated) persistUsageLedger(base, ledger);
|
|
1481
1494
|
const fpSet = new Set(ledger.fp);
|
|
1482
1495
|
const nameByIndex = new Map(entries.map((e) => [String(e.auth_index ?? e.authIndex), accountDisplayName(e)]));
|
|
1483
1496
|
return fetchJSON(`${instance.base}${USAGE_QUEUE_PATH}`, {
|
|
@@ -1526,7 +1539,7 @@ window.__ModuleLoader__.load({
|
|
|
1526
1539
|
/** Names with ANY ledger activity inside the window → last-used ts. */
|
|
1527
1540
|
function usageActiveNamesAny(base, now = Date.now()) {
|
|
1528
1541
|
const ledger = usageLedgerFor(base);
|
|
1529
|
-
const cutoff = now -
|
|
1542
|
+
const cutoff = now - usageWindowMs;
|
|
1530
1543
|
const lastByAccount = new Map();
|
|
1531
1544
|
for (const ev of ledger.ev) {
|
|
1532
1545
|
if (ev.t < cutoff) continue;
|
|
@@ -1539,7 +1552,7 @@ window.__ModuleLoader__.load({
|
|
|
1539
1552
|
/** Names that served the SELECTED model inside the window. */
|
|
1540
1553
|
function usageActiveNames(base, modelId, now = Date.now()) {
|
|
1541
1554
|
const ledger = usageLedgerFor(base);
|
|
1542
|
-
const cutoff = now -
|
|
1555
|
+
const cutoff = now - usageWindowMs;
|
|
1543
1556
|
const lastByAccount = new Map();
|
|
1544
1557
|
for (const ev of ledger.ev) {
|
|
1545
1558
|
if (ev.t < cutoff || !modelListMatches(ev.m, modelId)) continue;
|
|
@@ -2609,7 +2622,7 @@ body[data-ds-dark-theme] .cpa-q-select{color-scheme:dark}
|
|
|
2609
2622
|
window.dispatchEvent(new CustomEvent(EV_CONFIG));
|
|
2610
2623
|
},
|
|
2611
2624
|
}),
|
|
2612
|
-
ZH ? "
|
|
2625
|
+
ZH ? "只显示使用中的账号(每个刷新周期内用过当前模型)" : "Only show accounts that served the current model in the current refresh cycle"),
|
|
2613
2626
|
...rows.map((row) => {
|
|
2614
2627
|
const key = baseKey(row.baseURL);
|
|
2615
2628
|
const status = instanceStatus(row);
|
|
@@ -2712,6 +2725,8 @@ body[data-ds-dark-theme] .cpa-q-select{color-scheme:dark}
|
|
|
2712
2725
|
// uninjected properties; plugin config arrives via this argument only.
|
|
2713
2726
|
let config = readConfig(configArg);
|
|
2714
2727
|
let refreshMs = config.refreshMinutes * 60 * 1000;
|
|
2728
|
+
// "In use" tracks the current refresh cycle (also set on config changes).
|
|
2729
|
+
usageWindowMs = refreshMs;
|
|
2715
2730
|
|
|
2716
2731
|
/** model label/id (lowercased) → { baseURL, modelId, providerId } */
|
|
2717
2732
|
let modelIndex = new Map();
|
|
@@ -2766,6 +2781,8 @@ body[data-ds-dark-theme] .cpa-q-select{color-scheme:dark}
|
|
|
2766
2781
|
function applyConfig(next) {
|
|
2767
2782
|
config = next;
|
|
2768
2783
|
refreshMs = config.refreshMinutes * 60 * 1000;
|
|
2784
|
+
// "In use" tracks the current refresh cycle.
|
|
2785
|
+
usageWindowMs = refreshMs;
|
|
2769
2786
|
rebuildInstances();
|
|
2770
2787
|
scheduleDecorate();
|
|
2771
2788
|
restartQuotaTimer();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-client-ui-cpa-quota",
|
|
3
3
|
"description": "CliProxyAPI quota indicator: a native-styled ring left of the composer model name; hover shows per-account provider quotas, subscription plans, and status for Codex, Claude, Antigravity, Gemini CLI, Kimi, xAI/Grok, and other CPA auth providers. Targets the current dsh plugin contract (settings-namespace-keyed plugin cards).",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.4",
|
|
5
5
|
"author": "wkscc310",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|