@vibe-cafe/vibe-usage 0.10.18 → 0.10.19
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/parsers/codex-cache.js +1 -1
- package/src/parsers/codex.js +12 -31
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@ import { join } from 'node:path';
|
|
|
14
14
|
// separate from ~/.vibe-usage/state.json, whose hashes are the authoritative
|
|
15
15
|
// record of successful uploads and must remain backward-compatible.
|
|
16
16
|
export const CODEX_CACHE_SCHEMA_VERSION = 1;
|
|
17
|
-
export const CODEX_PARSER_ALGORITHM_VERSION =
|
|
17
|
+
export const CODEX_PARSER_ALGORITHM_VERSION = 3;
|
|
18
18
|
|
|
19
19
|
function hash(value, length = 24) {
|
|
20
20
|
return createHash('sha256').update(value).digest('hex').slice(0, length);
|
package/src/parsers/codex.js
CHANGED
|
@@ -26,12 +26,10 @@ import {
|
|
|
26
26
|
saveCodexFileTail,
|
|
27
27
|
} from './codex-cache.js';
|
|
28
28
|
|
|
29
|
-
const CODEX_API_BILLING_MARKER = '#billing=api';
|
|
30
|
-
const CODEX_SUBSCRIPTION_BILLING_MARKER = '#billing=subscription';
|
|
31
29
|
// Changing a model id changes its server-side bucket key. Keep pre-release
|
|
32
30
|
// history byte-for-byte stable so upgrading cannot re-upload the same tokens
|
|
33
|
-
// under decorated keys and double-count them.
|
|
34
|
-
const
|
|
31
|
+
// under tier-decorated keys and double-count them.
|
|
32
|
+
const CODEX_SERVICE_TIER_ATTRIBUTION_START_MS = Date.parse('2026-08-31T00:00:00.000Z');
|
|
35
33
|
|
|
36
34
|
function normalizeCodexServiceTier(value) {
|
|
37
35
|
if (typeof value !== 'string') return null;
|
|
@@ -41,22 +39,16 @@ function normalizeCodexServiceTier(value) {
|
|
|
41
39
|
return null;
|
|
42
40
|
}
|
|
43
41
|
|
|
44
|
-
function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (decorated === 'unknown' || timestampMs < CODEX_BILLING_ATTRIBUTION_START_MS) {
|
|
53
|
-
return decorated;
|
|
42
|
+
function decorateCodexModel(model, serviceTier, timestampMs) {
|
|
43
|
+
const rawModel = model || 'unknown';
|
|
44
|
+
if (
|
|
45
|
+
rawModel === 'unknown'
|
|
46
|
+
|| !serviceTier
|
|
47
|
+
|| timestampMs < CODEX_SERVICE_TIER_ATTRIBUTION_START_MS
|
|
48
|
+
) {
|
|
49
|
+
return rawModel;
|
|
54
50
|
}
|
|
55
|
-
|
|
56
|
-
decorated += subscriptionBilling
|
|
57
|
-
? CODEX_SUBSCRIPTION_BILLING_MARKER
|
|
58
|
-
: CODEX_API_BILLING_MARKER;
|
|
59
|
-
return decorated;
|
|
51
|
+
return `${rawModel}-${serviceTier}`;
|
|
60
52
|
}
|
|
61
53
|
|
|
62
54
|
// Codex stores live sessions in $CODEX_HOME/sessions (default ~/.codex) and,
|
|
@@ -634,7 +626,6 @@ async function parseSessionFile(filePath, snapshotSize, fm, boundary, {
|
|
|
634
626
|
|
|
635
627
|
let turnContextModel = previousTail?.turnContextModel || 'unknown';
|
|
636
628
|
let serviceTier = previousTail?.serviceTier || null;
|
|
637
|
-
let subscriptionBilling = previousTail?.subscriptionBilling || false;
|
|
638
629
|
let prevTotal = previousTail?.prevTotal || null;
|
|
639
630
|
let prevCumulativeTotal = previousTail?.prevCumulativeTotal ?? null;
|
|
640
631
|
const start = previousTail?.parsedBytes || 0;
|
|
@@ -708,10 +699,6 @@ async function parseSessionFile(filePath, snapshotSize, fm, boundary, {
|
|
|
708
699
|
const isReplayedHistory = inReplayBlock;
|
|
709
700
|
rawTokenSeen++;
|
|
710
701
|
|
|
711
|
-
if (hasSubscriptionPlan(payload.rate_limits?.plan_type)) {
|
|
712
|
-
subscriptionBilling = true;
|
|
713
|
-
}
|
|
714
|
-
|
|
715
702
|
const info = payload.info;
|
|
716
703
|
if (!info) continue;
|
|
717
704
|
|
|
@@ -761,12 +748,7 @@ async function parseSessionFile(filePath, snapshotSize, fm, boundary, {
|
|
|
761
748
|
if (!timestamp || isNaN(timestamp.getTime())) continue;
|
|
762
749
|
|
|
763
750
|
const rawModel = info.model || payload.model || turnContextModel || 'unknown';
|
|
764
|
-
const model = decorateCodexModel(
|
|
765
|
-
rawModel,
|
|
766
|
-
serviceTier,
|
|
767
|
-
subscriptionBilling,
|
|
768
|
-
timestamp.getTime()
|
|
769
|
-
);
|
|
751
|
+
const model = decorateCodexModel(rawModel, serviceTier, timestamp.getTime());
|
|
770
752
|
|
|
771
753
|
// OpenAI API: input_tokens INCLUDES cached, output_tokens INCLUDES reasoning.
|
|
772
754
|
// Normalize to Anthropic-style semantics where each field is non-overlapping.
|
|
@@ -822,7 +804,6 @@ async function parseSessionFile(filePath, snapshotSize, fm, boundary, {
|
|
|
822
804
|
firstSessionMetaSeen,
|
|
823
805
|
turnContextModel,
|
|
824
806
|
serviceTier,
|
|
825
|
-
subscriptionBilling,
|
|
826
807
|
prevTotal,
|
|
827
808
|
prevCumulativeTotal,
|
|
828
809
|
buckets,
|