@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-cafe/vibe-usage",
3
- "version": "0.10.18",
3
+ "version": "0.10.19",
4
4
  "description": "Track your AI coding tool token usage and sync to vibecafe.ai",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -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 = 2;
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);
@@ -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 CODEX_BILLING_ATTRIBUTION_START_MS = Date.parse('2026-08-31T00:00:00.000Z');
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 hasSubscriptionPlan(planType) {
45
- return typeof planType === 'string'
46
- && planType.trim() !== ''
47
- && planType.toLowerCase() !== 'unknown';
48
- }
49
-
50
- function decorateCodexModel(model, serviceTier, subscriptionBilling, timestampMs) {
51
- let decorated = model || 'unknown';
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
- if (serviceTier) decorated += `-${serviceTier}`;
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,