@vibescore/tracker 0.1.0 → 0.1.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/package.json +1 -1
- package/src/lib/rollout.js +75 -34
- package/src/lib/uploader.js +3 -3
package/package.json
CHANGED
package/src/lib/rollout.js
CHANGED
|
@@ -469,49 +469,90 @@ async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets })
|
|
|
469
469
|
}
|
|
470
470
|
if (touchedGroups.size === 0) return 0;
|
|
471
471
|
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
if (!hourStart) continue;
|
|
478
|
-
const groupKey = groupBucketKey(parsed.source, hourStart);
|
|
479
|
-
if (!touchedGroups.has(groupKey)) continue;
|
|
480
|
-
|
|
481
|
-
let group = grouped.get(groupKey);
|
|
482
|
-
if (!group) {
|
|
483
|
-
group = {
|
|
484
|
-
source: normalizeSourceInput(parsed.source) || DEFAULT_SOURCE,
|
|
485
|
-
hourStart,
|
|
486
|
-
models: new Set(),
|
|
487
|
-
totals: initTotals()
|
|
488
|
-
};
|
|
489
|
-
grouped.set(groupKey, group);
|
|
472
|
+
const groupQueued = hourlyState.groupQueued && typeof hourlyState.groupQueued === 'object' ? hourlyState.groupQueued : {};
|
|
473
|
+
const legacyGroups = new Set();
|
|
474
|
+
for (const groupKey of touchedGroups) {
|
|
475
|
+
if (Object.prototype.hasOwnProperty.call(groupQueued, groupKey)) {
|
|
476
|
+
legacyGroups.add(groupKey);
|
|
490
477
|
}
|
|
491
|
-
group.models.add(parsed.model || DEFAULT_MODEL);
|
|
492
|
-
addTotals(group.totals, bucket.totals);
|
|
493
478
|
}
|
|
494
479
|
|
|
495
480
|
const toAppend = [];
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
const groupKey = groupBucketKey(
|
|
501
|
-
if (
|
|
481
|
+
for (const bucketStart of touchedBuckets) {
|
|
482
|
+
const parsed = parseBucketKey(bucketStart);
|
|
483
|
+
const hourStart = parsed.hourStart;
|
|
484
|
+
if (!hourStart) continue;
|
|
485
|
+
const groupKey = groupBucketKey(parsed.source, hourStart);
|
|
486
|
+
if (legacyGroups.has(groupKey)) continue;
|
|
487
|
+
|
|
488
|
+
const normalizedKey = bucketKey(parsed.source, parsed.model, hourStart);
|
|
489
|
+
const bucket = hourlyState.buckets ? hourlyState.buckets[normalizedKey] : null;
|
|
490
|
+
if (!bucket || !bucket.totals) continue;
|
|
491
|
+
if (bucket.queuedKey != null && typeof bucket.queuedKey !== 'string') {
|
|
492
|
+
bucket.queuedKey = null;
|
|
493
|
+
}
|
|
494
|
+
const key = totalsKey(bucket.totals);
|
|
495
|
+
if (bucket.queuedKey === key) continue;
|
|
496
|
+
const source = normalizeSourceInput(parsed.source) || DEFAULT_SOURCE;
|
|
497
|
+
const model = normalizeModelInput(parsed.model) || DEFAULT_MODEL;
|
|
502
498
|
toAppend.push(
|
|
503
499
|
JSON.stringify({
|
|
504
|
-
source
|
|
500
|
+
source,
|
|
505
501
|
model,
|
|
506
|
-
hour_start:
|
|
507
|
-
input_tokens:
|
|
508
|
-
cached_input_tokens:
|
|
509
|
-
output_tokens:
|
|
510
|
-
reasoning_output_tokens:
|
|
511
|
-
total_tokens:
|
|
502
|
+
hour_start: hourStart,
|
|
503
|
+
input_tokens: bucket.totals.input_tokens,
|
|
504
|
+
cached_input_tokens: bucket.totals.cached_input_tokens,
|
|
505
|
+
output_tokens: bucket.totals.output_tokens,
|
|
506
|
+
reasoning_output_tokens: bucket.totals.reasoning_output_tokens,
|
|
507
|
+
total_tokens: bucket.totals.total_tokens
|
|
512
508
|
})
|
|
513
509
|
);
|
|
514
|
-
|
|
510
|
+
bucket.queuedKey = key;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (legacyGroups.size > 0) {
|
|
514
|
+
const grouped = new Map();
|
|
515
|
+
for (const [key, bucket] of Object.entries(hourlyState.buckets || {})) {
|
|
516
|
+
if (!bucket || !bucket.totals) continue;
|
|
517
|
+
const parsed = parseBucketKey(key);
|
|
518
|
+
const hourStart = parsed.hourStart;
|
|
519
|
+
if (!hourStart) continue;
|
|
520
|
+
const groupKey = groupBucketKey(parsed.source, hourStart);
|
|
521
|
+
if (!legacyGroups.has(groupKey)) continue;
|
|
522
|
+
|
|
523
|
+
let group = grouped.get(groupKey);
|
|
524
|
+
if (!group) {
|
|
525
|
+
group = {
|
|
526
|
+
source: normalizeSourceInput(parsed.source) || DEFAULT_SOURCE,
|
|
527
|
+
hourStart,
|
|
528
|
+
models: new Set(),
|
|
529
|
+
totals: initTotals()
|
|
530
|
+
};
|
|
531
|
+
grouped.set(groupKey, group);
|
|
532
|
+
}
|
|
533
|
+
group.models.add(parsed.model || DEFAULT_MODEL);
|
|
534
|
+
addTotals(group.totals, bucket.totals);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
for (const group of grouped.values()) {
|
|
538
|
+
const model = group.models.size === 1 ? [...group.models][0] : DEFAULT_MODEL;
|
|
539
|
+
const key = totalsKey(group.totals);
|
|
540
|
+
const groupKey = groupBucketKey(group.source, group.hourStart);
|
|
541
|
+
if (groupQueued[groupKey] === key) continue;
|
|
542
|
+
toAppend.push(
|
|
543
|
+
JSON.stringify({
|
|
544
|
+
source: group.source,
|
|
545
|
+
model,
|
|
546
|
+
hour_start: group.hourStart,
|
|
547
|
+
input_tokens: group.totals.input_tokens,
|
|
548
|
+
cached_input_tokens: group.totals.cached_input_tokens,
|
|
549
|
+
output_tokens: group.totals.output_tokens,
|
|
550
|
+
reasoning_output_tokens: group.totals.reasoning_output_tokens,
|
|
551
|
+
total_tokens: group.totals.total_tokens
|
|
552
|
+
})
|
|
553
|
+
);
|
|
554
|
+
groupQueued[groupKey] = key;
|
|
555
|
+
}
|
|
515
556
|
}
|
|
516
557
|
|
|
517
558
|
hourlyState.groupQueued = groupQueued;
|
package/src/lib/uploader.js
CHANGED
|
@@ -78,7 +78,7 @@ async function readBatch(queuePath, startOffset, maxBuckets) {
|
|
|
78
78
|
const model = normalizeModel(bucket?.model) || DEFAULT_MODEL;
|
|
79
79
|
bucket.source = source;
|
|
80
80
|
bucket.model = model;
|
|
81
|
-
bucketMap.set(bucketKey(source, hourStart), bucket);
|
|
81
|
+
bucketMap.set(bucketKey(source, model, hourStart), bucket);
|
|
82
82
|
linesRead += 1;
|
|
83
83
|
if (linesRead >= maxBuckets) break;
|
|
84
84
|
}
|
|
@@ -97,8 +97,8 @@ async function safeFileSize(p) {
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
function bucketKey(source, hourStart) {
|
|
101
|
-
return `${source}${BUCKET_SEPARATOR}${hourStart}`;
|
|
100
|
+
function bucketKey(source, model, hourStart) {
|
|
101
|
+
return `${source}${BUCKET_SEPARATOR}${model}${BUCKET_SEPARATOR}${hourStart}`;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
function normalizeSource(value) {
|