ccus-cli 0.2.5 → 0.2.6
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/dist/lib/aggregate.js +31 -12
- package/dist/lib/dashboard.js +4 -3
- package/package.json +1 -1
package/dist/lib/aggregate.js
CHANGED
|
@@ -411,8 +411,11 @@ function buildSevenDayCurveFromEvents(events) {
|
|
|
411
411
|
}
|
|
412
412
|
/**
|
|
413
413
|
* 同一 personKey 的 7d 累计曲线:把该人**所有 bundle**(非仅 winner)的 rawEvents 计算成事件、
|
|
414
|
-
* 取非 null `sevenDayUsagePct`、按 timestamp 升序合并、对完全相同 timestamp
|
|
415
|
-
*
|
|
414
|
+
* 取非 null `sevenDayUsagePct`、按 timestamp 升序合并、对完全相同 timestamp 去重,再做读数去毛刺。
|
|
415
|
+
*
|
|
416
|
+
* Claude 与 Codex 是两个不同额度池的独立曲线(读数水平常常相差悬殊),按 source 各自建一条,
|
|
417
|
+
* 算累计时分别做分段峰谷和再相加。混成一条会让低位源频繁触发假 reset、把高位源的上升段反复重算,
|
|
418
|
+
* 导致累计严重虚高(实测 jizhiqiang 混算 221% vs 分源相加 44%)。
|
|
416
419
|
*
|
|
417
420
|
* 走全样本而非 winner,是因为累计指标是同一条共享额度曲线的密集采样:只取 winner 会漏掉非 winner
|
|
418
421
|
* 机器的样本(曲线稀疏、累计偏小),分机各自累计再相加又会翻倍。结果按 bundles 数组缓存复用。
|
|
@@ -423,27 +426,31 @@ function buildPersonSevenDayCurve(bundles) {
|
|
|
423
426
|
if (cached) {
|
|
424
427
|
return cached;
|
|
425
428
|
}
|
|
426
|
-
const
|
|
429
|
+
const claudeByPerson = new Map();
|
|
430
|
+
const codexByPerson = new Map();
|
|
427
431
|
for (const { bundle } of bundles) {
|
|
428
432
|
const personKey = bundlePersonKey(bundle);
|
|
429
|
-
// 含 Claude + Codex 两源读数:codex 7d 读数不再过滤,并入同一条曲线算累计
|
|
430
433
|
for (const record of bundle.rawEvents.filter((r) => isPersistedStatuslineEvent(r))) {
|
|
431
434
|
const event = (0, payload_1.computeStatuslineEvent)(record);
|
|
432
435
|
if (event.sevenDayUsagePct === null) {
|
|
433
436
|
continue;
|
|
434
437
|
}
|
|
435
|
-
const
|
|
438
|
+
const target = (0, payload_1.isCodexSourceEvent)(event) ? codexByPerson : claudeByPerson;
|
|
439
|
+
const list = target.get(personKey);
|
|
436
440
|
if (list) {
|
|
437
441
|
list.push(event);
|
|
438
442
|
}
|
|
439
443
|
else {
|
|
440
|
-
|
|
444
|
+
target.set(personKey, [event]);
|
|
441
445
|
}
|
|
442
446
|
}
|
|
443
447
|
}
|
|
444
448
|
const curves = new Map();
|
|
445
|
-
for (const
|
|
446
|
-
curves.set(personKey,
|
|
449
|
+
for (const personKey of new Set([...claudeByPerson.keys(), ...codexByPerson.keys()])) {
|
|
450
|
+
curves.set(personKey, {
|
|
451
|
+
claude: buildSevenDayCurveFromEvents(claudeByPerson.get(personKey) ?? []),
|
|
452
|
+
codex: buildSevenDayCurveFromEvents(codexByPerson.get(personKey) ?? []),
|
|
453
|
+
});
|
|
447
454
|
}
|
|
448
455
|
personSevenDayCurveCache.set(bundles, curves);
|
|
449
456
|
return curves;
|
|
@@ -456,6 +463,18 @@ function sliceCurveByDate(curve, date) {
|
|
|
456
463
|
function sliceCurveByWeek(curve, week) {
|
|
457
464
|
return curve.filter((event) => weekKey(new Date(event.timestamp)) === week);
|
|
458
465
|
}
|
|
466
|
+
/**
|
|
467
|
+
* 分源 7d 累计:Claude 与 Codex 各自按区间切片做分段峰谷和,再用 `addNullable` 相加。
|
|
468
|
+
* 两源是不同额度池的独立曲线,混算会互相触发假 reset 而虚高;分源算后相加,与 CSV 里 token /
|
|
469
|
+
* 消息数「Claude+Codex 合计」口径一致。该 personKey 无任何曲线、或两源都无有效样本时返回 null。
|
|
470
|
+
*/
|
|
471
|
+
function computeCumulativeSevenDayBySource(curves, personKey, slicer, rangeKey) {
|
|
472
|
+
const bySource = curves.get(personKey);
|
|
473
|
+
if (!bySource) {
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
return addNullable(computeCumulativeSevenDay(slicer(bySource.claude, rangeKey)), computeCumulativeSevenDay(slicer(bySource.codex, rangeKey)));
|
|
477
|
+
}
|
|
459
478
|
/** 从一组事件按真实时间戳重算 5h / 7d 的 peak(max)与 latest(时间戳最新非空)。 */
|
|
460
479
|
function recomputeUsage(events) {
|
|
461
480
|
const newestFirst = [...events].sort((left, right) => new Date(right.timestamp).getTime() - new Date(left.timestamp).getTime());
|
|
@@ -526,8 +545,8 @@ function buildAggregatedDailyRows(bundles) {
|
|
|
526
545
|
const codexUsage = recomputeUsage(codexEvents);
|
|
527
546
|
// 额度回退:rawEvents 缺时从 daySummary 取(Claude+Codex 合并,见 fallbackWeeklyUsage)
|
|
528
547
|
const fallback = fallbackWeeklyUsage(reps.map((r) => r.day));
|
|
529
|
-
//
|
|
530
|
-
const sevenDayCumulativeUsagePct =
|
|
548
|
+
// 累计指标走全样本分源曲线(Claude + Codex 各自切片累计后相加),不走单机的 recomputeUsage,避免漏掉另一台机器的样本。
|
|
549
|
+
const sevenDayCumulativeUsagePct = computeCumulativeSevenDayBySource(curves, personKey, sliceCurveByDate, date);
|
|
531
550
|
rows.push({
|
|
532
551
|
personKey,
|
|
533
552
|
date,
|
|
@@ -621,8 +640,8 @@ function buildAggregatedWeeklyRows(bundles) {
|
|
|
621
640
|
const usage = recomputeUsage(claudeEvents);
|
|
622
641
|
const codexUsage = recomputeUsage(codexEvents);
|
|
623
642
|
const fallback = fallbackWeeklyUsage(acc.days);
|
|
624
|
-
//
|
|
625
|
-
const sevenDayCumulativeUsagePct =
|
|
643
|
+
// 整周累计:Claude + Codex 各自在整周子曲线上做分段峰谷和后相加,跨天边界增量被计入,故 weekly ≥ Σ daily。
|
|
644
|
+
const sevenDayCumulativeUsagePct = computeCumulativeSevenDayBySource(curves, acc.personKey, sliceCurveByWeek, acc.week);
|
|
626
645
|
rows.push({
|
|
627
646
|
personKey: acc.personKey,
|
|
628
647
|
week: acc.week,
|
package/dist/lib/dashboard.js
CHANGED
|
@@ -34,8 +34,8 @@ function summarizeEvents(events) {
|
|
|
34
34
|
const codexByDesc = events.filter(payload_1.isCodexSourceEvent).sort(byDesc);
|
|
35
35
|
const latestUsagePct = (0, aggregate_1.addNullable)(claudeByDesc.find((event) => event.usagePct !== null)?.usagePct ?? null, codexByDesc.find((event) => event.usagePct !== null)?.usagePct ?? null);
|
|
36
36
|
const latestSevenDayUsagePct = (0, aggregate_1.addNullable)(claudeByDesc.find((event) => event.sevenDayUsagePct !== null)?.sevenDayUsagePct ?? null, codexByDesc.find((event) => event.sevenDayUsagePct !== null)?.sevenDayUsagePct ?? null);
|
|
37
|
-
// 7d
|
|
38
|
-
const sevenDayCumulativeUsagePct = (0, aggregate_1.computeCumulativeSevenDay)((0, aggregate_1.buildSevenDayCurveFromEvents)(events));
|
|
37
|
+
// 7d 分源累计:Claude + Codex 各自「去毛刺 + 分段峰谷和」后相加,与 aggregate 同口径(混算会虚高)。
|
|
38
|
+
const sevenDayCumulativeUsagePct = (0, aggregate_1.addNullable)((0, aggregate_1.computeCumulativeSevenDay)((0, aggregate_1.buildSevenDayCurveFromEvents)(events.filter((event) => !(0, payload_1.isCodexSourceEvent)(event)))), (0, aggregate_1.computeCumulativeSevenDay)((0, aggregate_1.buildSevenDayCurveFromEvents)(events.filter(payload_1.isCodexSourceEvent))));
|
|
39
39
|
return {
|
|
40
40
|
fiveHourLatestUsagePct: latestUsagePct,
|
|
41
41
|
fiveHourPeakUsagePct: usages.length > 0 ? (0, time_1.roundNumber)(Math.max(...usages), 1) : null,
|
|
@@ -79,8 +79,9 @@ function bucketizeEvents(events, start, end, bucketMinutes = 5) {
|
|
|
79
79
|
}
|
|
80
80
|
// 7d 累计曲线(去毛刺 + 分段峰谷和的逐点版本)映射到时间桶:曲线已按时间升序,
|
|
81
81
|
// 同桶内后写覆盖前写,最终每个桶留下落在其区间内最后一个累计点的值(单调,等于桶内最大累计)。
|
|
82
|
+
// 只画 Claude 源:折线图是 Claude 趋势看板(与同图 5h/7d 两条线同源),Codex 累计已并入顶部 summary 数值。
|
|
82
83
|
const cumulativeByBucket = new Map();
|
|
83
|
-
for (const point of (0, aggregate_1.computeCumulativeSevenDayCurve)((0, aggregate_1.buildSevenDayCurveFromEvents)(events))) {
|
|
84
|
+
for (const point of (0, aggregate_1.computeCumulativeSevenDayCurve)((0, aggregate_1.buildSevenDayCurveFromEvents)(events.filter((event) => !(0, payload_1.isCodexSourceEvent)(event))))) {
|
|
84
85
|
const ts = new Date(point.timestamp).getTime();
|
|
85
86
|
if (ts < start.getTime() || ts > end.getTime()) {
|
|
86
87
|
continue;
|