@tokscale/cli 1.4.3 → 2.0.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.
Files changed (188) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +128 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +19 -26
  6. package/dist/auth.d.ts +0 -17
  7. package/dist/auth.d.ts.map +0 -1
  8. package/dist/auth.js +0 -162
  9. package/dist/auth.js.map +0 -1
  10. package/dist/cli.d.ts +0 -9
  11. package/dist/cli.d.ts.map +0 -1
  12. package/dist/cli.js +0 -1550
  13. package/dist/cli.js.map +0 -1
  14. package/dist/credentials.d.ts +0 -50
  15. package/dist/credentials.d.ts.map +0 -1
  16. package/dist/credentials.js +0 -151
  17. package/dist/credentials.js.map +0 -1
  18. package/dist/cursor.d.ts +0 -167
  19. package/dist/cursor.d.ts.map +0 -1
  20. package/dist/cursor.js +0 -906
  21. package/dist/cursor.js.map +0 -1
  22. package/dist/date-utils.d.ts +0 -10
  23. package/dist/date-utils.d.ts.map +0 -1
  24. package/dist/date-utils.js +0 -47
  25. package/dist/date-utils.js.map +0 -1
  26. package/dist/graph-types.d.ts +0 -142
  27. package/dist/graph-types.d.ts.map +0 -1
  28. package/dist/graph-types.js +0 -6
  29. package/dist/graph-types.js.map +0 -1
  30. package/dist/native-runner.d.ts +0 -11
  31. package/dist/native-runner.d.ts.map +0 -1
  32. package/dist/native-runner.js +0 -77
  33. package/dist/native-runner.js.map +0 -1
  34. package/dist/native.d.ts +0 -106
  35. package/dist/native.d.ts.map +0 -1
  36. package/dist/native.js +0 -302
  37. package/dist/native.js.map +0 -1
  38. package/dist/sessions/types.d.ts +0 -28
  39. package/dist/sessions/types.d.ts.map +0 -1
  40. package/dist/sessions/types.js +0 -27
  41. package/dist/sessions/types.js.map +0 -1
  42. package/dist/spinner.d.ts +0 -75
  43. package/dist/spinner.d.ts.map +0 -1
  44. package/dist/spinner.js +0 -203
  45. package/dist/spinner.js.map +0 -1
  46. package/dist/submit.d.ts +0 -23
  47. package/dist/submit.d.ts.map +0 -1
  48. package/dist/submit.js +0 -294
  49. package/dist/submit.js.map +0 -1
  50. package/dist/table.d.ts +0 -42
  51. package/dist/table.d.ts.map +0 -1
  52. package/dist/table.js +0 -181
  53. package/dist/table.js.map +0 -1
  54. package/dist/tui/App.d.ts +0 -4
  55. package/dist/tui/App.d.ts.map +0 -1
  56. package/dist/tui/App.js +0 -333
  57. package/dist/tui/App.js.map +0 -1
  58. package/dist/tui/components/BarChart.d.ts +0 -17
  59. package/dist/tui/components/BarChart.d.ts.map +0 -1
  60. package/dist/tui/components/BarChart.js +0 -146
  61. package/dist/tui/components/BarChart.js.map +0 -1
  62. package/dist/tui/components/DailyView.d.ts +0 -13
  63. package/dist/tui/components/DailyView.d.ts.map +0 -1
  64. package/dist/tui/components/DailyView.js +0 -86
  65. package/dist/tui/components/DailyView.js.map +0 -1
  66. package/dist/tui/components/DateBreakdownPanel.d.ts +0 -7
  67. package/dist/tui/components/DateBreakdownPanel.d.ts.map +0 -1
  68. package/dist/tui/components/DateBreakdownPanel.js +0 -36
  69. package/dist/tui/components/DateBreakdownPanel.js.map +0 -1
  70. package/dist/tui/components/Footer.d.ts +0 -28
  71. package/dist/tui/components/Footer.d.ts.map +0 -1
  72. package/dist/tui/components/Footer.js +0 -130
  73. package/dist/tui/components/Footer.js.map +0 -1
  74. package/dist/tui/components/Header.d.ts +0 -9
  75. package/dist/tui/components/Header.d.ts.map +0 -1
  76. package/dist/tui/components/Header.js +0 -20
  77. package/dist/tui/components/Header.js.map +0 -1
  78. package/dist/tui/components/Legend.d.ts +0 -7
  79. package/dist/tui/components/Legend.d.ts.map +0 -1
  80. package/dist/tui/components/Legend.js +0 -16
  81. package/dist/tui/components/Legend.js.map +0 -1
  82. package/dist/tui/components/LoadingSpinner.d.ts +0 -8
  83. package/dist/tui/components/LoadingSpinner.d.ts.map +0 -1
  84. package/dist/tui/components/LoadingSpinner.js +0 -55
  85. package/dist/tui/components/LoadingSpinner.js.map +0 -1
  86. package/dist/tui/components/ModelRow.d.ts +0 -13
  87. package/dist/tui/components/ModelRow.d.ts.map +0 -1
  88. package/dist/tui/components/ModelRow.js +0 -15
  89. package/dist/tui/components/ModelRow.js.map +0 -1
  90. package/dist/tui/components/ModelView.d.ts +0 -13
  91. package/dist/tui/components/ModelView.d.ts.map +0 -1
  92. package/dist/tui/components/ModelView.js +0 -96
  93. package/dist/tui/components/ModelView.js.map +0 -1
  94. package/dist/tui/components/OverviewView.d.ts +0 -14
  95. package/dist/tui/components/OverviewView.d.ts.map +0 -1
  96. package/dist/tui/components/OverviewView.js +0 -65
  97. package/dist/tui/components/OverviewView.js.map +0 -1
  98. package/dist/tui/components/StatsView.d.ts +0 -14
  99. package/dist/tui/components/StatsView.d.ts.map +0 -1
  100. package/dist/tui/components/StatsView.js +0 -102
  101. package/dist/tui/components/StatsView.js.map +0 -1
  102. package/dist/tui/components/TokenBreakdown.d.ts +0 -14
  103. package/dist/tui/components/TokenBreakdown.d.ts.map +0 -1
  104. package/dist/tui/components/TokenBreakdown.js +0 -10
  105. package/dist/tui/components/TokenBreakdown.js.map +0 -1
  106. package/dist/tui/components/index.d.ts +0 -16
  107. package/dist/tui/components/index.d.ts.map +0 -1
  108. package/dist/tui/components/index.js +0 -13
  109. package/dist/tui/components/index.js.map +0 -1
  110. package/dist/tui/config/settings.d.ts +0 -15
  111. package/dist/tui/config/settings.d.ts.map +0 -1
  112. package/dist/tui/config/settings.js +0 -147
  113. package/dist/tui/config/settings.js.map +0 -1
  114. package/dist/tui/config/themes.d.ts +0 -15
  115. package/dist/tui/config/themes.d.ts.map +0 -1
  116. package/dist/tui/config/themes.js +0 -82
  117. package/dist/tui/config/themes.js.map +0 -1
  118. package/dist/tui/hooks/useData.d.ts +0 -19
  119. package/dist/tui/hooks/useData.d.ts.map +0 -1
  120. package/dist/tui/hooks/useData.js +0 -468
  121. package/dist/tui/hooks/useData.js.map +0 -1
  122. package/dist/tui/index.d.ts +0 -4
  123. package/dist/tui/index.d.ts.map +0 -1
  124. package/dist/tui/index.js +0 -36
  125. package/dist/tui/index.js.map +0 -1
  126. package/dist/tui/types/index.d.ts +0 -137
  127. package/dist/tui/types/index.d.ts.map +0 -1
  128. package/dist/tui/types/index.js +0 -26
  129. package/dist/tui/types/index.js.map +0 -1
  130. package/dist/tui/utils/cleanup.d.ts +0 -22
  131. package/dist/tui/utils/cleanup.d.ts.map +0 -1
  132. package/dist/tui/utils/cleanup.js +0 -59
  133. package/dist/tui/utils/cleanup.js.map +0 -1
  134. package/dist/tui/utils/colors.d.ts +0 -19
  135. package/dist/tui/utils/colors.d.ts.map +0 -1
  136. package/dist/tui/utils/colors.js +0 -71
  137. package/dist/tui/utils/colors.js.map +0 -1
  138. package/dist/tui/utils/format.d.ts +0 -7
  139. package/dist/tui/utils/format.d.ts.map +0 -1
  140. package/dist/tui/utils/format.js +0 -45
  141. package/dist/tui/utils/format.js.map +0 -1
  142. package/dist/tui/utils/responsive.d.ts +0 -5
  143. package/dist/tui/utils/responsive.d.ts.map +0 -1
  144. package/dist/tui/utils/responsive.js +0 -5
  145. package/dist/tui/utils/responsive.js.map +0 -1
  146. package/dist/wrapped.d.ts +0 -43
  147. package/dist/wrapped.d.ts.map +0 -1
  148. package/dist/wrapped.js +0 -719
  149. package/dist/wrapped.js.map +0 -1
  150. package/src/auth.ts +0 -211
  151. package/src/cli.ts +0 -1892
  152. package/src/credentials.ts +0 -176
  153. package/src/cursor.ts +0 -1044
  154. package/src/date-utils.ts +0 -51
  155. package/src/graph-types.ts +0 -175
  156. package/src/native-runner.js +0 -4
  157. package/src/native-runner.ts +0 -91
  158. package/src/native.ts +0 -633
  159. package/src/sessions/types.ts +0 -59
  160. package/src/spinner.ts +0 -283
  161. package/src/submit.ts +0 -360
  162. package/src/table.ts +0 -233
  163. package/src/tui/App.tsx +0 -453
  164. package/src/tui/components/BarChart.tsx +0 -205
  165. package/src/tui/components/DailyView.tsx +0 -132
  166. package/src/tui/components/DateBreakdownPanel.tsx +0 -79
  167. package/src/tui/components/Footer.tsx +0 -380
  168. package/src/tui/components/Header.tsx +0 -68
  169. package/src/tui/components/Legend.tsx +0 -39
  170. package/src/tui/components/LoadingSpinner.tsx +0 -81
  171. package/src/tui/components/ModelRow.tsx +0 -47
  172. package/src/tui/components/ModelView.tsx +0 -147
  173. package/src/tui/components/OverviewView.tsx +0 -121
  174. package/src/tui/components/StatsView.tsx +0 -249
  175. package/src/tui/components/TokenBreakdown.tsx +0 -46
  176. package/src/tui/components/index.ts +0 -15
  177. package/src/tui/config/settings.ts +0 -183
  178. package/src/tui/config/themes.ts +0 -115
  179. package/src/tui/hooks/useData.ts +0 -558
  180. package/src/tui/index.tsx +0 -44
  181. package/src/tui/opentui.d.ts +0 -166
  182. package/src/tui/types/index.ts +0 -173
  183. package/src/tui/utils/cleanup.ts +0 -65
  184. package/src/tui/utils/colors.ts +0 -78
  185. package/src/tui/utils/format.ts +0 -36
  186. package/src/tui/utils/responsive.ts +0 -8
  187. package/src/types.d.ts +0 -28
  188. package/src/wrapped.ts +0 -848
package/src/native.ts DELETED
@@ -1,633 +0,0 @@
1
- /**
2
- * Native module loader for Rust core
3
- *
4
- * Exposes all Rust functions with proper TypeScript types.
5
- * Native module is REQUIRED - no TypeScript fallback.
6
- */
7
-
8
- import type {
9
- TokenContributionData,
10
- SourceType,
11
- } from "./graph-types.js";
12
- import { loadSettings } from "./tui/config/settings.js";
13
-
14
- // =============================================================================
15
- // Types matching Rust exports
16
- // =============================================================================
17
-
18
- interface NativeTokenBreakdown {
19
- input: number;
20
- output: number;
21
- cacheRead: number;
22
- cacheWrite: number;
23
- reasoning: number;
24
- }
25
-
26
- interface NativeDailyTotals {
27
- tokens: number;
28
- cost: number;
29
- messages: number;
30
- }
31
-
32
- interface NativeSourceContribution {
33
- source: string;
34
- modelId: string;
35
- providerId: string;
36
- tokens: NativeTokenBreakdown;
37
- cost: number;
38
- messages: number;
39
- }
40
-
41
- interface NativeDailyContribution {
42
- date: string;
43
- timestampMs?: number;
44
- totals: NativeDailyTotals;
45
- intensity: number;
46
- tokenBreakdown: NativeTokenBreakdown;
47
- sources: NativeSourceContribution[];
48
- }
49
-
50
- interface NativeYearSummary {
51
- year: string;
52
- totalTokens: number;
53
- totalCost: number;
54
- rangeStart: string;
55
- rangeEnd: string;
56
- }
57
-
58
- interface NativeDataSummary {
59
- totalTokens: number;
60
- totalCost: number;
61
- totalDays: number;
62
- activeDays: number;
63
- averagePerDay: number;
64
- maxCostInSingleDay: number;
65
- sources: string[];
66
- models: string[];
67
- }
68
-
69
- interface NativeGraphMeta {
70
- generatedAt: string;
71
- version: string;
72
- dateRangeStart: string;
73
- dateRangeEnd: string;
74
- processingTimeMs: number;
75
- }
76
-
77
- interface NativeGraphResult {
78
- meta: NativeGraphMeta;
79
- summary: NativeDataSummary;
80
- years: NativeYearSummary[];
81
- contributions: NativeDailyContribution[];
82
- }
83
-
84
- interface NativeModelUsage {
85
- source: string;
86
- model: string;
87
- provider: string;
88
- input: number;
89
- output: number;
90
- cacheRead: number;
91
- cacheWrite: number;
92
- reasoning: number;
93
- messageCount: number;
94
- cost: number;
95
- }
96
-
97
- interface NativeModelReport {
98
- entries: NativeModelUsage[];
99
- totalInput: number;
100
- totalOutput: number;
101
- totalCacheRead: number;
102
- totalCacheWrite: number;
103
- totalMessages: number;
104
- totalCost: number;
105
- processingTimeMs: number;
106
- }
107
-
108
- interface NativeMonthlyUsage {
109
- month: string;
110
- models: string[];
111
- input: number;
112
- output: number;
113
- cacheRead: number;
114
- cacheWrite: number;
115
- messageCount: number;
116
- cost: number;
117
- }
118
-
119
- interface NativeMonthlyReport {
120
- entries: NativeMonthlyUsage[];
121
- totalCost: number;
122
- processingTimeMs: number;
123
- }
124
-
125
- // Types for two-phase processing (parallel optimization)
126
- interface NativeParsedMessage {
127
- source: string;
128
- modelId: string;
129
- providerId: string;
130
- timestamp: number;
131
- date: string;
132
- input: number;
133
- output: number;
134
- cacheRead: number;
135
- cacheWrite: number;
136
- reasoning: number;
137
- sessionId: string;
138
- agent?: string;
139
- }
140
-
141
- interface NativeParsedMessages {
142
- messages: NativeParsedMessage[];
143
- opencodeCount: number;
144
- claudeCount: number;
145
- codexCount: number;
146
- geminiCount: number;
147
- ampCount: number;
148
- droidCount: number;
149
- openclawCount: number;
150
- piCount: number;
151
- kimiCount: number;
152
- processingTimeMs: number;
153
- }
154
-
155
- interface NativeLocalParseOptions {
156
- homeDir?: string;
157
- sources?: string[];
158
- since?: string;
159
- until?: string;
160
- year?: string;
161
- sinceTs?: number;
162
- untilTs?: number;
163
- }
164
-
165
- interface NativeFinalizeReportOptions {
166
- homeDir?: string;
167
- localMessages: NativeParsedMessages;
168
- includeCursor: boolean;
169
- since?: string;
170
- until?: string;
171
- year?: string;
172
- sinceTs?: number;
173
- untilTs?: number;
174
- }
175
-
176
- interface NativeCore {
177
- version(): string;
178
- parseLocalSources(options: NativeLocalParseOptions): NativeParsedMessages;
179
- finalizeReport(options: NativeFinalizeReportOptions): NativeModelReport;
180
- finalizeMonthlyReport(options: NativeFinalizeReportOptions): NativeMonthlyReport;
181
- finalizeGraph(options: NativeFinalizeReportOptions): NativeGraphResult;
182
- }
183
-
184
- // =============================================================================
185
- // Module loading
186
- // =============================================================================
187
-
188
- let nativeCore: NativeCore | null = null;
189
-
190
- try {
191
- // Type assertion needed because dynamic import returns module namespace
192
- // nativeCore.version() is called directly, async functions go through subprocess
193
- nativeCore = await import("@tokscale/core").then(
194
- (m) => (m.default || m) as unknown as NativeCore
195
- );
196
- } catch (e) {
197
- void e;
198
- }
199
-
200
- // =============================================================================
201
- // Public API
202
- // =============================================================================
203
-
204
- /**
205
- * Check if native module is available
206
- */
207
- export function isNativeAvailable(): boolean {
208
- return nativeCore !== null;
209
- }
210
-
211
- /**
212
- * Get native module version
213
- */
214
- export function getNativeVersion(): string | null {
215
- return nativeCore?.version() ?? null;
216
- }
217
-
218
- /**
219
- * Convert native result to TypeScript format
220
- */
221
- function fromNativeResult(result: NativeGraphResult): TokenContributionData {
222
- return {
223
- meta: {
224
- generatedAt: result.meta.generatedAt,
225
- version: result.meta.version,
226
- dateRange: {
227
- start: result.meta.dateRangeStart,
228
- end: result.meta.dateRangeEnd,
229
- },
230
- },
231
- summary: {
232
- totalTokens: result.summary.totalTokens,
233
- totalCost: result.summary.totalCost,
234
- totalDays: result.summary.totalDays,
235
- activeDays: result.summary.activeDays,
236
- averagePerDay: result.summary.averagePerDay,
237
- maxCostInSingleDay: result.summary.maxCostInSingleDay,
238
- sources: result.summary.sources as SourceType[],
239
- models: result.summary.models,
240
- },
241
- years: result.years.map((y) => ({
242
- year: y.year,
243
- totalTokens: y.totalTokens,
244
- totalCost: y.totalCost,
245
- range: {
246
- start: y.rangeStart,
247
- end: y.rangeEnd,
248
- },
249
- })),
250
- contributions: result.contributions.map((c) => ({
251
- date: c.date,
252
- timestampMs: c.timestampMs ?? undefined,
253
- totals: {
254
- tokens: c.totals.tokens,
255
- cost: c.totals.cost,
256
- messages: c.totals.messages,
257
- },
258
- intensity: c.intensity as 0 | 1 | 2 | 3 | 4,
259
- tokenBreakdown: {
260
- input: c.tokenBreakdown.input,
261
- output: c.tokenBreakdown.output,
262
- cacheRead: c.tokenBreakdown.cacheRead,
263
- cacheWrite: c.tokenBreakdown.cacheWrite,
264
- reasoning: c.tokenBreakdown.reasoning,
265
- },
266
- sources: c.sources.map((s) => ({
267
- source: s.source as SourceType,
268
- modelId: s.modelId,
269
- providerId: s.providerId,
270
- tokens: {
271
- input: s.tokens.input,
272
- output: s.tokens.output,
273
- cacheRead: s.tokens.cacheRead,
274
- cacheWrite: s.tokens.cacheWrite,
275
- reasoning: s.tokens.reasoning,
276
- },
277
- cost: s.cost,
278
- messages: s.messages,
279
- })),
280
- })),
281
- };
282
- }
283
-
284
- // =============================================================================
285
- // Reports
286
- // =============================================================================
287
-
288
- export interface ModelUsage {
289
- source: string;
290
- model: string;
291
- provider: string;
292
- input: number;
293
- output: number;
294
- cacheRead: number;
295
- cacheWrite: number;
296
- reasoning: number;
297
- messageCount: number;
298
- cost: number;
299
- }
300
-
301
- export interface ModelReport {
302
- entries: ModelUsage[];
303
- totalInput: number;
304
- totalOutput: number;
305
- totalCacheRead: number;
306
- totalCacheWrite: number;
307
- totalMessages: number;
308
- totalCost: number;
309
- processingTimeMs: number;
310
- }
311
-
312
- export interface MonthlyUsage {
313
- month: string;
314
- models: string[];
315
- input: number;
316
- output: number;
317
- cacheRead: number;
318
- cacheWrite: number;
319
- messageCount: number;
320
- cost: number;
321
- }
322
-
323
- export interface MonthlyReport {
324
- entries: MonthlyUsage[];
325
- totalCost: number;
326
- processingTimeMs: number;
327
- }
328
-
329
- // =============================================================================
330
- // Two-Phase Processing (Parallel Optimization)
331
- // =============================================================================
332
-
333
- export interface ParsedMessages {
334
- messages: Array<{
335
- source: string;
336
- modelId: string;
337
- providerId: string;
338
- timestamp: number;
339
- date: string;
340
- input: number;
341
- output: number;
342
- cacheRead: number;
343
- cacheWrite: number;
344
- reasoning: number;
345
- sessionId: string;
346
- agent?: string;
347
- }>;
348
- opencodeCount: number;
349
- claudeCount: number;
350
- codexCount: number;
351
- geminiCount: number;
352
- ampCount: number;
353
- droidCount: number;
354
- openclawCount: number;
355
- piCount: number;
356
- kimiCount: number;
357
- processingTimeMs: number;
358
- }
359
-
360
- export interface LocalParseOptions {
361
- homeDir?: string;
362
- sources?: SourceType[];
363
- since?: string;
364
- until?: string;
365
- year?: string;
366
- sinceTs?: number;
367
- untilTs?: number;
368
- }
369
-
370
- export interface FinalizeOptions {
371
- localMessages: ParsedMessages;
372
- includeCursor: boolean;
373
- since?: string;
374
- until?: string;
375
- year?: string;
376
- sinceTs?: number;
377
- untilTs?: number;
378
- }
379
-
380
-
381
-
382
- // =============================================================================
383
- // Async Subprocess Wrappers (Non-blocking for UI)
384
- // =============================================================================
385
-
386
- import { fileURLToPath } from "node:url";
387
- import { dirname, join } from "node:path";
388
- import { writeFileSync, readFileSync, unlinkSync, mkdirSync, existsSync } from "node:fs";
389
- import { tmpdir } from "node:os";
390
- import { randomUUID } from "node:crypto";
391
-
392
- const __filename = fileURLToPath(import.meta.url);
393
- const __dirname = dirname(__filename);
394
-
395
- const SIGKILL_GRACE_MS = 500;
396
-
397
- function getNativeTimeoutMs(): number {
398
- const settings = loadSettings();
399
- return process.env.TOKSCALE_NATIVE_TIMEOUT_MS
400
- ? parseInt(process.env.TOKSCALE_NATIVE_TIMEOUT_MS, 10)
401
- : (settings.nativeTimeoutMs ?? 300_000);
402
- }
403
-
404
- interface BunSubprocess {
405
- stdout: { text: () => Promise<string> };
406
- stderr: { text: () => Promise<string> };
407
- exited: Promise<number>;
408
- signalCode: string | null;
409
- killed: boolean;
410
- kill: (signal?: string) => void;
411
- }
412
-
413
- interface BunSpawnOptions {
414
- stdout: "pipe" | "ignore";
415
- stderr: "pipe" | "ignore";
416
- }
417
-
418
- interface BunGlobalType {
419
- spawn: (cmd: string[], opts: BunSpawnOptions) => BunSubprocess;
420
- }
421
-
422
- function safeKill(proc: unknown, signal?: string): void {
423
- try {
424
- (proc as { kill: (signal?: string) => void }).kill(signal);
425
- } catch {}
426
- }
427
-
428
- async function runInSubprocess<T>(method: string, args: unknown[]): Promise<T> {
429
- const NATIVE_TIMEOUT_MS = getNativeTimeoutMs();
430
- const runnerPath = join(__dirname, "native-runner.js");
431
- const input = JSON.stringify({ method, args });
432
-
433
- const tmpDir = join(tmpdir(), "tokscale");
434
- mkdirSync(tmpDir, { recursive: true });
435
- const id = randomUUID();
436
- const inputFile = join(tmpDir, `input-${id}.json`);
437
- const outputFile = join(tmpDir, `output-${id}.json`);
438
-
439
- writeFileSync(inputFile, input, "utf-8");
440
-
441
- const BunGlobal = (globalThis as Record<string, unknown>).Bun as BunGlobalType;
442
-
443
- let proc: BunSubprocess;
444
- try {
445
- proc = BunGlobal.spawn([process.execPath, runnerPath, inputFile, outputFile], {
446
- stdout: "ignore",
447
- stderr: "pipe",
448
- });
449
- } catch (e) {
450
- try { unlinkSync(inputFile); } catch {}
451
- throw new Error(`Failed to spawn subprocess: ${(e as Error).message}`);
452
- }
453
-
454
- let timeoutId: ReturnType<typeof setTimeout> | null = null;
455
- let sigkillId: ReturnType<typeof setTimeout> | null = null;
456
- let weInitiatedKill = false;
457
-
458
- const cleanup = async () => {
459
- if (timeoutId) clearTimeout(timeoutId);
460
- if (sigkillId) clearTimeout(sigkillId);
461
- try { unlinkSync(inputFile); } catch {}
462
- try { unlinkSync(outputFile); } catch {}
463
- };
464
-
465
- try {
466
- const timeoutPromise = new Promise<never>((_, reject) => {
467
- timeoutId = setTimeout(() => {
468
- weInitiatedKill = true;
469
- safeKill(proc, "SIGTERM");
470
- sigkillId = setTimeout(() => {
471
- safeKill(proc, "SIGKILL");
472
- reject(new Error(
473
- `Subprocess '${method}' timed out after ${NATIVE_TIMEOUT_MS}ms (hard kill)`
474
- ));
475
- }, SIGKILL_GRACE_MS);
476
- }, NATIVE_TIMEOUT_MS);
477
- });
478
-
479
- const exitCode = await Promise.race([proc.exited, timeoutPromise]);
480
-
481
- if (timeoutId) clearTimeout(timeoutId);
482
-
483
- if (weInitiatedKill || proc.signalCode) {
484
- throw new Error(
485
- `Subprocess '${method}' was killed (signal: ${proc.signalCode || "SIGTERM"})`
486
- );
487
- }
488
-
489
- if (exitCode !== 0) {
490
- const stderr = await proc.stderr.text();
491
- let errorMsg = `Process exited with code ${exitCode}`;
492
- if (stderr) {
493
- try {
494
- const parsed = JSON.parse(stderr);
495
- if (parsed.error) {
496
- errorMsg = parsed.error;
497
- } else {
498
- errorMsg = stderr;
499
- }
500
- } catch {
501
- // Not JSON — include raw stderr so the user sees the actual error
502
- // (e.g. dynamic linker errors on NixOS, missing shared libraries, etc.)
503
- errorMsg = stderr;
504
- }
505
- }
506
- throw new Error(`Subprocess '${method}' failed: ${errorMsg}`);
507
- }
508
-
509
- if (!existsSync(outputFile)) {
510
- throw new Error(`Subprocess '${method}' did not produce output file`);
511
- }
512
-
513
- try {
514
- const output = readFileSync(outputFile, "utf-8");
515
- return JSON.parse(output) as T;
516
- } catch (e) {
517
- throw new Error(
518
- `Failed to parse subprocess output: ${(e as Error).message}`
519
- );
520
- }
521
- } finally {
522
- await cleanup();
523
- }
524
- }
525
-
526
- export async function parseLocalSourcesAsync(options: LocalParseOptions): Promise<ParsedMessages> {
527
- if (!isNativeAvailable()) {
528
- throw new Error("Native module required. Run: bun run build:core");
529
- }
530
-
531
- const nativeOptions: NativeLocalParseOptions = {
532
- homeDir: options.homeDir,
533
- sources: options.sources,
534
- since: options.since,
535
- until: options.until,
536
- year: options.year,
537
- sinceTs: options.sinceTs,
538
- untilTs: options.untilTs,
539
- };
540
-
541
- return runInSubprocess<ParsedMessages>("parseLocalSources", [nativeOptions]);
542
- }
543
-
544
- export async function finalizeReportAsync(options: FinalizeOptions): Promise<ModelReport> {
545
- if (!isNativeAvailable()) {
546
- throw new Error("Native module required. Run: bun run build:core");
547
- }
548
-
549
- const nativeOptions: NativeFinalizeReportOptions = {
550
- homeDir: undefined,
551
- localMessages: options.localMessages,
552
- includeCursor: options.includeCursor,
553
- since: options.since,
554
- until: options.until,
555
- year: options.year,
556
- sinceTs: options.sinceTs,
557
- untilTs: options.untilTs,
558
- };
559
-
560
- return runInSubprocess<ModelReport>("finalizeReport", [nativeOptions]);
561
- }
562
-
563
- export async function finalizeMonthlyReportAsync(options: FinalizeOptions): Promise<MonthlyReport> {
564
- if (!isNativeAvailable()) {
565
- throw new Error("Native module required. Run: bun run build:core");
566
- }
567
-
568
- const nativeOptions: NativeFinalizeReportOptions = {
569
- homeDir: undefined,
570
- localMessages: options.localMessages,
571
- includeCursor: options.includeCursor,
572
- since: options.since,
573
- until: options.until,
574
- year: options.year,
575
- sinceTs: options.sinceTs,
576
- untilTs: options.untilTs,
577
- };
578
-
579
- return runInSubprocess<MonthlyReport>("finalizeMonthlyReport", [nativeOptions]);
580
- }
581
-
582
- export async function finalizeGraphAsync(options: FinalizeOptions): Promise<TokenContributionData> {
583
- if (!isNativeAvailable()) {
584
- throw new Error("Native module required. Run: bun run build:core");
585
- }
586
-
587
- const nativeOptions: NativeFinalizeReportOptions = {
588
- homeDir: undefined,
589
- localMessages: options.localMessages,
590
- includeCursor: options.includeCursor,
591
- since: options.since,
592
- until: options.until,
593
- year: options.year,
594
- sinceTs: options.sinceTs,
595
- untilTs: options.untilTs,
596
- };
597
-
598
- const result = await runInSubprocess<NativeGraphResult>("finalizeGraph", [nativeOptions]);
599
- return fromNativeResult(result);
600
- }
601
-
602
- export interface ReportAndGraph {
603
- report: ModelReport;
604
- graph: TokenContributionData;
605
- }
606
-
607
- interface NativeReportAndGraph {
608
- report: NativeModelReport;
609
- graph: NativeGraphResult;
610
- }
611
-
612
- export async function finalizeReportAndGraphAsync(options: FinalizeOptions): Promise<ReportAndGraph> {
613
- if (!isNativeAvailable()) {
614
- throw new Error("Native module required. Run: bun run build:core");
615
- }
616
-
617
- const nativeOptions: NativeFinalizeReportOptions = {
618
- homeDir: undefined,
619
- localMessages: options.localMessages,
620
- includeCursor: options.includeCursor,
621
- since: options.since,
622
- until: options.until,
623
- year: options.year,
624
- sinceTs: options.sinceTs,
625
- untilTs: options.untilTs,
626
- };
627
-
628
- const result = await runInSubprocess<NativeReportAndGraph>("finalizeReportAndGraph", [nativeOptions]);
629
- return {
630
- report: result.report,
631
- graph: fromNativeResult(result.graph),
632
- };
633
- }
@@ -1,59 +0,0 @@
1
- /**
2
- * Unified message types for session parsers (matches Rust UnifiedMessage)
3
- */
4
-
5
- export interface TokenBreakdown {
6
- input: number;
7
- output: number;
8
- cacheRead: number;
9
- cacheWrite: number;
10
- reasoning: number;
11
- }
12
-
13
- export interface UnifiedMessage {
14
- source: string;
15
- modelId: string;
16
- providerId: string;
17
- sessionId: string;
18
- timestamp: number;
19
- date: string;
20
- tokens: TokenBreakdown;
21
- cost: number;
22
- agent?: string;
23
- }
24
-
25
- export type SourceType = "opencode" | "claude" | "codex" | "gemini" | "cursor" | "amp" | "droid" | "openclaw" | "pi" | "kimi";
26
-
27
- /**
28
- * Convert Unix milliseconds timestamp to YYYY-MM-DD date string
29
- */
30
- export function timestampToDate(timestampMs: number): string {
31
- const date = new Date(timestampMs);
32
- const year = date.getUTCFullYear();
33
- const month = String(date.getUTCMonth() + 1).padStart(2, "0");
34
- const day = String(date.getUTCDate()).padStart(2, "0");
35
- return `${year}-${month}-${day}`;
36
- }
37
-
38
- export function createUnifiedMessage(
39
- source: string,
40
- modelId: string,
41
- providerId: string,
42
- sessionId: string,
43
- timestamp: number,
44
- tokens: TokenBreakdown,
45
- cost: number = 0,
46
- agent?: string
47
- ): UnifiedMessage {
48
- return {
49
- source,
50
- modelId,
51
- providerId,
52
- sessionId,
53
- timestamp,
54
- date: timestampToDate(timestamp),
55
- tokens,
56
- cost,
57
- agent,
58
- };
59
- }