@leo000001/opencode-quota-sidebar 4.0.0 → 4.0.2
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 +6 -0
- package/README.zh-CN.md +6 -0
- package/dist/format.js +89 -8
- package/dist/title.js +3 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -325,6 +325,12 @@ Examples:
|
|
|
325
325
|
|
|
326
326
|
The package exposes a standalone CLI dashboard. After installing globally or making the `bin` available:
|
|
327
327
|
|
|
328
|
+
```bash
|
|
329
|
+
npm install -g @leo000001/opencode-quota-sidebar
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
If you prefer not to install globally, you can also run it with `npx @leo000001/opencode-quota-sidebar <args>`.
|
|
333
|
+
|
|
328
334
|
```bash
|
|
329
335
|
# Current period (single snapshot)
|
|
330
336
|
opencode-quota day # today
|
package/README.zh-CN.md
CHANGED
|
@@ -332,6 +332,12 @@ usage 聚合采用增量模式。插件会为每个 session 维护 cursor,优
|
|
|
332
332
|
|
|
333
333
|
这个包同时提供一个独立 CLI dashboard。全局安装或让 `bin` 可执行后:
|
|
334
334
|
|
|
335
|
+
```bash
|
|
336
|
+
npm install -g @leo000001/opencode-quota-sidebar
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
如果不想全局安装,也可以直接用 `npx @leo000001/opencode-quota-sidebar <args>` 运行。
|
|
340
|
+
|
|
335
341
|
```bash
|
|
336
342
|
# 当前周期(单次快照)
|
|
337
343
|
opencode-quota day # 今天
|
package/dist/format.js
CHANGED
|
@@ -409,15 +409,22 @@ function usageDetailLines(usage, cacheMetrics, options) {
|
|
|
409
409
|
`I${numberToken(usage.input)}`,
|
|
410
410
|
`O${numberToken(usage.output)}`,
|
|
411
411
|
]);
|
|
412
|
-
const
|
|
412
|
+
const secondaryGroups = [];
|
|
413
|
+
const coverageTokens = [];
|
|
414
|
+
if (cacheMetrics.cachedRatio !== undefined) {
|
|
415
|
+
coverageTokens.push(`Cd ${formatPercent(cacheMetrics.cachedRatio, 0)}`);
|
|
416
|
+
}
|
|
417
|
+
if (coverageTokens.length > 0)
|
|
418
|
+
secondaryGroups.push(coverageTokens);
|
|
419
|
+
const cacheTokens = [];
|
|
413
420
|
const pushCacheRead = () => {
|
|
414
421
|
if (usage.cacheRead > 0) {
|
|
415
|
-
|
|
422
|
+
cacheTokens.push(`R${numberToken(usage.cacheRead)}`);
|
|
416
423
|
}
|
|
417
424
|
};
|
|
418
425
|
const pushCacheWrite = () => {
|
|
419
426
|
if (usage.cacheWrite > 0) {
|
|
420
|
-
|
|
427
|
+
cacheTokens.push(`W${numberToken(usage.cacheWrite)}`);
|
|
421
428
|
}
|
|
422
429
|
};
|
|
423
430
|
if (options.cacheReadFirst) {
|
|
@@ -428,11 +435,22 @@ function usageDetailLines(usage, cacheMetrics, options) {
|
|
|
428
435
|
pushCacheWrite();
|
|
429
436
|
pushCacheRead();
|
|
430
437
|
}
|
|
431
|
-
if (
|
|
432
|
-
|
|
438
|
+
if (cacheTokens.length > 0) {
|
|
439
|
+
if (coverageTokens.length > 0) {
|
|
440
|
+
const combined = [...coverageTokens, ...cacheTokens].join(' ');
|
|
441
|
+
if (fitsLine(combined, width)) {
|
|
442
|
+
secondaryGroups.length = 0;
|
|
443
|
+
secondaryGroups.push([...coverageTokens, ...cacheTokens]);
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
secondaryGroups.push(cacheTokens);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
secondaryGroups.push(cacheTokens);
|
|
451
|
+
}
|
|
433
452
|
}
|
|
434
|
-
|
|
435
|
-
groups.push(secondary);
|
|
453
|
+
groups.push(...secondaryGroups);
|
|
436
454
|
if (options.showCost && usage.apiCost > 0) {
|
|
437
455
|
groups.push([costToken(usage.apiCost)]);
|
|
438
456
|
}
|
|
@@ -453,6 +471,65 @@ function usageDetailLines(usage, cacheMetrics, options) {
|
|
|
453
471
|
}
|
|
454
472
|
return packed;
|
|
455
473
|
}
|
|
474
|
+
function packUsageGroups(groups, width) {
|
|
475
|
+
const packed = [];
|
|
476
|
+
for (const group of groups) {
|
|
477
|
+
let current = '';
|
|
478
|
+
for (const token of group) {
|
|
479
|
+
const candidate = current ? `${current} ${token}` : token;
|
|
480
|
+
if (!current || fitsLine(candidate, width)) {
|
|
481
|
+
current = candidate;
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
packed.push(current);
|
|
485
|
+
current = token;
|
|
486
|
+
}
|
|
487
|
+
if (current)
|
|
488
|
+
packed.push(current);
|
|
489
|
+
}
|
|
490
|
+
return packed;
|
|
491
|
+
}
|
|
492
|
+
function readableSidebarUsageLines(usage, cacheMetrics, width, showCost) {
|
|
493
|
+
const groups = [
|
|
494
|
+
[
|
|
495
|
+
`Req ${shortNumber(usage.assistantMessages, 1)}`,
|
|
496
|
+
`In ${panelNumber(usage.input)}`,
|
|
497
|
+
`Out ${panelNumber(usage.output)}`,
|
|
498
|
+
],
|
|
499
|
+
];
|
|
500
|
+
if (cacheMetrics.cachedRatio !== undefined) {
|
|
501
|
+
const cacheTokens = [
|
|
502
|
+
`Cached ${formatPercent(cacheMetrics.cachedRatio, 0)}`,
|
|
503
|
+
];
|
|
504
|
+
if (usage.cacheRead > 0)
|
|
505
|
+
cacheTokens.push(`Read ${panelNumber(usage.cacheRead)}`);
|
|
506
|
+
if (usage.cacheWrite > 0)
|
|
507
|
+
cacheTokens.push(`Write ${panelNumber(usage.cacheWrite)}`);
|
|
508
|
+
groups.push(cacheTokens);
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
const cacheTokens = [];
|
|
512
|
+
if (usage.cacheRead > 0)
|
|
513
|
+
cacheTokens.push(`Cache Read ${panelNumber(usage.cacheRead)}`);
|
|
514
|
+
if (usage.cacheWrite > 0)
|
|
515
|
+
cacheTokens.push(`Write ${panelNumber(usage.cacheWrite)}`);
|
|
516
|
+
if (cacheTokens.length > 0)
|
|
517
|
+
groups.push(cacheTokens);
|
|
518
|
+
}
|
|
519
|
+
const summaryTokens = [];
|
|
520
|
+
if (showCost && usage.apiCost > 0) {
|
|
521
|
+
summaryTokens.push(`Est ${formatApiCostValue(usage.apiCost)}`);
|
|
522
|
+
}
|
|
523
|
+
if (summaryTokens.length > 0)
|
|
524
|
+
groups.push(summaryTokens);
|
|
525
|
+
const allTokens = groups.flat();
|
|
526
|
+
if (allTokens.some((token) => !fitsLine(token, width)))
|
|
527
|
+
return undefined;
|
|
528
|
+
const packed = packUsageGroups(groups, width);
|
|
529
|
+
if (packed.length > 4)
|
|
530
|
+
return undefined;
|
|
531
|
+
return packed;
|
|
532
|
+
}
|
|
456
533
|
function formatQuotaPercent(value, options) {
|
|
457
534
|
const missing = options?.missing ?? '-';
|
|
458
535
|
if (value === undefined)
|
|
@@ -611,9 +688,13 @@ export function renderSidebarContextLine(tokens, percent, width) {
|
|
|
611
688
|
export function renderSidebarUsageLines(usage, config, options) {
|
|
612
689
|
const width = Math.max(8, Math.floor(config.sidebar.width || 36));
|
|
613
690
|
const cacheMetrics = getCacheCoverageMetrics(usage);
|
|
691
|
+
const showCost = options?.showCost ?? config.sidebar.showCost;
|
|
692
|
+
const readable = readableSidebarUsageLines(usage, cacheMetrics, width, showCost);
|
|
693
|
+
if (readable)
|
|
694
|
+
return readable.map((line) => fitLine(line, width));
|
|
614
695
|
return usageDetailLines(usage, cacheMetrics, {
|
|
615
696
|
width,
|
|
616
|
-
showCost
|
|
697
|
+
showCost,
|
|
617
698
|
numberToken: panelNumber,
|
|
618
699
|
costToken: (value) => `Est ${formatApiCostValue(value)}`,
|
|
619
700
|
cacheReadFirst: true,
|
package/dist/title.js
CHANGED
|
@@ -3,6 +3,7 @@ function sanitizeTitleFragment(value) {
|
|
|
3
3
|
.replace(/[\x00-\x1F\x7F-\x9F]/g, ' ')
|
|
4
4
|
.trimEnd();
|
|
5
5
|
}
|
|
6
|
+
const compactUsageTokenPattern = '(?:R\\$?[\\d.,]+[kKmM]?|W\\$?[\\d.,]+[kKmM]?|I\\$?[\\d.,]+[kKmM]?|O\\$?[\\d.,]+[kKmM]?|CR\\$?[\\d.,]+[kKmM]?|CW\\$?[\\d.,]+[kKmM]?|R(?:ead)?\\s+\\$?[\\d.,]+[kKmM]?|W(?:rite)?\\s+\\$?[\\d.,]+[kKmM]?|Cd\\s*\\d[\\d.,]*%|CC\\d[\\d.,]*%|CRC\\d[\\d.,]*%|API\\$\\S+|Est\\$\\S+)';
|
|
6
7
|
function isCoreDecoratedDetail(line) {
|
|
7
8
|
if (!line)
|
|
8
9
|
return false;
|
|
@@ -29,7 +30,7 @@ function isCoreDecoratedDetail(line) {
|
|
|
29
30
|
return true;
|
|
30
31
|
if (/^Est\$\S+$/.test(line))
|
|
31
32
|
return true;
|
|
32
|
-
if (
|
|
33
|
+
if (new RegExp(`^${compactUsageTokenPattern}(?:\\s+${compactUsageTokenPattern})*$`).test(line)) {
|
|
33
34
|
return true;
|
|
34
35
|
}
|
|
35
36
|
// Single-line compact mode compatibility.
|
|
@@ -125,7 +126,7 @@ function isSingleLineDecoratedPrefix(line) {
|
|
|
125
126
|
return true;
|
|
126
127
|
if (/^Est\$\S+(?:~|$)/.test(line))
|
|
127
128
|
return true;
|
|
128
|
-
if (
|
|
129
|
+
if (new RegExp(`^${compactUsageTokenPattern}(?:\\s+${compactUsageTokenPattern})*?(?:~|$)`).test(line)) {
|
|
129
130
|
return true;
|
|
130
131
|
}
|
|
131
132
|
return false;
|
package/package.json
CHANGED