dsh-opencode-go 0.2.0 → 0.2.1
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.en.md +20 -18
- package/README.md +26 -18
- package/THIRD_PARTY_NOTICES.md +5 -1
- package/docs/advanced.en.md +17 -13
- package/docs/advanced.md +18 -13
- package/docs/assets/usage-history-desktop.jpg +0 -0
- package/docs/assets/usage-history-mobile.jpg +0 -0
- package/docs/assets/usage-history-models.jpg +0 -0
- package/docs/development.md +23 -9
- package/docs/usage-analytics.en.md +34 -85
- package/docs/usage-analytics.md +34 -85
- package/docs/verification.md +50 -13
- package/lib/build-info.json +1 -1
- package/lib/client.js +2111 -2257
- package/lib/free-http-worker.js +32 -0
- package/lib/index.js +3078 -1899
- package/lib/types/accounts.d.ts +2 -2
- package/lib/types/adapter.d.ts +24 -9
- package/lib/types/analytics.d.ts +22 -332
- package/lib/types/catalog.d.ts +35 -76
- package/lib/types/client/AnalyticsDialog.d.ts +11 -18
- package/lib/types/client/Section.d.ts +3 -13
- package/lib/types/client/UsagePill.d.ts +10 -3
- package/lib/types/client/controller.d.ts +10 -8
- package/lib/types/client/dashboard-copy.d.ts +58 -0
- package/lib/types/client/index.d.ts +9 -0
- package/lib/types/client/presentation.d.ts +36 -72
- package/lib/types/config.d.ts +5 -1
- package/lib/types/contracts.d.ts +80 -25
- package/lib/types/conversion.d.ts +10 -2
- package/lib/types/free-channel.d.ts +21 -0
- package/lib/types/free-http-worker.d.ts +1 -0
- package/lib/types/free-policy.d.ts +4 -0
- package/lib/types/free-protocol.d.ts +16 -0
- package/lib/types/free-runtime.d.ts +2 -0
- package/lib/types/free-socks-tunnel.d.ts +4 -0
- package/lib/types/free-transport.d.ts +19 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/pricing.d.ts +29 -0
- package/lib/types/sdk-types.d.ts +1577 -2890
- package/lib/types/transport.d.ts +13 -5
- package/lib/vendor-licenses.txt +79 -55
- package/package.json +4 -4
- package/docs/assets/usage-panel.png +0 -0
|
@@ -2,107 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
[Back to README](../README.en.md) · [简体中文](usage-analytics.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The dashboard shows official history for the workspace belonging to the selected OpenCode key. It can include calls from other clients and does not attribute calls to this plugin. Coverage of anonymous Free calls is not guaranteed.
|
|
6
6
|
|
|
7
|
-
## Entry points
|
|
7
|
+
## Entry points and accounts
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- the **Usage analytics** card on the settings page: the same folding card the model and advanced sections use. Unfolded it has two rows — **Dashboard**, which opens the dashboard, and **Theme**, which picks the style. Folded, its trailing note names the style in force.
|
|
9
|
+
Open it from the conversation's expanded usage pill or the sidebar dashboard button. Settings no longer include a usage analytics card or theme picker.
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
The dashboard has an independent viewing-account selector, defaulting to the account currently used for inference. Changing it only changes the dashboard scope; it does not switch the account for subsequent conversations or combine all saved accounts. The dashboard's five-hour, weekly and monthly quota windows follow the selected account and use official quota percentages.
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
## Official data source
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
- `readSession(id)` returns the complete event log, including closed sessions;
|
|
18
|
-
- only events are scanned; the dashboard never parses compressed logs on disk or makes a session live. After an app restart, the Host reads session events again; the plugin does not keep an on-disk fold cache.
|
|
15
|
+
The Host uses the selected account's key to request the official daily CSV:
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
```text
|
|
18
|
+
https://opencode.ai/console/api/v2/usage/export?range=7d|30d|90d
|
|
19
|
+
```
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
Totals, daily charts and model detail all come from one CSV snapshot, avoiding differences between endpoints queried at different times. Ranges are today, 7 days, 30 days and 90 days; today filters the 7-day CSV to the current UTC date. All dates use UTC, with missing dates filled with zero to keep the daily series continuous. Official daily aggregates may be delayed, so refreshing may not immediately include a recently completed call.
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
The Host stores and uses keys. Normal reports send the browser only aggregate numbers and grouping fields such as provider, model and day, without conversation content, member fields or keys. An official CSV explicitly downloaded by the user may contain official member fields.
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
History queries require an official model gateway configuration before the Host sends a key to the `opencode.ai` Console. Third-party gateways show an unsupported state and their keys are not sent to Console. Queries retain the configured proxy path, cancellation, timeouts and response-size limits.
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
- `compaction/summary` events on the same route (the summarization request);
|
|
30
|
-
- the pre-0.1.16 `opencode-go` route, but only for requests before 2026-09-30 UTC. Later `opencode-go` records belong to DSH's native route and are excluded.
|
|
27
|
+
## Accounting
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
| Metric | Source |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| Requests | Sum of official CSV request counts |
|
|
32
|
+
| Input / output tokens | Official input and output fields, summed separately |
|
|
33
|
+
| Cache-read tokens | Sum of the official cache-read field |
|
|
34
|
+
| Cache-write tokens | Sum of official 5-minute and 1-hour cache-write fields |
|
|
35
|
+
| Total tokens | Input + output + cache read + both cache-write fields |
|
|
36
|
+
| Official usage amount | Exact sum of `cost_micro_cents`; `1 USD = 100,000,000 cost_micro_cents` |
|
|
37
|
+
| Model grouping | Provider + model; identical model names from different providers stay separate |
|
|
33
38
|
|
|
34
|
-
|
|
35
|
-
- fork-inherited prefixes (sequence numbers strictly below `inheritedEventCount`; the boundary slot belongs to this session, matching the host's half-open `isOwnSeq`);
|
|
36
|
-
- model calls that never enter the session log (for example some title generation);
|
|
37
|
-
- model calls that cannot be attributed to this plugin's route (the log lacks a routing header or model name) — the footer counts them as unattributed activity, without tokens or cost;
|
|
38
|
-
- failed requests whose gateway charge is not represented by a usage record; they appear only as unsettled attempts.
|
|
39
|
+
The amount comes directly from official records and is labeled **official usage amount**. It does not mean an additional charge beyond the Go subscription. The dashboard does not reprice history using the current model catalog or derive quota percentages from amounts.
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
Only source-supported metrics are shown. Local session coverage, summary-call counts, unsettled attempts and unattributed activity are not reported or filled with misleading zeros. UTC zero-filling only means the official CSV contains no records for that day.
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
## Presentation and refresh
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
- A wide-screen dialog becomes full-screen on narrow screens, with stacked daily token bars or daily request bars, model rankings and detail.
|
|
46
|
+
- Settings, the pill, expanded sidebar and dashboard share warm paper / charcoal surfaces and terracotta accents, following the Host's light/dark mode. There is no theme picker. Locally installed Anthropic Serif / Sans / Mono fonts are preferred, with system and CJK serif fallbacks. Settings recolor the Host's existing controls only within the plugin section.
|
|
47
|
+
- History queries run only when opening the dashboard, changing the viewing account or range, or refreshing manually. There is no background history polling; closing the dashboard cancels its active query.
|
|
48
|
+
- The Host caches official reports and CSVs for 30 seconds, isolated by credential, account, network configuration, range and UTC date. A forced manual refresh bypasses the cache.
|
|
49
|
+
- Authentication, permission, network and data-format errors show an explicit failure, without falling back to local session scans or fabricated zero usage.
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
- billed input = input + cache read + cache write (pi-ai's input excludes caches);
|
|
48
|
-
- usage degrades per field: a present-but-malformed component zeroes only itself while the valid components still count; a request counts as missing usage only when input and output are both missing or malformed, and missing usage is never zero-filled into the estimate;
|
|
49
|
-
- cache hit rate = cache read / (input + cache read + cache write): output tokens never enter the denominator, matching the repository's existing session statistic; a zero denominator shows 0.0%.
|
|
50
|
-
|
|
51
|
-
### Estimate
|
|
52
|
-
|
|
53
|
-
- current models.dev rates for `opencode-go` (USD per 1M tokens) — all history is estimated at the rates in force at query time (models.dev publishes no historical rates);
|
|
54
|
-
- the highest matching context tier prices the whole request;
|
|
55
|
-
- DeepSeek V4.1 Flash and V4 Pro double during the documented peak window;
|
|
56
|
-
- a model whose upstream cost block is missing or malformed is treated as unpriced: it adds no cost, is counted separately, and its cost cell shows an **unpriced** tag; such models were previously priced at zero silently — the new display is louder but honest. A genuinely free model with a published, legal (including all-zero) cost block still prices at zero;
|
|
57
|
-
- the lead sentence only states an amount when at least one request was priced: with `pricedRequests === 0` it puts `—` where the amount would go (the same meaning as the KPI's `-`), so "cannot be priced" is never rendered as `$0.00`;
|
|
58
|
-
- when the price table fails or times out (at most a 4-second wait) the last successful table is used; with no usable table at all, every model that appeared is listed as unpriced;
|
|
59
|
-
- amounts accumulate as integer micro-USD; this is an estimate, not an invoice.
|
|
60
|
-
|
|
61
|
-
## Model detail
|
|
62
|
-
|
|
63
|
-
Each model row shows only the display name plus requests, input, output, cache read, cost, and cost share; the invocation id and the Go / Go Plus monthly limits are no longer rendered (the snapshot data remains in `src/analytics.ts`).
|
|
64
|
-
|
|
65
|
-
The cost cell has three states: priced requests render the estimate (even when some requests in the same row are unpriced); `pricedRequests === 0` with `unpricedRequests > 0` renders the **unpriced** tag; a row whose requests all lack usage (both pricing counters are zero) renders `—`, meaning the row carries no usable data rather than "free". The share cell renders `—` whenever there is no amount, and the composition note's "also free or unpriced" line only lists genuinely unpriced models, no longer mixing in missing-usage rows.
|
|
66
|
-
|
|
67
|
-
The official `/usage` five-hour, weekly, and monthly percentages remain authoritative; the dashboard never derives them from the estimate. The quota row now shows only the window name, percentage, bar, reset time and the near-limit tick — the "plenty left / near limit" wording and the remaining-percentage line are gone.
|
|
68
|
-
|
|
69
|
-
The daily view is pointer-interactive: hovering a calendar cell (or within 5px of one) or any point on the trend shows that day's estimate, request count and tokens, highlights the same bucket in both views and draws a vertical guide. Selection is computed from the distance to the nearest cell: moving more than 5px away from every cell — into the gaps between cells — clears it immediately instead of holding the previous bucket, and leaving the chart area clears it too. Per-model, per-day breakdowns are not part of the current contract, so the tooltip reports the day's totals.
|
|
70
|
-
|
|
71
|
-
The calendar is laid out densely by calendar date across the selected range (a 30-day range always fills 30 cells, capped at 366): dates missing from `byDay` become zero-value cells, so every cell always sits under its true weekday instead of drifting when activity skips dates. Days without activity are hoverable too and report $0.00 / 0 requests; the trend shares this dense series, so the hover index matches in both views. The daily average is computed over the range's calendar days (including days without activity), the same denominator as the KPI band.
|
|
72
|
-
|
|
73
|
-
## Themes and the pill
|
|
74
|
-
|
|
75
|
-
- Four styles: **Silent Black**, **Graphite** (default), **Sea Salt**, and **Warm Sand**. Each has a dark and a light variant that follows DSH's color scheme.
|
|
76
|
-
- The only switch is the **Theme** row inside the settings page's Usage analytics card, where each option previews its own surface, accent and text colors. The choice is stored in the browser, not in the settings document.
|
|
77
|
-
- The pill popover and the dashboard no longer carry a switch; they render whatever style is selected.
|
|
78
|
-
- The pill no longer carries the `Go ·` prefix; with multiple accounts it shows the active account's full name, truncated with an ellipsis when long, with the complete name kept in the button title and accessible label while the expanded panel still offers every account. Account switching is unchanged, and pill rebuilds triggered by account or connection changes no longer close an open dashboard.
|
|
79
|
-
- The settings page keeps DSH's own appearance and is not affected by these themes.
|
|
80
|
-
|
|
81
|
-
## Scan limits and performance
|
|
82
|
-
|
|
83
|
-
- by default, at most **500 sessions**, **500,000 events**, and **12 seconds**, read with up to eight concurrent session reads (falling back to serial for a Host that cannot read concurrently);
|
|
84
|
-
- exceeding a limit marks the report incomplete with its cause (session slice / event budget / time budget); the footer also reports how many sessions were left unread when the budget or cap stopped the scan, without implying the range was fully covered;
|
|
85
|
-
- **Scan more history** raises the session cap to 1,000 then 2,000; the choice is stored in the browser and survives reopening the panel;
|
|
86
|
-
- session folds are cached in memory under an LRU policy for at most five seconds; live sessions are re-read on closing, and restarting clears the cache. Eviction happens after scanning, while each report uses its own scan results;
|
|
87
|
-
- the price table is fetched in parallel with the scan, waiting at most 4 seconds;
|
|
88
|
-
- the footer splits list / scan / pricing timings;
|
|
89
|
-
- within one open, the window end is taken once at open time, so re-entering the same range does not rescan; **Refresh** forces a new scan;
|
|
90
|
-
- without a reusable in-memory cache, the scan reads target sessions under those budgets; sessions are read again after restarting or after the five-second reuse window;
|
|
91
|
-
- a range already seen in this open renders its previous report immediately and revalidates in the background, explicitly labeled as the previous scan while loading;
|
|
92
|
-
- closing the dialog aborts the running scan; there is no background polling.
|
|
93
|
-
|
|
94
|
-
## Query and report contracts
|
|
95
|
-
|
|
96
|
-
`src/contracts.ts` validates query dates, timezone and scan limits. Report types and aggregation live in `src/analytics.ts`. RPC checks the response envelope without manually revalidating every aggregate field. The host and client ship in the same package.
|
|
97
|
-
|
|
98
|
-
## Known limitations
|
|
99
|
-
|
|
100
|
-
- session request headers carry no account identity, so history cannot be split per account; the dashboard totals every saved account;
|
|
101
|
-
- a request that fails or is canceled before usage may still be billed by the gateway but adds no cost;
|
|
102
|
-
- summaries count as requests, so the request total includes them;
|
|
103
|
-
- device or gateway clock skew can move a request across a peak boundary or a day boundary;
|
|
104
|
-
- models.dev rates and the official plan page can drift; the footer shows the price update time.
|
|
51
|
+
The usage pill's existing quota refresh is independent of history queries.
|
|
105
52
|
|
|
106
53
|
## Verification
|
|
107
54
|
|
|
108
|
-
|
|
55
|
+
An existing manual check on 2026-11-06 used the current desktop key without Cookie or organization headers. All four official Console history endpoints returned HTTP 200, with matching 30-day totals of **7,064 requests, 1,105,009,939 tokens and 3,152,640,453 cost_micro_cents**. This established that the daily CSV supplies the dashboard data; it does not establish identical permissions for every account or complete anonymous Free coverage.
|
|
56
|
+
|
|
57
|
+
See [verification notes](verification.md) for this implementation's automated tests, build and UI checks. Unfinished checks are marked separately.
|
package/docs/usage-analytics.md
CHANGED
|
@@ -2,107 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
[返回 README](../README.md) · [English](usage-analytics.en.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
用量看板展示所选 OpenCode Key 所属工作区的官方历史用量。数据可能包含其他客户端的调用,不能据此判断某次调用来自本插件;匿名 Free 调用的覆盖不作保证。
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 入口与账号
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- 设置页的「用量统计」卡片:与「可用模型」「高级设置」同一种折叠卡片,点击展开后分两栏——第一栏「看板」打开看板,第二栏「主题」切换风格。折叠时右侧显示当前风格名。
|
|
9
|
+
从对话用量胶囊展开后的看板按钮,或侧栏看板按钮打开。设置页不再提供用量统计卡片或主题选择器。
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
看板有独立的查看账号选择器,默认选择当前调用账号。切换查看账号只改变看板范围,不会切换后续对话使用的账号,也不会合并所有已保存账号。看板内的 5 小时、每周、每月额度窗口均跟随所选账号,百分比以官方额度接口为准。
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
## 官方数据来源
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
- `readSession(id)` 读取完整事件日志,包含已关闭会话;
|
|
18
|
-
- 只扫描事件,不解析磁盘上的压缩日志,也不把会话加载为实时。重启后由宿主重新读取会话事件,不使用插件磁盘折叠缓存。
|
|
15
|
+
Host 使用所选账号的 Key 请求官方每日 CSV:
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
```text
|
|
18
|
+
https://opencode.ai/console/api/v2/usage/export?range=7d|30d|90d
|
|
19
|
+
```
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
一份报告的总计、每日图表与模型明细都从同一个 CSV 快照生成,避免多个接口在不同时间返回数据造成差异。支持今日、7 天、30 天、90 天;「今日」从 7 天 CSV 中筛选 UTC 当日。日期统一按 UTC,区间内缺少记录的日期补零,保持日序列连续。官方每日汇总可能延迟,刷新不保证立即看到刚结束的调用。
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
### 计入的请求
|
|
27
|
-
|
|
28
|
-
- `dsh-opencode-go` 路由下的 `assistant/message`(每次已结算的模型请求);
|
|
29
|
-
- 同一路由下的 `compaction/summary`(上下文压缩的摘要请求);
|
|
30
|
-
- `opencode-go` 旧路由,仅限 0.1.16 改名(2026-09-30 UTC)之前的请求;之后的 `opencode-go` 视为 DSH 原生路由,不计入。
|
|
31
|
-
|
|
32
|
-
### 不计入
|
|
33
|
-
|
|
34
|
-
- DSH 原生 OpenCode Go 路由与其他 provider;
|
|
35
|
-
- fork 继承的前缀(严格低于 `inheritedEventCount` 的序号;边界槽位属于本会话,与宿主 `isOwnSeq` 的半开区间一致);
|
|
36
|
-
- 未写入会话日志的模型调用(例如部分会话标题生成);
|
|
37
|
-
- 无法归属到插件路由的模型调用(日志缺少路由头或模型名)——页脚以"未归属活动"单独计数,不计 token 与金额;
|
|
38
|
-
- 已失败的请求中网关可能已经计费、但日志里没有 usage 的调用(这类只会计入"未结算尝试")。
|
|
39
|
-
|
|
40
|
-
### 请求时间
|
|
41
|
-
|
|
42
|
-
优先取同一 `turn:step` 的 `step/start` 时间(请求开始);该键缺失(遗留或损坏的日志)时取本会话最近一次 `step/start`;整段会话没有任何开始事件时才退回消息事件时间,旧路由判定随请求开始时间自然修正。压缩摘要使用事件时间。区间为半开区间 `[from, to)`,按浏览器传入的 IANA 时区分桶。
|
|
43
|
-
|
|
44
|
-
### token
|
|
45
|
-
|
|
46
|
-
- 输入、输出、缓存读、缓存写分别统计;
|
|
47
|
-
- 计费输入 = 输入 + 缓存读 + 缓存写(pi-ai 的 input 不含缓存);
|
|
48
|
-
- usage 按字段降级:存在的分量畸形只把该分量记 0,其余有效分量照常入账;仅当输入与输出同时缺失或畸形时,整条请求计入"缺用量",不补零到金额。
|
|
49
|
-
- 缓存命中率 = 缓存读 / (输入 + 缓存读 + 缓存写):输出 token 不计入分母,与仓库既有的会话统计口径一致;分母为 0 时显示 0.0%。
|
|
50
|
-
|
|
51
|
-
### 金额
|
|
23
|
+
Key 由 Host 保存并使用。常规报告只向浏览器传递聚合数字,以及 provider、model、day 等分组字段,不含会话正文、成员字段或 Key。用户主动下载官方 CSV 时,文件可包含官方导出的成员字段。
|
|
52
24
|
|
|
53
|
-
|
|
54
|
-
- 有上下文阶梯的模型,按计费输入选择最高命中的阈值;
|
|
55
|
-
- DeepSeek V4.1 Flash / V4 Pro 在峰时整体 ×2;
|
|
56
|
-
- 上游缺少价目块或价目块损坏的模型按"未计价"处理:不计金额、单独计数,费用列显示 `未计价` 标签;此前这类模型被静默按 0 价计费,现在更显眼但更诚实。上游发布了合法价目(含全零)的真免费模型仍按 0 价计费;
|
|
57
|
-
- 首句只在一份报告里存在可计价请求时才给出金额:`pricedRequests === 0` 时用「—」代替金额(与 KPI 区的 `-` 同义),不会把"无法计价"写成 `$0.00`;
|
|
58
|
-
- 价目表拉取失败或超时(至多等 4 秒)时回退到最近一次成功的价目表;完全没有任何可用价目时,出现过的模型全部列为未计价;
|
|
59
|
-
- 金额以整数微美元累计,页面显示为美元;这是估算,不是账单。
|
|
25
|
+
只有官方模型网关配置支持历史查询,Host 才会将 Key 发给 `opencode.ai` Console。第三方网关配置显示不支持,不会把其 Key 发送到 Console。查询沿用已配置的代理路径,并保留取消、超时和响应体大小限制。
|
|
60
26
|
|
|
61
|
-
##
|
|
62
|
-
|
|
63
|
-
模型行只显示模型名称,以及请求、输入、输出、缓存读、花费与花费占比;调用名与 Go / Go Plus 月限额不再出现在看板上(限额快照数据仍保留在 `src/analytics.ts`)。
|
|
64
|
-
|
|
65
|
-
费用列分三态:有计价请求时显示估算金额(哪怕同一模型还有部分请求未计价);`pricedRequests === 0` 且 `unpricedRequests > 0` 时显示 `未计价` 标签;全部请求都缺用量(两个计价计数器均为 0)时显示 `—`,表示这一行没有任何可用数据,而不是"免费"。占比列在无金额时同样显示 `—`;Composition 的"另有免费或未计价模型"只列真正未计价的模型,缺用量模型不再混入。
|
|
66
|
-
|
|
67
|
-
官方 `/usage` 的 5 小时 / 每周 / 每月百分比仍是额度权威值;看板不根据金额反推百分比。额度栏只显示窗口名称、百分比、进度、重置时间与临近上限的阈值刻线,不再重复"充足 / 接近上限 / 余量"等文字。
|
|
68
|
-
|
|
69
|
-
按天区域支持指针悬停:把鼠标移到日历格子上(或靠近格子 5px 以内)或折线上的任意一天,会显示该日的估算金额、请求数与 Token,同时在日历与折线上高亮同一天并画出竖向参考线。判定按"指针到最近格子的距离"计算:移到格子之间的空白处超过 5px 就立即取消选中,不会保留上一格的状态;指针离开图表区域同样清除。按模型、按天的逐日拆分不在当前契约内,悬停只呈现当日合计。
|
|
70
|
-
|
|
71
|
-
日历按所选区间的每一个日历日稠密排布(30 天区间固定 30 格,上限 366 格),`byDay` 里缺失的日期补成零值格,所以每一格永远落在它真实的星期列下,不会因为中间空档而错位。没有活动的日子同样可以悬停,显示 $0.00 / 0 次;趋势图与日历共用这份稠密序列,悬停索引一一对应。"日均"按区间日历天数计算(分母包含没有活动的日子),与 KPI 区的日均为同一口径。
|
|
72
|
-
|
|
73
|
-
## 主题与胶囊
|
|
74
|
-
|
|
75
|
-
- 四套主题:**寂静黑**、**石墨**(默认)、**海盐青**、**暖砂**;每套都有深色与浅色版本,跟随 DSH 的明暗模式。
|
|
76
|
-
- 唯一的切换入口是设置页「用量统计」展开后的「主题」栏,每套风格用一张小样显示自己的表面色、强调色与文字色;偏好保存在浏览器本地(不写入设置文档)。
|
|
77
|
-
- 胶囊面板和看板不再提供切换,只按所选风格渲染。
|
|
78
|
-
- 胶囊不再带 `Go ·` 前缀;多账号时直接显示当前账号全名,名字过长时以省略号截断,完整名字保留在按钮标题与读屏标签中,展开面板仍可选择全部账号;账号切换逻辑不变。账号或连接变化引发的胶囊界面重建不再合上打开中的看板。
|
|
79
|
-
- 设置页保持 DSH 自己的外观,不受这套主题影响。
|
|
27
|
+
## 统计口径
|
|
80
28
|
|
|
81
|
-
|
|
29
|
+
| 项目 | 口径 |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| 请求数 | 汇总 CSV 的官方请求数 |
|
|
32
|
+
| 输入 / 输出 Token | 分别汇总官方输入、输出字段 |
|
|
33
|
+
| 缓存读 Token | 汇总官方 cache-read 字段 |
|
|
34
|
+
| 缓存写 Token | 合计官方 5 分钟与 1 小时 cache-write 字段 |
|
|
35
|
+
| 总 Token | 输入 + 输出 + 缓存读 + 两类缓存写 |
|
|
36
|
+
| 官方用量金额 | 精确累加 `cost_micro_cents`;`1 USD = 100,000,000 cost_micro_cents` |
|
|
37
|
+
| 模型分组 | 使用 provider + model;不同 provider 的同名模型分别统计 |
|
|
82
38
|
|
|
83
|
-
|
|
84
|
-
- 任一上限触发时,报告标记"不完整"并区分成因(会话数切片 / 事件预算 / 时间预算);页脚另报"预算或上限截止时未读取的会话"数,不暗示范围已完整覆盖;
|
|
85
|
-
- 可点击 **扫描更多历史** 将会话上限提升到 1000 / 2000;该选择保存在浏览器本地,重新打开面板后保留;
|
|
86
|
-
- 会话折叠结果仅在进程内按 LRU 缓存,最多复用 5 秒;live 会话关闭时重新读取,重启后重新扫描。逐出在每轮扫描结束后进行,当轮报告使用本轮实际读到的结果,不因逐出丢数;
|
|
87
|
-
- 价目表在扫描开始时并行拉取,至多等 4 秒;
|
|
88
|
-
- 页脚分列显示列表 / 扫描 / 定价耗时;
|
|
89
|
-
- 同一次打开内区间终点只取打开时刻一次,重复进入同一区间不会重复扫描,**刷新**按钮强制重新扫描;
|
|
90
|
-
- 没有可复用内存缓存时,扫描读取目标会话并遵守上述预算;重启或超过 5 秒复用窗口后重新读取;
|
|
91
|
-
- 本次打开已看过的区间再次选中时,立即渲染上次的报告并在后台重新校验,加载期间明确标注"以下为上一轮结果";
|
|
92
|
-
- 关闭弹窗会中止进行中的扫描,不后台轮询。
|
|
39
|
+
金额直接来自官方记录,称为「官方用量金额」,不等同于 Go 套餐之外的额外扣款。看板不使用当前模型价目表重算历史费用,也不根据金额反推订阅额度百分比。
|
|
93
40
|
|
|
94
|
-
|
|
41
|
+
只有来源能够支持的数据才会显示。看板不提供本地会话覆盖、摘要调用、未结算尝试或未归属活动等指标,也不会用零值代替这些未知数据。UTC 补零仅表示官方 CSV 在该日没有记录。
|
|
95
42
|
|
|
96
|
-
|
|
43
|
+
## 展示与刷新
|
|
97
44
|
|
|
98
|
-
|
|
45
|
+
- 看板在宽屏使用弹窗,窄屏使用全屏;提供 Token 堆叠日柱图或请求日柱图、模型排行与明细。
|
|
46
|
+
- 设置页、胶囊、展开侧栏和看板统一使用暖纸色 / 炭灰色与陶土色强调,跟随宿主明暗模式;不提供主题选择器。优先匹配本地 Anthropic Serif / Sans / Mono 字体,中文标题使用宋体等衬线回退。设置页中的宿主控件仅在插件区域内应用这套配色。
|
|
47
|
+
- 历史只在打开看板、切换查看账号、切换区间或手动刷新时查询,不后台轮询。关闭看板会取消正在进行的查询。
|
|
48
|
+
- Host 对官方报告与 CSV 使用 30 秒短缓存,按凭证、账号、网络配置、区间与 UTC 日期隔离;手动强制刷新绕过缓存。
|
|
49
|
+
- 鉴权、权限、网络或数据格式错误明确显示失败,不回退到本地会话扫描,也不显示伪造的零用量。
|
|
99
50
|
|
|
100
|
-
|
|
101
|
-
- 请求若在产生 usage 前失败/取消,可能已被网关计费,但不会产生金额。
|
|
102
|
-
- 压缩摘要与普通消息都按请求计入;"请求"数因此包含摘要调用。
|
|
103
|
-
- 设备时间或网关时钟偏差会影响峰时边界与按天分桶。
|
|
104
|
-
- models.dev 价格与官方套餐页可能短期不同步;页面显示价格更新时间。
|
|
51
|
+
额度胶囊原有的额度刷新与历史查询相互独立。
|
|
105
52
|
|
|
106
53
|
## 验证
|
|
107
54
|
|
|
108
|
-
|
|
55
|
+
2026-11-06 的既有手工检查中,当前桌面 Key 在不携带 Cookie 或组织请求头的情况下可访问四个官方 Console 历史接口,均返回 HTTP 200;30 天汇总一致为 **7,064 次请求、1,105,009,939 Token、3,152,640,453 cost_micro_cents**。该检查确认每日 CSV 可提供看板所需数据,不代表所有账号均有相同权限或匿名 Free 历史一定完整。
|
|
56
|
+
|
|
57
|
+
本轮实现的自动测试、构建和界面验证结果见[验证记录](verification.md);尚未完成的项目单独标记。
|
package/docs/verification.md
CHANGED
|
@@ -1,40 +1,77 @@
|
|
|
1
1
|
# Verification
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The recorded baseline on 2026-11-06 used macOS, Node `24.22.1`, npm `12.2.1`, development peers DSH `0.2.1-rc.5`, Cordis `4.0.5` and Schemastery `3.18.5`. The installed DSH `0.2.2-rc.1` CLI was also exercised with an isolated headless profile and the rebuilt plugin. Those results precede the official-history dashboard migration and do not validate its new implementation.
|
|
4
4
|
|
|
5
|
-
The minimum supported Host is DSH `>=0.2.1-rc.5`, with Cordis `~4.0.5`. The
|
|
5
|
+
The minimum supported Host is DSH `>=0.2.1-rc.5`, with Cordis `~4.0.5`. The package retains its `.` and `./client` export contracts. The current architecture and command reference are in [development](development.md).
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Recorded baseline before the dashboard migration
|
|
8
8
|
|
|
9
9
|
| Command | Result |
|
|
10
10
|
| --- | --- |
|
|
11
|
-
| `npm test` |
|
|
11
|
+
| `npm test` | 17 test files, 913 tests, zero failures or skipped tests |
|
|
12
12
|
| `npm run typecheck` | Host and browser TypeScript projects pass |
|
|
13
|
-
| `npm run check:dist` | All
|
|
13
|
+
| `npm run check:dist` | All 33 shipped build artifacts match an independent rebuild |
|
|
14
14
|
| `npm run verify` | Types, artifact comparison, full Vitest suite and installed-package smoke pass |
|
|
15
15
|
|
|
16
|
-
`verify` includes `typecheck`, `test:ci` and `verify:installed`; `test:ci` includes `check:dist` and `npm test`. CI runs this same acceptance path after `npm ci --strict-peer-deps` on Linux and Windows with Node 22.19 and 24. Those CI jobs are configured; the
|
|
16
|
+
`verify` includes `typecheck`, `test:ci` and `verify:installed`; `test:ci` includes `check:dist` and `npm test`. CI runs this same acceptance path after `npm ci --strict-peer-deps` on Linux and Windows with Node 22.19 and 24. Those CI jobs are configured; the baseline results above are from macOS.
|
|
17
|
+
|
|
18
|
+
## Official-history source check
|
|
19
|
+
|
|
20
|
+
A manual read-only check on 2026-11-06 used the current desktop key without Cookie or organization headers. Four official Console history endpoints returned HTTP 200. Their 30-day totals agreed:
|
|
21
|
+
|
|
22
|
+
| Metric | Recorded value |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| Requests | 7,064 |
|
|
25
|
+
| Total tokens | 1,105,009,939 |
|
|
26
|
+
| `cost_micro_cents` | 3,152,640,453 |
|
|
27
|
+
| Official usage amount (`1 USD = 100,000,000` units) | $31.52640453 |
|
|
28
|
+
|
|
29
|
+
The daily CSV at `https://opencode.ai/console/api/v2/usage/export?range=30d` supplied the fields needed for totals, daily charts and provider/model detail. The implementation uses that single snapshot rather than combining multiple endpoint snapshots. The check establishes access and consistency for this account at that time; it does not establish every account's permissions, immediate publication of recent usage or complete anonymous Free coverage. The official usage amount does not establish additional Go subscription charges.
|
|
30
|
+
|
|
31
|
+
## This dashboard migration
|
|
32
|
+
|
|
33
|
+
| Check | Current result |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| Official CSV parsing, exact totals, UTC date filling and today filtering | Pass: strict CSV fixtures, large integers, unit conversion, provider/model grouping and exact reconciliation |
|
|
36
|
+
| Credential/account/network/date cache isolation, force refresh, proxy path, cancellation, timeout and response limits | Pass: Host service and RPC tests, including independent cancellation and connection-change races |
|
|
37
|
+
| Key/member-field boundary, third-party gateway rejection and explicit upstream failures | Pass: report excludes member fields and keys; explicit permission, credential, gateway and malformed-response failures |
|
|
38
|
+
| Dashboard account/range/refresh, selected-account quotas and responsive light/dark UI | Pass: browser interaction tests plus real-browser 1280×1000 dark / 390×844 light checks, Chinese and English |
|
|
39
|
+
| `npm test` | Pass: 17 files, 886 tests; zero failures or skipped tests |
|
|
40
|
+
| `npm run typecheck` / `npm run compile` | Pass: Host and browser types and distribution build |
|
|
41
|
+
| `npm run check:dist` | Pass: all 31 shipped artifacts match an independent rebuild |
|
|
42
|
+
| `npm run verify` | Pass: types, build comparison, all tests and installed-package smoke |
|
|
43
|
+
|
|
44
|
+
The user-facing Free status card, its copy/styles, status/probe RPCs and manual inference probe have been removed. Normal requests retain Free error classification and passive Retry-After/backoff, including account isolation, cancellation and coexistence with Go.
|
|
45
|
+
|
|
46
|
+
Backend migration checks use synthetic CSVs, synthetic keys and loopback services, never a real user's key. The manual Console source check above is separate from automated tests.
|
|
47
|
+
|
|
48
|
+
The rewritten `GoAnalyticsService` was also checked directly against Console with the current desktop key on 2026-11-06: both the 30-day report and CSV export succeeded. The report contained 30 calendar days and 13 provider/model rows, with no member fields or key; the explicitly requested CSV retained its 14 official columns and contained no key. This was a read-only check, with no inference or profile changes.
|
|
49
|
+
|
|
50
|
+
Real-browser layout checks used synthetic preview data. The narrow view fills 390×844 without horizontal page overflow; charts and detail tables scroll within their own regions. Account/range changes and model detail were exercised. Previews: [desktop](assets/usage-history-desktop.jpg), [narrow light](assets/usage-history-mobile.jpg), [models](assets/usage-history-models.jpg).
|
|
17
51
|
|
|
18
52
|
## Regression scope
|
|
19
53
|
|
|
20
|
-
The
|
|
54
|
+
The test files import current modules directly, without resolver aliases or temporary path substitutions. Support helpers provide current host/account services, ConfigForm/React fixtures, offline model data, loopback gateways and proxies. Tests for removed journals, recovery state machines, diagnostic capture, global image pools and legacy host APIs are removed.
|
|
21
55
|
|
|
22
|
-
|
|
56
|
+
The pre-migration baseline covered:
|
|
23
57
|
|
|
24
58
|
- Real Cordis/Loader lifecycle, native SettingsForms and owner-scoped RPC, hot profile changes without adapter remounts, coexistence with the native provider and durable signed continuations.
|
|
25
59
|
- Account CRUD, generated-key ownership, the 20-account limit, queue serialization across reconnects, failed-write cleanup, read-only keys, stale operations and primary promotion. Real HTTP 401/403/429 and quota responses verify fallback before output, cooldown/expiry, cancellation and prevention of replay after output or charged usage.
|
|
26
60
|
- Model catalog discovery, missing/invalid metadata, online refresh and ETag/disk caching, endpoint isolation, lifecycle visibility, typed capacities, request snapshots, reasoning choices and OpenAI/Anthropic/Google wire behavior.
|
|
27
61
|
- Stable session and attribution headers, stream outcomes/deadlines, independent tool-role conversion, replay signatures, image offload projection, exact encoded-byte/count budgets and request-local preparation concurrency.
|
|
28
|
-
- Official quota/error codecs
|
|
62
|
+
- Official quota/error codecs. Official-history CSV behavior is covered by the migration checks above.
|
|
29
63
|
- Bounded JSON/gzip responses, safe gateway classification/redaction, actual HTTP CONNECT and SOCKS5 proxy paths, concurrent Google fetch binding and version-guarded SDK patch matching.
|
|
30
|
-
-
|
|
64
|
+
- Free-specific quota/client/access/rate-limit classification, Retry-After seconds and HTTP dates including clock skew, bounded exponential fallback, endpoint/proxy isolation, concurrent completion ordering and zero inference during cooldown. A normal Host request test limits Free and then completes Go streaming with its saved fixture key in the same mount.
|
|
65
|
+
- Settings Save/Reset/Discard and rejected/concurrent writes; AccountsCard additions, quota states, row actions and drag/keyboard sorting; model editor/search/visibility and refresh races; quota pill polling, account switching and retained readings; installed locale resolution and live Chinese/English changes. Dashboard and palette migration checks are listed separately above.
|
|
31
66
|
|
|
32
67
|
## Isolation and limits
|
|
33
68
|
|
|
34
|
-
Vitest gives each test a temporary `DSH_HOME`, serves synthetic models
|
|
69
|
+
Vitest gives each test a temporary `DSH_HOME`, serves complete synthetic `/models` declarations, uses loopback gateways/proxies and rejects other network requests. The installed-package smoke also uses a temporary home, synthetic credentials and metadata, and loopback inference. It resolves the built package through the consumer's ordinary Cordis resolver and verifies dual route discovery, streamed text, session headers, attribution, authorization and unload.
|
|
35
70
|
|
|
36
71
|
The pinned rc.5 UI primitives package references an unpublished `index.js.map`; Vite reports a non-fatal source-map warning. Undici also reports its experimental SOCKS5 notice during the real proxy test. Neither creates a failed test or nonzero command exit. The suite does not filter these messages or patch installed packages.
|
|
37
72
|
|
|
38
|
-
JSDOM verifies DOM interactions and accessible state. Its static ResizeObserver fixture does not establish browser layout geometry
|
|
73
|
+
JSDOM verifies DOM interactions and accessible state. Its static ResizeObserver fixture does not establish browser layout geometry or production latency; the real-browser preview checks above cover the recorded layouts. Loopback inference does not establish live gateway availability or paid model behavior. `npm run verify:headless -- /path/to/consumer` remains available for a consumer containing the official CLI; it is separate from the default acceptance path.
|
|
74
|
+
|
|
75
|
+
The installed Harness CLI loaded the rebuilt package from an isolated `DSH_HOME`: Go completed one loopback request with the expected synthetic credential and session header (exit 0). A single public `beam-free` request to the real Free gateway returned HTTP 429 / `FreeUsageLimitError`, now surfaced as `FREE_QUOTA` (exit 1, expected upstream rejection). This validates error propagation, not live Free availability; no paid upstream inference was used. The 53,305-second backoff and Go coexistence were verified with deterministic HTTP/RPC fixtures.
|
|
39
76
|
|
|
40
|
-
No
|
|
77
|
+
No publication or paid upstream inference was performed for the dashboard migration.
|
package/lib/build-info.json
CHANGED