@tokscale/cli 1.0.24 → 1.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/src/submit.ts CHANGED
@@ -10,7 +10,7 @@ import { exec } from "node:child_process";
10
10
  import { promisify } from "node:util";
11
11
  import { loadCredentials, getApiBaseUrl, loadStarCache, saveStarCache } from "./credentials.js";
12
12
  import { parseLocalSourcesAsync, finalizeReportAndGraphAsync, type ParsedMessages } from "./native.js";
13
- import { syncCursorCache, loadCursorCredentials } from "./cursor.js";
13
+ import { syncCursorCache, isCursorLoggedIn, hasCursorUsageCache } from "./cursor.js";
14
14
  import type { TokenContributionData } from "./graph-types.js";
15
15
  import { formatCurrency } from "./table.js";
16
16
 
@@ -221,16 +221,21 @@ export async function submit(options: SubmitOptions = {}): Promise<void> {
221
221
  until: options.until,
222
222
  year: options.year,
223
223
  }),
224
- includeCursor && loadCursorCredentials()
224
+ includeCursor && isCursorLoggedIn()
225
225
  ? syncCursorCache()
226
- : Promise.resolve({ synced: false, rows: 0 }),
226
+ : Promise.resolve({ synced: false, rows: 0, error: undefined }),
227
227
  ]);
228
228
 
229
+ if (includeCursor && cursorSync.error && (cursorSync.synced || hasCursorUsageCache())) {
230
+ const prefix = cursorSync.synced ? "Cursor sync warning" : "Cursor sync failed; using cached data";
231
+ console.log(pc.yellow(` ${prefix}: ${cursorSync.error}`));
232
+ }
233
+
229
234
  // Phase 2: Finalize with pricing (combines local + cursor)
230
235
  // Single subprocess call ensures consistent pricing for both report and graph
231
236
  const { report, graph } = await finalizeReportAndGraphAsync({
232
237
  localMessages,
233
- includeCursor: includeCursor && cursorSync.synced,
238
+ includeCursor: includeCursor && (cursorSync.synced || hasCursorUsageCache()),
234
239
  since: options.since,
235
240
  until: options.until,
236
241
  year: options.year,
@@ -20,7 +20,7 @@ import {
20
20
  type ParsedMessages,
21
21
  } from "../../native.js";
22
22
 
23
- import { syncCursorCache, loadCursorCredentials } from "../../cursor.js";
23
+ import { syncCursorCache, isCursorLoggedIn, hasCursorUsageCache } from "../../cursor.js";
24
24
  import { getModelColor } from "../utils/colors.js";
25
25
  import { loadCachedData, saveCachedData, isCacheStale, loadSettings } from "../config/settings.js";
26
26
 
@@ -156,7 +156,7 @@ async function loadData(
156
156
  setPhase?.("parsing-sources");
157
157
 
158
158
  const phase1Results = await Promise.allSettled([
159
- includeCursor && loadCursorCredentials() ? syncCursorCache() : Promise.resolve({ synced: false, rows: 0 }),
159
+ includeCursor && isCursorLoggedIn() ? syncCursorCache() : Promise.resolve({ synced: false, rows: 0, error: undefined }),
160
160
  localSources.length > 0
161
161
  ? parseLocalSourcesAsync({ sources: localSources as ("opencode" | "claude" | "codex" | "gemini" | "amp" | "droid")[], since, until, year })
162
162
  : Promise.resolve({ messages: [], opencodeCount: 0, claudeCount: 0, codexCount: 0, geminiCount: 0, ampCount: 0, droidCount: 0, processingTimeMs: 0 } as ParsedMessages),
@@ -164,11 +164,17 @@ async function loadData(
164
164
 
165
165
  const cursorSync = phase1Results[0].status === "fulfilled"
166
166
  ? phase1Results[0].value
167
- : { synced: false, rows: 0 };
167
+ : { synced: false, rows: 0, error: "Cursor sync failed" };
168
168
  const localMessages = phase1Results[1].status === "fulfilled"
169
169
  ? phase1Results[1].value
170
170
  : null;
171
171
 
172
+ if (includeCursor && cursorSync.error && (cursorSync.synced || hasCursorUsageCache())) {
173
+ // TUI should keep working; just emit a warning.
174
+ const prefix = cursorSync.synced ? "Cursor sync warning" : "Cursor sync failed; using cached data";
175
+ console.warn(`${prefix}: ${cursorSync.error}`);
176
+ }
177
+
172
178
  const emptyMessages: ParsedMessages = {
173
179
  messages: [],
174
180
  opencodeCount: 0,
@@ -184,7 +190,7 @@ async function loadData(
184
190
  // Single call ensures consistent pricing between report and graph
185
191
  const { report, graph } = await finalizeReportAndGraphAsync({
186
192
  localMessages: localMessages || emptyMessages,
187
- includeCursor: includeCursor && cursorSync.synced,
193
+ includeCursor: includeCursor && (cursorSync.synced || hasCursorUsageCache()),
188
194
  since,
189
195
  until,
190
196
  year,
package/src/wrapped.ts CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  finalizeReportAndGraphAsync,
10
10
  type ParsedMessages,
11
11
  } from "./native.js";
12
- import { syncCursorCache, loadCursorCredentials } from "./cursor.js";
12
+ import { syncCursorCache, isCursorLoggedIn, hasCursorUsageCache } from "./cursor.js";
13
13
  import { loadCredentials } from "./credentials.js";
14
14
  import type { SourceType } from "./graph-types.js";
15
15
 
@@ -218,7 +218,7 @@ async function loadWrappedData(options: WrappedOptions): Promise<WrappedData> {
218
218
  const until = `${year}-12-31`;
219
219
 
220
220
  const phase1Results = await Promise.allSettled([
221
- includeCursor && loadCursorCredentials() ? syncCursorCache() : Promise.resolve({ synced: false, rows: 0 }),
221
+ includeCursor && isCursorLoggedIn() ? syncCursorCache() : Promise.resolve({ synced: false, rows: 0, error: undefined }),
222
222
  localSources.length > 0
223
223
  ? parseLocalSourcesAsync({ sources: localSources, since, until, year })
224
224
  : Promise.resolve({ messages: [], opencodeCount: 0, claudeCount: 0, codexCount: 0, geminiCount: 0, ampCount: 0, droidCount: 0, processingTimeMs: 0 } as ParsedMessages),
@@ -226,11 +226,16 @@ async function loadWrappedData(options: WrappedOptions): Promise<WrappedData> {
226
226
 
227
227
  const cursorSync = phase1Results[0].status === "fulfilled"
228
228
  ? phase1Results[0].value
229
- : { synced: false, rows: 0 };
229
+ : { synced: false, rows: 0, error: "Cursor sync failed" };
230
230
  const localMessages = phase1Results[1].status === "fulfilled"
231
231
  ? phase1Results[1].value
232
232
  : null;
233
233
 
234
+ if (includeCursor && cursorSync.error && (cursorSync.synced || hasCursorUsageCache())) {
235
+ const prefix = cursorSync.synced ? "Cursor sync warning" : "Cursor sync failed; using cached data";
236
+ console.log(pc.yellow(` ${prefix}: ${cursorSync.error}`));
237
+ }
238
+
234
239
  const emptyMessages: ParsedMessages = {
235
240
  messages: [],
236
241
  opencodeCount: 0,
@@ -244,7 +249,7 @@ async function loadWrappedData(options: WrappedOptions): Promise<WrappedData> {
244
249
 
245
250
  const { report, graph } = await finalizeReportAndGraphAsync({
246
251
  localMessages: localMessages || emptyMessages,
247
- includeCursor: includeCursor && cursorSync.synced,
252
+ includeCursor: includeCursor && (cursorSync.synced || hasCursorUsageCache()),
248
253
  since,
249
254
  until,
250
255
  year,