opencode-tokenwatch 0.2.0 → 0.3.0

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 TTWK
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 TTWK
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.en.md CHANGED
@@ -1,96 +1,97 @@
1
- # opencode-tokenwatch
2
-
3
- **English** · [简体中文](./README.md)
4
-
5
- ![Sidebar](./assets/sidebar.png)
6
-
7
- Real-time token usage, cache analytics & performance dashboard plugin for OpenCode CLI.
8
-
9
- ## Features
10
-
11
- - **Sidebar panel** — Session-level and per-model real-time stats (requests, tokens, cache, latency, cost)
12
- - **Cache hit rate** — Inline progress bars with color thresholds and trend indicators (↑/↓)
13
- - **Performance metrics** — Time to first token (TTFT), tokens per second (TPS), end-to-end latency
14
- - **Token distribution** — Breakdown by role (system, user, Agent, Tool, etc.)
15
- - **Model pricing** — Input/cache/output unit prices
16
- - **`/usage` command** — HTML Report → JSON Export → Text Report → Settings
17
- - **HTML report** — Interactive ECharts dashboard, auto-opened in browser
18
- - **Multi-level collapse** — Panel, models, and sub-blocks collapsible with persisted state
19
- - **Language switching** — Auto-detect or manually switch between Chinese and English
20
- - **Per-request tracking** — TTFT/TPS/latency logged to JSONL for report analysis
21
- - **Adaptive coloring** — Colors auto-derived from theme
22
-
23
- ## Install
24
-
25
- ```sh
26
- npm install opencode-tokenwatch
27
- ```
28
-
29
- Add to `opencode.json` or `opencode.jsonc`:
30
-
31
- ```json
32
- {
33
- "$schema": "https://opencode.ai/config.json",
34
- "plugin": ["opencode-tokenwatch"]
35
- }
36
- ```
37
-
38
- ## Configuration
39
-
40
- ```jsonc
41
- {
42
- "plugin": ["opencode-tokenwatch"],
43
- "pluginConfig": {
44
- "opencode-tokenwatch": {
45
- "sidebar": {
46
- "showPerformance": true,
47
- "showPricing": false,
48
- "showTokenDistribution": false,
49
- "showTrend": true
50
- },
51
- "language": "auto"
52
- }
53
- }
54
- }
55
- ```
56
-
57
- | Option | Type | Default | Description |
58
- |--------|------|---------|-------------|
59
- | `sidebar.showPerformance` | boolean | `true` | Show TTFT/TPS/latency |
60
- | `sidebar.showPricing` | boolean | `true` | Show model pricing |
61
- | `sidebar.showTokenDistribution` | boolean | `true` | Show token distribution |
62
- | `sidebar.showTrend` | boolean | `true` | Show trend indicator |
63
- | `language` | `"auto"` / `"zh"` / `"en"` | `"auto"` | UI language |
64
-
65
- Settings can also be toggled via `/usage` → Settings, taking precedence over `pluginConfig`.
66
-
67
- ## Usage
68
-
69
- In OpenCode TUI, run `/usage`:
70
-
71
- - **HTML Report** — Pick a date range, generates a dashboard and opens it in browser
72
- - **JSON Export** — Exports full usage data to `~/.opencode/reports/`
73
- - **Text Report** — Exports Markdown report to `~/.opencode/reports/`
74
- - **Settings** — Toggle sidebar blocks, switch language
75
-
76
- ## Requirements
77
-
78
- - OpenCode CLI (with `opencode db` command)
79
- - Node.js 18+
80
-
81
- ## Build
82
-
83
- ```sh
84
- npm install
85
- npm run build
86
- ```
87
-
88
- ## Related
89
-
90
- - [opencode-throughput](https://github.com/Howardzhangdqs/opencode-throughput) — Real-time LLM performance monitoring (TTFT/TPS/latency/cost)
91
- - [opencode-visual-cache](https://github.com/Hotakus/opencode-visual-cache) — TUI sidebar cache hit rate visualization, token distribution analysis
92
- - [magic-context](https://github.com/cortexkit/magic-context/) — Cache-aware infinite context + cross-session memory system
93
-
94
- ## License
95
-
96
- MIT
1
+ # opencode-tokenwatch
2
+
3
+ **English** · [简体中文](./README.md)
4
+
5
+ ![Sidebar](./assets/sidebar.png)
6
+
7
+ Real-time token usage, cache analytics & performance dashboard plugin for OpenCode CLI.
8
+
9
+ ## Features
10
+
11
+ - **Sidebar panel** — Session-level and per-model real-time stats (requests, tokens, cache, latency, cost)
12
+ - **Cache hit rate** — Inline progress bars with color thresholds, trend indicators (↑/↓), and global weighted cache hit rate in the summary row
13
+ - **Performance metrics** — TTFT / TPS / End-to-end latency + P50/P95/P99 latency percentiles
14
+ - **Token distribution** — 5-bucket role breakdown (system, user, Agent, Tool and other with fallback and adaptive scaling)
15
+ - **Error rate statistics** — Detects and tracks failed requests (empty token response) and real-time error rate
16
+ - **Model pricing** — Input/cache/output unit prices
17
+ - **`/usage` command** — HTML Report JSON Export → Text Report → Settings
18
+ - **HTML report** — Interactive ECharts dashboard: Token distribution, performance percentiles, error rate analysis, model speed rankings (redesigned from overlapping scatter plots to horizontal bar charts), auto-opened in browser
19
+ - **Multi-level collapse** — Panel, models, and sub-blocks collapsible with persisted state
20
+ - **Language switching** — Auto-detect or manually switch between Chinese and English
21
+ - **Per-request tracking** — TTFT/TPS/latency logged to JSONL for report analysis
22
+ - **Adaptive coloring** — Colors auto-derived from theme
23
+
24
+ ## Install
25
+
26
+ ```sh
27
+ npm install opencode-tokenwatch
28
+ ```
29
+
30
+ Add to `opencode.json` or `opencode.jsonc`:
31
+
32
+ ```json
33
+ {
34
+ "$schema": "https://opencode.ai/config.json",
35
+ "plugin": ["opencode-tokenwatch"]
36
+ }
37
+ ```
38
+
39
+ ## Configuration
40
+
41
+ ```jsonc
42
+ {
43
+ "plugin": ["opencode-tokenwatch"],
44
+ "pluginConfig": {
45
+ "opencode-tokenwatch": {
46
+ "sidebar": {
47
+ "showPerformance": true,
48
+ "showPricing": false,
49
+ "showTokenDistribution": false,
50
+ "showTrend": true
51
+ },
52
+ "language": "auto"
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ | Option | Type | Default | Description |
59
+ |--------|------|---------|-------------|
60
+ | `sidebar.showPerformance` | boolean | `true` | Show TTFT/TPS/latency |
61
+ | `sidebar.showPricing` | boolean | `true` | Show model pricing |
62
+ | `sidebar.showTokenDistribution` | boolean | `true` | Show token distribution |
63
+ | `sidebar.showTrend` | boolean | `true` | Show trend indicator |
64
+ | `language` | `"auto"` / `"zh"` / `"en"` | `"auto"` | UI language |
65
+
66
+ Settings can also be toggled via `/usage` → Settings, taking precedence over `pluginConfig`.
67
+
68
+ ## Usage
69
+
70
+ In OpenCode TUI, run `/usage`:
71
+
72
+ - **HTML Report** — Pick a date range, generates a dashboard and opens it in browser
73
+ - **JSON Export** — Exports full usage data to `~/.opencode/reports/`
74
+ - **Text Report** — Exports Markdown report to `~/.opencode/reports/`
75
+ - **Settings** — Toggle sidebar blocks, switch language
76
+
77
+ ## Requirements
78
+
79
+ - OpenCode CLI (with `opencode db` command)
80
+ - Node.js 18+
81
+
82
+ ## Build
83
+
84
+ ```sh
85
+ npm install
86
+ npm run build
87
+ ```
88
+
89
+ ## Related
90
+
91
+ - [opencode-throughput](https://github.com/Howardzhangdqs/opencode-throughput) — Real-time LLM performance monitoring (TTFT/TPS/latency/cost)
92
+ - [opencode-visual-cache](https://github.com/Hotakus/opencode-visual-cache) — TUI sidebar cache hit rate visualization, token distribution analysis
93
+ - [magic-context](https://github.com/cortexkit/magic-context/) — Cache-aware infinite context + cross-session memory system
94
+
95
+ ## License
96
+
97
+ MIT
package/README.md CHANGED
@@ -1,96 +1,97 @@
1
- # opencode-tokenwatch
2
-
3
- [English](./README.en.md) · **简体中文**
4
-
5
- ![Sidebar](./assets/sidebar.png)
6
-
7
- OpenCode CLI 的实时 Token 用量统计、缓存分析与性能指标插件。
8
-
9
- ## 功能
10
-
11
- - **侧边栏面板** — 会话级与按模型的实时统计(请求数、Token、缓存、耗时、成本)
12
- - **缓存命中率** — 模型行内彩色进度条,带趋势指示器(↑/↓)
13
- - **性能指标** — Token 延迟(TTFT)、每秒吞吐(TPS)、端到端延迟
14
- - **Token 分布** — 按角色分解(系统、用户、Agent、Tool 等)
15
- - **模型定价**输入/缓存/输出单价
16
- - **`/usage` 命令** HTML 报告 → JSON 导出 → 文本报告 → 设置
17
- - **HTML 报告**交互式 ECharts 仪表盘,自动在浏览器打开
18
- - **多级折叠**面板、模型、子区块均可折叠,状态持久化
19
- - **语言切换**中英双语,可跟随系统或手动切换
20
- - **性能追踪**每次请求的 TTFT/TPS/延迟写入 JSONL,用于报告分析
21
- - **自适应配色**从主题色自动衍生
22
-
23
- ## 安装
24
-
25
- ```sh
26
- npm install opencode-tokenwatch
27
- ```
28
-
29
- 在 `opencode.json` 或 `opencode.jsonc` 中添加:
30
-
31
- ```json
32
- {
33
- "$schema": "https://opencode.ai/config.json",
34
- "plugin": ["opencode-tokenwatch"]
35
- }
36
- ```
37
-
38
- ## 配置
39
-
40
- ```jsonc
41
- {
42
- "plugin": ["opencode-tokenwatch"],
43
- "pluginConfig": {
44
- "opencode-tokenwatch": {
45
- "sidebar": {
46
- "showPerformance": true,
47
- "showPricing": false,
48
- "showTokenDistribution": false,
49
- "showTrend": true
50
- },
51
- "language": "auto"
52
- }
53
- }
54
- }
55
- ```
56
-
57
- | 配置项 | 类型 | 默认值 | 说明 |
58
- |--------|------|--------|------|
59
- | `sidebar.showPerformance` | boolean | `true` | 显示 TTFT/TPS/延迟 |
60
- | `sidebar.showPricing` | boolean | `true` | 显示模型定价 |
61
- | `sidebar.showTokenDistribution` | boolean | `true` | 显示 Token 分布 |
62
- | `sidebar.showTrend` | boolean | `true` | 显示趋势指示器 |
63
- | `language` | `"auto"` / `"zh"` / `"en"` | `"auto"` | 界面语言 |
64
-
65
- 运行时也可通过 `/usage` → 设置 调整,优先级高于 `pluginConfig`。
66
-
67
- ## 用法
68
-
69
- 在 OpenCode TUI 中输入 `/usage`,选择:
70
-
71
- - **HTML 报告** — 选择日期范围,生成仪表盘并在浏览器打开
72
- - **JSON 导出**导出完整用量数据至 `~/.opencode/reports/`
73
- - **文本报告**导出 Markdown 格式至 `~/.opencode/reports/`
74
- - **设置**开关侧边栏显示项、切换语言
75
-
76
- ## 系统要求
77
-
78
- - OpenCode CLI(支持 `opencode db` 命令)
79
- - Node.js 18+
80
-
81
- ## 构建
82
-
83
- ```sh
84
- npm install
85
- npm run build
86
- ```
87
-
88
- ## 相关项目
89
-
90
- - [opencode-throughput](https://github.com/Howardzhangdqs/opencode-throughput) — 实时 LLM 性能监控,采集 TTFT/TPS/延迟和成本
91
- - [opencode-visual-cache](https://github.com/Hotakus/opencode-visual-cache) — TUI 侧边栏缓存命中率可视化,Token 分布分析
92
- - [magic-context](https://github.com/cortexkit/magic-context/) — 缓存感知的无限上下文 + 跨会话记忆系统
93
-
94
- ## 许可
95
-
96
- MIT
1
+ # opencode-tokenwatch
2
+
3
+ [English](./README.en.md) · **简体中文**
4
+
5
+ ![Sidebar](./assets/sidebar.png)
6
+
7
+ OpenCode CLI 的实时 Token 用量统计、缓存分析与性能指标插件。
8
+
9
+ ## 功能
10
+
11
+ - **侧边栏面板** — 会话级与按模型的实时统计(请求数、Token、缓存、耗时、成本)
12
+ - **缓存命中率** — 模型行内彩色进度条,带趋势指示器(↑/↓),全局总计行显示**全局加权命中率**
13
+ - **性能指标** — TTFT / TPS / 端到端延迟 + P50/P95/P99 延迟分位数
14
+ - **Token 分布** — 5 桶角色分解(系统、用户、Agent、Tool 以及 other 兜底,支持自适应缩放)
15
+ - **错误率统计**识别并统计失败请求(空 Token 响应),实时计算错误率
16
+ - **模型定价**输入/缓存/输出单价
17
+ - **`/usage` 命令**HTML 报告 → JSON 导出 → 文本报告 → 设置
18
+ - **HTML 报告** 交互式 ECharts 仪表盘:Token 分布、性能分位数、错误率分析、模型效率水平排名(已重构重叠散点图为水平条形对比图),自动在浏览器打开
19
+ - **多级折叠**面板、模型、子区块均可折叠,状态持久化
20
+ - **语言切换**中英双语,可跟随系统或手动切换
21
+ - **性能追踪**每次请求的 TTFT/TPS/延迟写入 JSONL,用于报告分析
22
+ - **自适应配色** — 从主题色自动衍生
23
+
24
+ ## 安装
25
+
26
+ ```sh
27
+ npm install opencode-tokenwatch
28
+ ```
29
+
30
+ 在 `opencode.json` 或 `opencode.jsonc` 中添加:
31
+
32
+ ```json
33
+ {
34
+ "$schema": "https://opencode.ai/config.json",
35
+ "plugin": ["opencode-tokenwatch"]
36
+ }
37
+ ```
38
+
39
+ ## 配置
40
+
41
+ ```jsonc
42
+ {
43
+ "plugin": ["opencode-tokenwatch"],
44
+ "pluginConfig": {
45
+ "opencode-tokenwatch": {
46
+ "sidebar": {
47
+ "showPerformance": true,
48
+ "showPricing": false,
49
+ "showTokenDistribution": false,
50
+ "showTrend": true
51
+ },
52
+ "language": "auto"
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ | 配置项 | 类型 | 默认值 | 说明 |
59
+ |--------|------|--------|------|
60
+ | `sidebar.showPerformance` | boolean | `true` | 显示 TTFT/TPS/延迟 |
61
+ | `sidebar.showPricing` | boolean | `true` | 显示模型定价 |
62
+ | `sidebar.showTokenDistribution` | boolean | `true` | 显示 Token 分布 |
63
+ | `sidebar.showTrend` | boolean | `true` | 显示趋势指示器 |
64
+ | `language` | `"auto"` / `"zh"` / `"en"` | `"auto"` | 界面语言 |
65
+
66
+ 运行时也可通过 `/usage` → 设置 调整,优先级高于 `pluginConfig`。
67
+
68
+ ## 用法
69
+
70
+ 在 OpenCode TUI 中输入 `/usage`,选择:
71
+
72
+ - **HTML 报告**选择日期范围,生成仪表盘并在浏览器打开
73
+ - **JSON 导出** 导出完整用量数据至 `~/.opencode/reports/`
74
+ - **文本报告**导出 Markdown 格式至 `~/.opencode/reports/`
75
+ - **设置** — 开关侧边栏显示项、切换语言
76
+
77
+ ## 系统要求
78
+
79
+ - OpenCode CLI(支持 `opencode db` 命令)
80
+ - Node.js 18+
81
+
82
+ ## 构建
83
+
84
+ ```sh
85
+ npm install
86
+ npm run build
87
+ ```
88
+
89
+ ## 相关项目
90
+
91
+ - [opencode-throughput](https://github.com/Howardzhangdqs/opencode-throughput) — 实时 LLM 性能监控,采集 TTFT/TPS/延迟和成本
92
+ - [opencode-visual-cache](https://github.com/Hotakus/opencode-visual-cache) — TUI 侧边栏缓存命中率可视化,Token 分布分析
93
+ - [magic-context](https://github.com/cortexkit/magic-context/) — 缓存感知的无限上下文 + 跨会话记忆系统
94
+
95
+ ## 许可
96
+
97
+ MIT
package/dist/commands.jsx CHANGED
@@ -44,6 +44,19 @@ function openInBrowser(filePath) {
44
44
  }
45
45
  catch { /* silently fail */ }
46
46
  }
47
+ /** 线性插值百分位数,输入须为有序数组 */
48
+ function computePercentile(sortedArr, p) {
49
+ if (sortedArr.length === 0)
50
+ return null;
51
+ if (sortedArr.length === 1)
52
+ return sortedArr[0];
53
+ const idx = (p / 100) * (sortedArr.length - 1);
54
+ const lo = Math.floor(idx);
55
+ const hi = Math.ceil(idx);
56
+ if (lo === hi)
57
+ return sortedArr[lo];
58
+ return sortedArr[lo] + (sortedArr[hi] - sortedArr[lo]) * (idx - lo);
59
+ }
47
60
  function aggregatePerfStats(logs) {
48
61
  const map = new Map();
49
62
  for (const entry of logs) {
@@ -54,10 +67,16 @@ function aggregatePerfStats(logs) {
54
67
  model: key,
55
68
  providerID: entry.providerID,
56
69
  requestCount: 0,
70
+ ttftCount: 0, // Bug fix: 独立维护有效样本计数
71
+ tpsCount: 0,
72
+ latencyCount: 0,
57
73
  totalInput: 0, totalOutput: 0, totalCacheRead: 0, totalCacheWrite: 0, totalCost: 0,
58
74
  avgTTFT: null, maxTTFT: null, minTTFT: null,
75
+ p50TTFT: null, p95TTFT: null, p99TTFT: null,
59
76
  avgTPS: null, maxTPS: null, minTPS: null,
60
77
  avgLatency: null, maxLatency: null, minLatency: null,
78
+ p50Latency: null, p95Latency: null, p99Latency: null,
79
+ cacheHitRate: null,
61
80
  };
62
81
  map.set(key, s);
63
82
  }
@@ -67,24 +86,61 @@ function aggregatePerfStats(logs) {
67
86
  s.totalCacheRead += entry.cacheReadTokens;
68
87
  s.totalCacheWrite += entry.cacheWriteTokens;
69
88
  s.totalCost += entry.cost;
70
- const c = s.requestCount;
71
89
  if (entry.ttft_ms != null) {
90
+ // Bug fix: 分母使用 ttftCount(有效样本数),而非 requestCount(总请求数)
91
+ s.ttftCount++;
92
+ const c = s.ttftCount;
72
93
  s.avgTTFT = s.avgTTFT != null ? s.avgTTFT + (entry.ttft_ms - s.avgTTFT) / c : entry.ttft_ms;
73
94
  s.maxTTFT = s.maxTTFT != null ? Math.max(s.maxTTFT, entry.ttft_ms) : entry.ttft_ms;
74
95
  s.minTTFT = s.minTTFT != null ? Math.min(s.minTTFT, entry.ttft_ms) : entry.ttft_ms;
75
96
  }
76
97
  if (entry.tps != null) {
98
+ // Bug fix: 分母使用 tpsCount(有效样本数)
99
+ s.tpsCount++;
100
+ const c = s.tpsCount;
77
101
  s.avgTPS = s.avgTPS != null ? s.avgTPS + (entry.tps - s.avgTPS) / c : entry.tps;
78
102
  s.maxTPS = s.maxTPS != null ? Math.max(s.maxTPS, entry.tps) : entry.tps;
79
103
  s.minTPS = s.minTPS != null ? Math.min(s.minTPS, entry.tps) : entry.tps;
80
104
  }
81
105
  if (entry.latency_ms != null) {
106
+ s.latencyCount++;
107
+ const c = s.latencyCount;
82
108
  s.avgLatency = s.avgLatency != null ? s.avgLatency + (entry.latency_ms - s.avgLatency) / c : entry.latency_ms;
83
109
  s.maxLatency = s.maxLatency != null ? Math.max(s.maxLatency, entry.latency_ms) : entry.latency_ms;
84
110
  s.minLatency = s.minLatency != null ? Math.min(s.minLatency, entry.latency_ms) : entry.latency_ms;
85
111
  }
86
112
  }
87
- return Array.from(map.values());
113
+ // 分位数后处理:需要收集每个模型的所有样本然后计算
114
+ // 注: 此处采用单次遍历日志重新收集分数据,需要两次遍历
115
+ const ttftBuckets = new Map();
116
+ const latBuckets = new Map();
117
+ for (const entry of logs) {
118
+ const key = entry.model;
119
+ if (entry.ttft_ms != null) {
120
+ const arr = ttftBuckets.get(key) ?? [];
121
+ arr.push(entry.ttft_ms);
122
+ ttftBuckets.set(key, arr);
123
+ }
124
+ if (entry.latency_ms != null) {
125
+ const arr = latBuckets.get(key) ?? [];
126
+ arr.push(entry.latency_ms);
127
+ latBuckets.set(key, arr);
128
+ }
129
+ }
130
+ const result = Array.from(map.values());
131
+ for (const s of result) {
132
+ const ttftArr = [...(ttftBuckets.get(s.model) ?? [])].sort((a, b) => a - b);
133
+ s.p50TTFT = computePercentile(ttftArr, 50);
134
+ s.p95TTFT = computePercentile(ttftArr, 95);
135
+ s.p99TTFT = computePercentile(ttftArr, 99);
136
+ const latArr = [...(latBuckets.get(s.model) ?? [])].sort((a, b) => a - b);
137
+ s.p50Latency = computePercentile(latArr, 50);
138
+ s.p95Latency = computePercentile(latArr, 95);
139
+ s.p99Latency = computePercentile(latArr, 99);
140
+ const denom = s.totalInput + s.totalCacheRead;
141
+ s.cacheHitRate = denom > 0 ? (s.totalCacheRead / denom) * 100 : null;
142
+ }
143
+ return result;
88
144
  }
89
145
  async function buildCombinedData(api, filters = {}) {
90
146
  const report = await getUsageReport(filters);
@@ -67,6 +67,22 @@ export interface SessionBreakdownItem {
67
67
  totalCost: number;
68
68
  day: string;
69
69
  }
70
+ /** 失败请求统计 */
71
+ export interface ErrorStats {
72
+ /** 过滤内总请求数(tokens.total > 0 的 assistant) */
73
+ successCount: number;
74
+ /** 失败请求数(tokens.total == 0 的 assistant) */
75
+ failedCount: number;
76
+ /** 失败率:failedCount / (successCount + failedCount) */
77
+ errorRate: number;
78
+ /** 按模型细化的失败数 */
79
+ byModel: Array<{
80
+ provider: string;
81
+ model: string;
82
+ failed: number;
83
+ total: number;
84
+ }>;
85
+ }
70
86
  export interface UsageReport {
71
87
  filters: UsageFilters;
72
88
  summary: SessionTokenData;
@@ -74,6 +90,7 @@ export interface UsageReport {
74
90
  providers: ProviderBreakdownItem[];
75
91
  daily: DailyBreakdownItem[];
76
92
  sessions: SessionBreakdownItem[];
93
+ errors?: ErrorStats;
77
94
  }
78
95
  export declare function formatTokens(n: number): string;
79
96
  export declare function formatCost(n: number): string;
@@ -95,12 +112,17 @@ export interface SessionPerfStats {
95
112
  totalCacheWrite: number;
96
113
  totalRequests: number;
97
114
  totalCost: number;
115
+ /** 全局加权缓存命中率(按请求数加权平均) */
116
+ weightedCacheHitRate: number | null;
98
117
  };
99
118
  }
100
119
  export interface ModelPerfStats {
101
120
  model: string;
102
121
  providerID: string;
103
122
  requestCount: number;
123
+ ttftCount: number;
124
+ tpsCount: number;
125
+ latencyCount: number;
104
126
  totalInput: number;
105
127
  totalOutput: number;
106
128
  totalCacheRead: number;
@@ -109,12 +131,20 @@ export interface ModelPerfStats {
109
131
  avgTTFT: number | null;
110
132
  maxTTFT: number | null;
111
133
  minTTFT: number | null;
134
+ p50TTFT: number | null;
135
+ p95TTFT: number | null;
136
+ p99TTFT: number | null;
112
137
  avgTPS: number | null;
113
138
  maxTPS: number | null;
114
139
  minTPS: number | null;
115
140
  avgLatency: number | null;
116
141
  maxLatency: number | null;
117
142
  minLatency: number | null;
143
+ p50Latency: number | null;
144
+ p95Latency: number | null;
145
+ p99Latency: number | null;
146
+ /** 该模型加权缓存命中率:cacheRead / (cacheRead + input) */
147
+ cacheHitRate: number | null;
118
148
  }
119
149
  export interface TokenDistribution {
120
150
  system: number;