@vibe-cafe/vibe-usage 0.14.4 → 0.14.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/src/state.js CHANGED
@@ -52,24 +52,37 @@ function sameIdentity(a, b) {
52
52
  // `identity` is optional: callers that only read the recorded counts (e.g.
53
53
  // `status`) pass nothing and keep the pre-0.11.1 behaviour of taking the file
54
54
  // at face value.
55
+ function parserMetaFrom(parsed) {
56
+ const meta = parsed?.parserMeta;
57
+ return meta && typeof meta === 'object' && !Array.isArray(meta) ? meta : {};
58
+ }
59
+
55
60
  export function loadState(identity) {
56
61
  if (!existsSync(STATE_FILE)) return { buckets: {}, sessions: {} };
57
62
  try {
58
63
  const parsed = JSON.parse(readFileSync(STATE_FILE, 'utf-8'));
59
64
  const buckets = parsed.buckets ?? {};
60
65
  const sessions = parsed.sessions ?? {};
66
+ // Local parser diagnostics (currently Cursor's account/newest event).
67
+ // Purely additive; older CLIs ignore it and it never enters an upload.
68
+ const parserMeta = parserMetaFrom(parsed);
69
+ const withMeta = (value) => (Object.keys(parserMeta).length > 0
70
+ ? { ...value, parserMeta }
71
+ : value);
61
72
  if (!isIdentity(identity) || !isIdentity(parsed.identity)) {
62
73
  // No identity recorded — written by a CLI older than 0.11.1. Adopt the
63
74
  // entries as-is rather than forcing a re-upload: on upgrade day that
64
75
  // would make every installed client re-send its whole history at once.
65
76
  // The next saveState() stamps the current identity, so any later re-bind
66
77
  // is caught.
67
- return { buckets, sessions };
78
+ return withMeta({ buckets, sessions });
68
79
  }
69
- if (sameIdentity(parsed.identity, identity)) return { buckets, sessions };
80
+ if (sameIdentity(parsed.identity, identity)) return withMeta({ buckets, sessions });
70
81
  // Bound to a different account or server: nothing recorded here was ever
71
82
  // uploaded to the current target, so start empty and re-send local history.
72
83
  // `identityChanged` is a runtime signal for the caller, never persisted.
84
+ // Parser diagnostics describe the old target's local source, so they are
85
+ // dropped with the old hashes.
73
86
  return { buckets: {}, sessions: {}, identityChanged: true };
74
87
  } catch {
75
88
  // Corrupt/unreadable state must not lose data — treat as empty, which
@@ -91,6 +104,10 @@ export function saveState(state, identity) {
91
104
  buckets: state.buckets ?? {},
92
105
  sessions: state.sessions ?? {},
93
106
  };
107
+ if (state.parserMeta && typeof state.parserMeta === 'object'
108
+ && Object.keys(state.parserMeta).length > 0) {
109
+ payload.parserMeta = state.parserMeta;
110
+ }
94
111
  if (isIdentity(identity)) {
95
112
  payload.identity = {
96
113
  apiUrl: identity.apiUrl,