opencode-tokenwatch 0.1.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 +21 -21
- package/README.en.md +97 -0
- package/README.md +97 -103
- package/dist/commands.d.ts +2 -0
- package/dist/commands.jsx +369 -0
- package/dist/formatter.d.ts +103 -0
- package/dist/formatter.js +14 -3
- package/dist/generate-usage-html.d.ts +2 -0
- package/dist/generate-usage-html.js +866 -0
- package/dist/i18n.d.ts +5 -0
- package/dist/i18n.js +171 -0
- package/dist/perf-tracker.d.ts +60 -0
- package/dist/perf-tracker.js +257 -0
- package/dist/queries.d.ts +3 -1
- package/dist/queries.js +156 -97
- package/dist/sidebar.d.ts +22 -0
- package/dist/sidebar.jsx +395 -0
- package/dist/tui.d.ts +15 -1
- package/dist/tui.jsx +123 -0
- package/package.json +63 -63
- package/dist/tui.js +0 -406
package/dist/queries.js
CHANGED
|
@@ -20,6 +20,10 @@ async function queryDb(sql) {
|
|
|
20
20
|
function escapeSql(value) {
|
|
21
21
|
return value.replace(/'/g, "''");
|
|
22
22
|
}
|
|
23
|
+
/** 校验日期格式必须为 YYYY-MM-DD,防止格式异常字符串进入 SQL */
|
|
24
|
+
function isValidDate(s) {
|
|
25
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(s);
|
|
26
|
+
}
|
|
23
27
|
function messageWhere(filters) {
|
|
24
28
|
const where = [
|
|
25
29
|
"json_extract(m.data, '$.role') = 'assistant'",
|
|
@@ -31,10 +35,13 @@ function messageWhere(filters) {
|
|
|
31
35
|
where.push(`coalesce(json_extract(m.data, '$.providerID'), '') = '${escapeSql(filters.provider)}'`);
|
|
32
36
|
if (filters.model)
|
|
33
37
|
where.push(`coalesce(json_extract(m.data, '$.modelID'), '') = '${escapeSql(filters.model)}'`);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
// Risk fix: 日期参数先验证格式(YYYY-MM-DD),格式不符则忽略该过滤条件
|
|
39
|
+
if (filters.startDate && isValidDate(filters.startDate)) {
|
|
40
|
+
where.push(`date(m.time_created / 1000, 'unixepoch', 'localtime') >= '${filters.startDate}'`);
|
|
41
|
+
}
|
|
42
|
+
if (filters.endDate && isValidDate(filters.endDate)) {
|
|
43
|
+
where.push(`date(m.time_created / 1000, 'unixepoch', 'localtime') <= '${filters.endDate}'`);
|
|
44
|
+
}
|
|
38
45
|
return where.join(" AND ");
|
|
39
46
|
}
|
|
40
47
|
function parseList(value) {
|
|
@@ -83,41 +90,41 @@ export async function getCurrentSessionStats(sessionId) {
|
|
|
83
90
|
return getSummary(filters);
|
|
84
91
|
}
|
|
85
92
|
export async function getSummary(filters = {}) {
|
|
86
|
-
const sql = `
|
|
87
|
-
SELECT
|
|
88
|
-
group_concat(distinct coalesce(json_extract(m.data, '$.modelID'), 'unknown')) as models_used,
|
|
89
|
-
group_concat(distinct coalesce(json_extract(m.data, '$.providerID'), 'unknown')) as providers_used,
|
|
90
|
-
count(*) as request_count,
|
|
91
|
-
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
92
|
-
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
93
|
-
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
94
|
-
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
95
|
-
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
96
|
-
sum(coalesce(json_extract(m.data, '$.tokens.cache.write'), 0)) as cache_write,
|
|
97
|
-
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost
|
|
98
|
-
FROM message m
|
|
99
|
-
WHERE ${messageWhere(filters)}
|
|
93
|
+
const sql = `
|
|
94
|
+
SELECT
|
|
95
|
+
group_concat(distinct coalesce(json_extract(m.data, '$.modelID'), 'unknown')) as models_used,
|
|
96
|
+
group_concat(distinct coalesce(json_extract(m.data, '$.providerID'), 'unknown')) as providers_used,
|
|
97
|
+
count(*) as request_count,
|
|
98
|
+
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
99
|
+
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
100
|
+
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
101
|
+
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
102
|
+
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
103
|
+
sum(coalesce(json_extract(m.data, '$.tokens.cache.write'), 0)) as cache_write,
|
|
104
|
+
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost
|
|
105
|
+
FROM message m
|
|
106
|
+
WHERE ${messageWhere(filters)}
|
|
100
107
|
`.trim();
|
|
101
108
|
const rows = await queryDb(sql);
|
|
102
109
|
return toSessionTokenData(rows[0]);
|
|
103
110
|
}
|
|
104
111
|
export async function getModelBreakdown(filters = {}) {
|
|
105
|
-
const sql = `
|
|
106
|
-
SELECT
|
|
107
|
-
coalesce(json_extract(m.data, '$.providerID'), 'unknown') as provider,
|
|
108
|
-
coalesce(json_extract(m.data, '$.modelID'), 'unknown') as model,
|
|
109
|
-
count(*) as requests,
|
|
110
|
-
count(distinct m.session_id) as sessions,
|
|
111
|
-
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
112
|
-
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
113
|
-
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
114
|
-
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
115
|
-
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
116
|
-
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost
|
|
117
|
-
FROM message m
|
|
118
|
-
WHERE ${messageWhere(filters)}
|
|
119
|
-
GROUP BY provider, model
|
|
120
|
-
ORDER BY total_tokens DESC
|
|
112
|
+
const sql = `
|
|
113
|
+
SELECT
|
|
114
|
+
coalesce(json_extract(m.data, '$.providerID'), 'unknown') as provider,
|
|
115
|
+
coalesce(json_extract(m.data, '$.modelID'), 'unknown') as model,
|
|
116
|
+
count(*) as requests,
|
|
117
|
+
count(distinct m.session_id) as sessions,
|
|
118
|
+
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
119
|
+
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
120
|
+
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
121
|
+
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
122
|
+
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
123
|
+
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost
|
|
124
|
+
FROM message m
|
|
125
|
+
WHERE ${messageWhere(filters)}
|
|
126
|
+
GROUP BY provider, model
|
|
127
|
+
ORDER BY total_tokens DESC
|
|
121
128
|
`.trim();
|
|
122
129
|
const rows = await queryDb(sql);
|
|
123
130
|
return rows.map((row) => ({
|
|
@@ -134,21 +141,21 @@ ORDER BY total_tokens DESC
|
|
|
134
141
|
}));
|
|
135
142
|
}
|
|
136
143
|
export async function getProviderBreakdown(filters = {}) {
|
|
137
|
-
const sql = `
|
|
138
|
-
SELECT
|
|
139
|
-
coalesce(json_extract(m.data, '$.providerID'), 'unknown') as provider,
|
|
140
|
-
count(*) as requests,
|
|
141
|
-
count(distinct m.session_id) as sessions,
|
|
142
|
-
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
143
|
-
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
144
|
-
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
145
|
-
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
146
|
-
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
147
|
-
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost
|
|
148
|
-
FROM message m
|
|
149
|
-
WHERE ${messageWhere(filters)}
|
|
150
|
-
GROUP BY provider
|
|
151
|
-
ORDER BY total_tokens DESC
|
|
144
|
+
const sql = `
|
|
145
|
+
SELECT
|
|
146
|
+
coalesce(json_extract(m.data, '$.providerID'), 'unknown') as provider,
|
|
147
|
+
count(*) as requests,
|
|
148
|
+
count(distinct m.session_id) as sessions,
|
|
149
|
+
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
150
|
+
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
151
|
+
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
152
|
+
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
153
|
+
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
154
|
+
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost
|
|
155
|
+
FROM message m
|
|
156
|
+
WHERE ${messageWhere(filters)}
|
|
157
|
+
GROUP BY provider
|
|
158
|
+
ORDER BY total_tokens DESC
|
|
152
159
|
`.trim();
|
|
153
160
|
const rows = await queryDb(sql);
|
|
154
161
|
return rows.map((row) => ({
|
|
@@ -165,22 +172,22 @@ ORDER BY total_tokens DESC
|
|
|
165
172
|
}
|
|
166
173
|
export async function getDailyBreakdown(filters = {}) {
|
|
167
174
|
const limit = filters.limit ?? 30;
|
|
168
|
-
const sql = `
|
|
169
|
-
SELECT
|
|
170
|
-
date(m.time_created / 1000, 'unixepoch', 'localtime') as day,
|
|
171
|
-
count(*) as requests,
|
|
172
|
-
count(distinct m.session_id) as sessions,
|
|
173
|
-
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
174
|
-
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
175
|
-
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
176
|
-
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
177
|
-
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
178
|
-
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost
|
|
179
|
-
FROM message m
|
|
180
|
-
WHERE ${messageWhere(filters)}
|
|
181
|
-
GROUP BY day
|
|
182
|
-
ORDER BY day DESC
|
|
183
|
-
LIMIT ${Math.max(1, limit)}
|
|
175
|
+
const sql = `
|
|
176
|
+
SELECT
|
|
177
|
+
date(m.time_created / 1000, 'unixepoch', 'localtime') as day,
|
|
178
|
+
count(*) as requests,
|
|
179
|
+
count(distinct m.session_id) as sessions,
|
|
180
|
+
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
181
|
+
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
182
|
+
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
183
|
+
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
184
|
+
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
185
|
+
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost
|
|
186
|
+
FROM message m
|
|
187
|
+
WHERE ${messageWhere(filters)}
|
|
188
|
+
GROUP BY day
|
|
189
|
+
ORDER BY day DESC
|
|
190
|
+
LIMIT ${Math.max(1, limit)}
|
|
184
191
|
`.trim();
|
|
185
192
|
const rows = await queryDb(sql);
|
|
186
193
|
return rows.map((row) => ({
|
|
@@ -197,26 +204,26 @@ LIMIT ${Math.max(1, limit)}
|
|
|
197
204
|
}
|
|
198
205
|
export async function getSessionBreakdown(filters = {}) {
|
|
199
206
|
const limit = filters.limit ?? 15;
|
|
200
|
-
const sql = `
|
|
201
|
-
SELECT
|
|
202
|
-
s.id as session_id,
|
|
203
|
-
s.title as title,
|
|
204
|
-
coalesce(json_extract(m.data, '$.providerID'), json_extract(s.model, '$.providerID'), 'unknown') as provider,
|
|
205
|
-
coalesce(json_extract(m.data, '$.modelID'), json_extract(s.model, '$.id'), 'unknown') as model,
|
|
206
|
-
count(*) as requests,
|
|
207
|
-
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
208
|
-
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
209
|
-
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
210
|
-
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
211
|
-
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
212
|
-
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost,
|
|
213
|
-
date(max(m.time_created) / 1000, 'unixepoch', 'localtime') as day
|
|
214
|
-
FROM message m
|
|
215
|
-
JOIN session s ON s.id = m.session_id
|
|
216
|
-
WHERE ${messageWhere(filters)}
|
|
217
|
-
GROUP BY s.id, s.title, provider, model
|
|
218
|
-
ORDER BY max(m.time_created) DESC
|
|
219
|
-
LIMIT ${Math.max(1, limit)}
|
|
207
|
+
const sql = `
|
|
208
|
+
SELECT
|
|
209
|
+
s.id as session_id,
|
|
210
|
+
s.title as title,
|
|
211
|
+
coalesce(json_extract(m.data, '$.providerID'), json_extract(s.model, '$.providerID'), 'unknown') as provider,
|
|
212
|
+
coalesce(json_extract(m.data, '$.modelID'), json_extract(s.model, '$.id'), 'unknown') as model,
|
|
213
|
+
count(*) as requests,
|
|
214
|
+
sum(coalesce(json_extract(m.data, '$.tokens.total'), 0)) as total_tokens,
|
|
215
|
+
sum(coalesce(json_extract(m.data, '$.tokens.input'), 0)) as input_tokens,
|
|
216
|
+
sum(coalesce(json_extract(m.data, '$.tokens.output'), 0)) as output_tokens,
|
|
217
|
+
sum(coalesce(json_extract(m.data, '$.tokens.reasoning'), 0)) as reasoning_tokens,
|
|
218
|
+
sum(coalesce(json_extract(m.data, '$.tokens.cache.read'), 0)) as cache_read,
|
|
219
|
+
sum(coalesce(json_extract(m.data, '$.cost'), 0)) as total_cost,
|
|
220
|
+
date(max(m.time_created) / 1000, 'unixepoch', 'localtime') as day
|
|
221
|
+
FROM message m
|
|
222
|
+
JOIN session s ON s.id = m.session_id
|
|
223
|
+
WHERE ${messageWhere(filters)}
|
|
224
|
+
GROUP BY s.id, s.title, provider, model
|
|
225
|
+
ORDER BY max(m.time_created) DESC
|
|
226
|
+
LIMIT ${Math.max(1, limit)}
|
|
220
227
|
`.trim();
|
|
221
228
|
const rows = await queryDb(sql);
|
|
222
229
|
return rows.map((row) => ({
|
|
@@ -235,34 +242,86 @@ LIMIT ${Math.max(1, limit)}
|
|
|
235
242
|
}));
|
|
236
243
|
}
|
|
237
244
|
export async function getAvailableModels() {
|
|
238
|
-
const sql = `
|
|
239
|
-
SELECT distinct coalesce(json_extract(m.data, '$.modelID'), 'unknown') as value
|
|
240
|
-
FROM message m
|
|
241
|
-
WHERE ${messageWhere({})}
|
|
242
|
-
ORDER BY value ASC
|
|
245
|
+
const sql = `
|
|
246
|
+
SELECT distinct coalesce(json_extract(m.data, '$.modelID'), 'unknown') as value
|
|
247
|
+
FROM message m
|
|
248
|
+
WHERE ${messageWhere({})}
|
|
249
|
+
ORDER BY value ASC
|
|
243
250
|
`.trim();
|
|
244
251
|
const rows = await queryDb(sql);
|
|
245
252
|
return rows.map((row) => row.value ?? "unknown");
|
|
246
253
|
}
|
|
247
254
|
export async function getAvailableProviders() {
|
|
248
|
-
const sql = `
|
|
249
|
-
SELECT distinct coalesce(json_extract(m.data, '$.providerID'), 'unknown') as value
|
|
250
|
-
FROM message m
|
|
251
|
-
WHERE ${messageWhere({})}
|
|
252
|
-
ORDER BY value ASC
|
|
255
|
+
const sql = `
|
|
256
|
+
SELECT distinct coalesce(json_extract(m.data, '$.providerID'), 'unknown') as value
|
|
257
|
+
FROM message m
|
|
258
|
+
WHERE ${messageWhere({})}
|
|
259
|
+
ORDER BY value ASC
|
|
253
260
|
`.trim();
|
|
254
261
|
const rows = await queryDb(sql);
|
|
255
262
|
return rows.map((row) => row.value ?? "unknown");
|
|
256
263
|
}
|
|
264
|
+
/** 失败请求计数 SQL。1次运行获取成功数+失败数+按模型细分 */
|
|
265
|
+
export async function getErrorStats(filters = {}) {
|
|
266
|
+
// 构建日期/Session/Provider/Model 过滤条件(不包含 tokens.total > 0 过滤)
|
|
267
|
+
const baseConds = [
|
|
268
|
+
"json_extract(m.data, '$.role') = 'assistant'",
|
|
269
|
+
];
|
|
270
|
+
if (filters.sessionId)
|
|
271
|
+
baseConds.push(`m.session_id = '${escapeSql(filters.sessionId)}'`);
|
|
272
|
+
if (filters.provider)
|
|
273
|
+
baseConds.push(`coalesce(json_extract(m.data, '$.providerID'), '') = '${escapeSql(filters.provider)}'`);
|
|
274
|
+
if (filters.model)
|
|
275
|
+
baseConds.push(`coalesce(json_extract(m.data, '$.modelID'), '') = '${escapeSql(filters.model)}'`);
|
|
276
|
+
if (filters.startDate && isValidDate(filters.startDate)) {
|
|
277
|
+
baseConds.push(`date(m.time_created / 1000, 'unixepoch', 'localtime') >= '${filters.startDate}'`);
|
|
278
|
+
}
|
|
279
|
+
if (filters.endDate && isValidDate(filters.endDate)) {
|
|
280
|
+
baseConds.push(`date(m.time_created / 1000, 'unixepoch', 'localtime') <= '${filters.endDate}'`);
|
|
281
|
+
}
|
|
282
|
+
const baseWhere = baseConds.join(" AND ");
|
|
283
|
+
// 按模型细化:同时统计成功和失败请求
|
|
284
|
+
const sql = `
|
|
285
|
+
SELECT
|
|
286
|
+
coalesce(json_extract(m.data, '$.providerID'), 'unknown') as provider,
|
|
287
|
+
coalesce(json_extract(m.data, '$.modelID'), 'unknown') as model,
|
|
288
|
+
count(*) as total,
|
|
289
|
+
sum(CASE WHEN coalesce(json_extract(m.data, '$.tokens.total'), 0) = 0 THEN 1 ELSE 0 END) as failed
|
|
290
|
+
FROM message m
|
|
291
|
+
WHERE ${baseWhere}
|
|
292
|
+
GROUP BY provider, model
|
|
293
|
+
ORDER BY failed DESC
|
|
294
|
+
`.trim();
|
|
295
|
+
try {
|
|
296
|
+
const rows = await queryDb(sql);
|
|
297
|
+
let successCount = 0, failedCount = 0;
|
|
298
|
+
const byModel = rows.map(r => {
|
|
299
|
+
const total = r.total ?? 0;
|
|
300
|
+
const failed = r.failed ?? 0;
|
|
301
|
+
const success = total - failed;
|
|
302
|
+
successCount += success;
|
|
303
|
+
failedCount += failed;
|
|
304
|
+
return { provider: r.provider ?? 'unknown', model: r.model ?? 'unknown', failed, total };
|
|
305
|
+
});
|
|
306
|
+
const errorRate = (successCount + failedCount) > 0
|
|
307
|
+
? failedCount / (successCount + failedCount)
|
|
308
|
+
: 0;
|
|
309
|
+
return { successCount, failedCount, errorRate, byModel };
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return { successCount: 0, failedCount: 0, errorRate: 0, byModel: [] };
|
|
313
|
+
}
|
|
314
|
+
}
|
|
257
315
|
export async function getUsageReport(filters = {}) {
|
|
258
|
-
const [summary, models, providers, daily, sessions] = await Promise.all([
|
|
316
|
+
const [summary, models, providers, daily, sessions, errors] = await Promise.all([
|
|
259
317
|
getSummary(filters),
|
|
260
318
|
getModelBreakdown(filters),
|
|
261
319
|
getProviderBreakdown(filters),
|
|
262
320
|
getDailyBreakdown(filters),
|
|
263
321
|
getSessionBreakdown(filters),
|
|
322
|
+
getErrorStats(filters),
|
|
264
323
|
]);
|
|
265
|
-
return { filters, summary, models, providers, daily, sessions };
|
|
324
|
+
return { filters, summary, models, providers, daily, sessions, errors };
|
|
266
325
|
}
|
|
267
326
|
function csvEscape(value) {
|
|
268
327
|
const text = String(value);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TuiPluginApi, TuiTheme } from "@opencode-ai/plugin/tui";
|
|
2
|
+
import type { PerfTracker } from "./perf-tracker.js";
|
|
3
|
+
import type { TokenMessage } from "./tui.jsx";
|
|
4
|
+
export interface SidebarConfig {
|
|
5
|
+
sidebar: {
|
|
6
|
+
showPerformance: boolean;
|
|
7
|
+
showPricing: boolean;
|
|
8
|
+
showTokenDistribution: boolean;
|
|
9
|
+
showTrend: boolean;
|
|
10
|
+
};
|
|
11
|
+
language: "zh" | "en" | "auto";
|
|
12
|
+
}
|
|
13
|
+
export declare function loadConfig(api: TuiPluginApi): SidebarConfig;
|
|
14
|
+
interface TokenWatchPanelProps {
|
|
15
|
+
api: TuiPluginApi;
|
|
16
|
+
theme: TuiTheme;
|
|
17
|
+
perfTracker: PerfTracker;
|
|
18
|
+
messages: readonly any[];
|
|
19
|
+
allTokenMessages: TokenMessage[];
|
|
20
|
+
}
|
|
21
|
+
export declare function TokenWatchPanel(props: TokenWatchPanelProps): any;
|
|
22
|
+
export {};
|