@tokscale/cli 1.4.2 → 2.0.0

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 -1523
  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 -105
  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 -22
  47. package/dist/submit.d.ts.map +0 -1
  48. package/dist/submit.js +0 -292
  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 -350
  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 -467
  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 -25
  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 -68
  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 -716
  149. package/dist/wrapped.js.map +0 -1
  150. package/src/auth.ts +0 -211
  151. package/src/cli.ts +0 -1865
  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 -631
  159. package/src/sessions/types.ts +0 -59
  160. package/src/spinner.ts +0 -283
  161. package/src/submit.ts +0 -358
  162. package/src/table.ts +0 -233
  163. package/src/tui/App.tsx +0 -443
  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 -368
  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 -557
  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 -172
  183. package/src/tui/utils/cleanup.ts +0 -65
  184. package/src/tui/utils/colors.ts +0 -76
  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 -845
package/src/native.ts DELETED
@@ -1,631 +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
- processingTimeMs: number;
152
- }
153
-
154
- interface NativeLocalParseOptions {
155
- homeDir?: string;
156
- sources?: string[];
157
- since?: string;
158
- until?: string;
159
- year?: string;
160
- sinceTs?: number;
161
- untilTs?: number;
162
- }
163
-
164
- interface NativeFinalizeReportOptions {
165
- homeDir?: string;
166
- localMessages: NativeParsedMessages;
167
- includeCursor: boolean;
168
- since?: string;
169
- until?: string;
170
- year?: string;
171
- sinceTs?: number;
172
- untilTs?: number;
173
- }
174
-
175
- interface NativeCore {
176
- version(): string;
177
- parseLocalSources(options: NativeLocalParseOptions): NativeParsedMessages;
178
- finalizeReport(options: NativeFinalizeReportOptions): NativeModelReport;
179
- finalizeMonthlyReport(options: NativeFinalizeReportOptions): NativeMonthlyReport;
180
- finalizeGraph(options: NativeFinalizeReportOptions): NativeGraphResult;
181
- }
182
-
183
- // =============================================================================
184
- // Module loading
185
- // =============================================================================
186
-
187
- let nativeCore: NativeCore | null = null;
188
-
189
- try {
190
- // Type assertion needed because dynamic import returns module namespace
191
- // nativeCore.version() is called directly, async functions go through subprocess
192
- nativeCore = await import("@tokscale/core").then(
193
- (m) => (m.default || m) as unknown as NativeCore
194
- );
195
- } catch (e) {
196
- void e;
197
- }
198
-
199
- // =============================================================================
200
- // Public API
201
- // =============================================================================
202
-
203
- /**
204
- * Check if native module is available
205
- */
206
- export function isNativeAvailable(): boolean {
207
- return nativeCore !== null;
208
- }
209
-
210
- /**
211
- * Get native module version
212
- */
213
- export function getNativeVersion(): string | null {
214
- return nativeCore?.version() ?? null;
215
- }
216
-
217
- /**
218
- * Convert native result to TypeScript format
219
- */
220
- function fromNativeResult(result: NativeGraphResult): TokenContributionData {
221
- return {
222
- meta: {
223
- generatedAt: result.meta.generatedAt,
224
- version: result.meta.version,
225
- dateRange: {
226
- start: result.meta.dateRangeStart,
227
- end: result.meta.dateRangeEnd,
228
- },
229
- },
230
- summary: {
231
- totalTokens: result.summary.totalTokens,
232
- totalCost: result.summary.totalCost,
233
- totalDays: result.summary.totalDays,
234
- activeDays: result.summary.activeDays,
235
- averagePerDay: result.summary.averagePerDay,
236
- maxCostInSingleDay: result.summary.maxCostInSingleDay,
237
- sources: result.summary.sources as SourceType[],
238
- models: result.summary.models,
239
- },
240
- years: result.years.map((y) => ({
241
- year: y.year,
242
- totalTokens: y.totalTokens,
243
- totalCost: y.totalCost,
244
- range: {
245
- start: y.rangeStart,
246
- end: y.rangeEnd,
247
- },
248
- })),
249
- contributions: result.contributions.map((c) => ({
250
- date: c.date,
251
- timestampMs: c.timestampMs ?? undefined,
252
- totals: {
253
- tokens: c.totals.tokens,
254
- cost: c.totals.cost,
255
- messages: c.totals.messages,
256
- },
257
- intensity: c.intensity as 0 | 1 | 2 | 3 | 4,
258
- tokenBreakdown: {
259
- input: c.tokenBreakdown.input,
260
- output: c.tokenBreakdown.output,
261
- cacheRead: c.tokenBreakdown.cacheRead,
262
- cacheWrite: c.tokenBreakdown.cacheWrite,
263
- reasoning: c.tokenBreakdown.reasoning,
264
- },
265
- sources: c.sources.map((s) => ({
266
- source: s.source as SourceType,
267
- modelId: s.modelId,
268
- providerId: s.providerId,
269
- tokens: {
270
- input: s.tokens.input,
271
- output: s.tokens.output,
272
- cacheRead: s.tokens.cacheRead,
273
- cacheWrite: s.tokens.cacheWrite,
274
- reasoning: s.tokens.reasoning,
275
- },
276
- cost: s.cost,
277
- messages: s.messages,
278
- })),
279
- })),
280
- };
281
- }
282
-
283
- // =============================================================================
284
- // Reports
285
- // =============================================================================
286
-
287
- export interface ModelUsage {
288
- source: string;
289
- model: string;
290
- provider: string;
291
- input: number;
292
- output: number;
293
- cacheRead: number;
294
- cacheWrite: number;
295
- reasoning: number;
296
- messageCount: number;
297
- cost: number;
298
- }
299
-
300
- export interface ModelReport {
301
- entries: ModelUsage[];
302
- totalInput: number;
303
- totalOutput: number;
304
- totalCacheRead: number;
305
- totalCacheWrite: number;
306
- totalMessages: number;
307
- totalCost: number;
308
- processingTimeMs: number;
309
- }
310
-
311
- export interface MonthlyUsage {
312
- month: string;
313
- models: string[];
314
- input: number;
315
- output: number;
316
- cacheRead: number;
317
- cacheWrite: number;
318
- messageCount: number;
319
- cost: number;
320
- }
321
-
322
- export interface MonthlyReport {
323
- entries: MonthlyUsage[];
324
- totalCost: number;
325
- processingTimeMs: number;
326
- }
327
-
328
- // =============================================================================
329
- // Two-Phase Processing (Parallel Optimization)
330
- // =============================================================================
331
-
332
- export interface ParsedMessages {
333
- messages: Array<{
334
- source: string;
335
- modelId: string;
336
- providerId: string;
337
- timestamp: number;
338
- date: string;
339
- input: number;
340
- output: number;
341
- cacheRead: number;
342
- cacheWrite: number;
343
- reasoning: number;
344
- sessionId: string;
345
- agent?: string;
346
- }>;
347
- opencodeCount: number;
348
- claudeCount: number;
349
- codexCount: number;
350
- geminiCount: number;
351
- ampCount: number;
352
- droidCount: number;
353
- openclawCount: number;
354
- piCount: number;
355
- processingTimeMs: number;
356
- }
357
-
358
- export interface LocalParseOptions {
359
- homeDir?: string;
360
- sources?: SourceType[];
361
- since?: string;
362
- until?: string;
363
- year?: string;
364
- sinceTs?: number;
365
- untilTs?: number;
366
- }
367
-
368
- export interface FinalizeOptions {
369
- localMessages: ParsedMessages;
370
- includeCursor: boolean;
371
- since?: string;
372
- until?: string;
373
- year?: string;
374
- sinceTs?: number;
375
- untilTs?: number;
376
- }
377
-
378
-
379
-
380
- // =============================================================================
381
- // Async Subprocess Wrappers (Non-blocking for UI)
382
- // =============================================================================
383
-
384
- import { fileURLToPath } from "node:url";
385
- import { dirname, join } from "node:path";
386
- import { writeFileSync, readFileSync, unlinkSync, mkdirSync, existsSync } from "node:fs";
387
- import { tmpdir } from "node:os";
388
- import { randomUUID } from "node:crypto";
389
-
390
- const __filename = fileURLToPath(import.meta.url);
391
- const __dirname = dirname(__filename);
392
-
393
- const SIGKILL_GRACE_MS = 500;
394
-
395
- function getNativeTimeoutMs(): number {
396
- const settings = loadSettings();
397
- return process.env.TOKSCALE_NATIVE_TIMEOUT_MS
398
- ? parseInt(process.env.TOKSCALE_NATIVE_TIMEOUT_MS, 10)
399
- : (settings.nativeTimeoutMs ?? 300_000);
400
- }
401
-
402
- interface BunSubprocess {
403
- stdout: { text: () => Promise<string> };
404
- stderr: { text: () => Promise<string> };
405
- exited: Promise<number>;
406
- signalCode: string | null;
407
- killed: boolean;
408
- kill: (signal?: string) => void;
409
- }
410
-
411
- interface BunSpawnOptions {
412
- stdout: "pipe" | "ignore";
413
- stderr: "pipe" | "ignore";
414
- }
415
-
416
- interface BunGlobalType {
417
- spawn: (cmd: string[], opts: BunSpawnOptions) => BunSubprocess;
418
- }
419
-
420
- function safeKill(proc: unknown, signal?: string): void {
421
- try {
422
- (proc as { kill: (signal?: string) => void }).kill(signal);
423
- } catch {}
424
- }
425
-
426
- async function runInSubprocess<T>(method: string, args: unknown[]): Promise<T> {
427
- const NATIVE_TIMEOUT_MS = getNativeTimeoutMs();
428
- const runnerPath = join(__dirname, "native-runner.js");
429
- const input = JSON.stringify({ method, args });
430
-
431
- const tmpDir = join(tmpdir(), "tokscale");
432
- mkdirSync(tmpDir, { recursive: true });
433
- const id = randomUUID();
434
- const inputFile = join(tmpDir, `input-${id}.json`);
435
- const outputFile = join(tmpDir, `output-${id}.json`);
436
-
437
- writeFileSync(inputFile, input, "utf-8");
438
-
439
- const BunGlobal = (globalThis as Record<string, unknown>).Bun as BunGlobalType;
440
-
441
- let proc: BunSubprocess;
442
- try {
443
- proc = BunGlobal.spawn([process.execPath, runnerPath, inputFile, outputFile], {
444
- stdout: "ignore",
445
- stderr: "pipe",
446
- });
447
- } catch (e) {
448
- try { unlinkSync(inputFile); } catch {}
449
- throw new Error(`Failed to spawn subprocess: ${(e as Error).message}`);
450
- }
451
-
452
- let timeoutId: ReturnType<typeof setTimeout> | null = null;
453
- let sigkillId: ReturnType<typeof setTimeout> | null = null;
454
- let weInitiatedKill = false;
455
-
456
- const cleanup = async () => {
457
- if (timeoutId) clearTimeout(timeoutId);
458
- if (sigkillId) clearTimeout(sigkillId);
459
- try { unlinkSync(inputFile); } catch {}
460
- try { unlinkSync(outputFile); } catch {}
461
- };
462
-
463
- try {
464
- const timeoutPromise = new Promise<never>((_, reject) => {
465
- timeoutId = setTimeout(() => {
466
- weInitiatedKill = true;
467
- safeKill(proc, "SIGTERM");
468
- sigkillId = setTimeout(() => {
469
- safeKill(proc, "SIGKILL");
470
- reject(new Error(
471
- `Subprocess '${method}' timed out after ${NATIVE_TIMEOUT_MS}ms (hard kill)`
472
- ));
473
- }, SIGKILL_GRACE_MS);
474
- }, NATIVE_TIMEOUT_MS);
475
- });
476
-
477
- const exitCode = await Promise.race([proc.exited, timeoutPromise]);
478
-
479
- if (timeoutId) clearTimeout(timeoutId);
480
-
481
- if (weInitiatedKill || proc.signalCode) {
482
- throw new Error(
483
- `Subprocess '${method}' was killed (signal: ${proc.signalCode || "SIGTERM"})`
484
- );
485
- }
486
-
487
- if (exitCode !== 0) {
488
- const stderr = await proc.stderr.text();
489
- let errorMsg = `Process exited with code ${exitCode}`;
490
- if (stderr) {
491
- try {
492
- const parsed = JSON.parse(stderr);
493
- if (parsed.error) {
494
- errorMsg = parsed.error;
495
- } else {
496
- errorMsg = stderr;
497
- }
498
- } catch {
499
- // Not JSON — include raw stderr so the user sees the actual error
500
- // (e.g. dynamic linker errors on NixOS, missing shared libraries, etc.)
501
- errorMsg = stderr;
502
- }
503
- }
504
- throw new Error(`Subprocess '${method}' failed: ${errorMsg}`);
505
- }
506
-
507
- if (!existsSync(outputFile)) {
508
- throw new Error(`Subprocess '${method}' did not produce output file`);
509
- }
510
-
511
- try {
512
- const output = readFileSync(outputFile, "utf-8");
513
- return JSON.parse(output) as T;
514
- } catch (e) {
515
- throw new Error(
516
- `Failed to parse subprocess output: ${(e as Error).message}`
517
- );
518
- }
519
- } finally {
520
- await cleanup();
521
- }
522
- }
523
-
524
- export async function parseLocalSourcesAsync(options: LocalParseOptions): Promise<ParsedMessages> {
525
- if (!isNativeAvailable()) {
526
- throw new Error("Native module required. Run: bun run build:core");
527
- }
528
-
529
- const nativeOptions: NativeLocalParseOptions = {
530
- homeDir: options.homeDir,
531
- sources: options.sources,
532
- since: options.since,
533
- until: options.until,
534
- year: options.year,
535
- sinceTs: options.sinceTs,
536
- untilTs: options.untilTs,
537
- };
538
-
539
- return runInSubprocess<ParsedMessages>("parseLocalSources", [nativeOptions]);
540
- }
541
-
542
- export async function finalizeReportAsync(options: FinalizeOptions): Promise<ModelReport> {
543
- if (!isNativeAvailable()) {
544
- throw new Error("Native module required. Run: bun run build:core");
545
- }
546
-
547
- const nativeOptions: NativeFinalizeReportOptions = {
548
- homeDir: undefined,
549
- localMessages: options.localMessages,
550
- includeCursor: options.includeCursor,
551
- since: options.since,
552
- until: options.until,
553
- year: options.year,
554
- sinceTs: options.sinceTs,
555
- untilTs: options.untilTs,
556
- };
557
-
558
- return runInSubprocess<ModelReport>("finalizeReport", [nativeOptions]);
559
- }
560
-
561
- export async function finalizeMonthlyReportAsync(options: FinalizeOptions): Promise<MonthlyReport> {
562
- if (!isNativeAvailable()) {
563
- throw new Error("Native module required. Run: bun run build:core");
564
- }
565
-
566
- const nativeOptions: NativeFinalizeReportOptions = {
567
- homeDir: undefined,
568
- localMessages: options.localMessages,
569
- includeCursor: options.includeCursor,
570
- since: options.since,
571
- until: options.until,
572
- year: options.year,
573
- sinceTs: options.sinceTs,
574
- untilTs: options.untilTs,
575
- };
576
-
577
- return runInSubprocess<MonthlyReport>("finalizeMonthlyReport", [nativeOptions]);
578
- }
579
-
580
- export async function finalizeGraphAsync(options: FinalizeOptions): Promise<TokenContributionData> {
581
- if (!isNativeAvailable()) {
582
- throw new Error("Native module required. Run: bun run build:core");
583
- }
584
-
585
- const nativeOptions: NativeFinalizeReportOptions = {
586
- homeDir: undefined,
587
- localMessages: options.localMessages,
588
- includeCursor: options.includeCursor,
589
- since: options.since,
590
- until: options.until,
591
- year: options.year,
592
- sinceTs: options.sinceTs,
593
- untilTs: options.untilTs,
594
- };
595
-
596
- const result = await runInSubprocess<NativeGraphResult>("finalizeGraph", [nativeOptions]);
597
- return fromNativeResult(result);
598
- }
599
-
600
- export interface ReportAndGraph {
601
- report: ModelReport;
602
- graph: TokenContributionData;
603
- }
604
-
605
- interface NativeReportAndGraph {
606
- report: NativeModelReport;
607
- graph: NativeGraphResult;
608
- }
609
-
610
- export async function finalizeReportAndGraphAsync(options: FinalizeOptions): Promise<ReportAndGraph> {
611
- if (!isNativeAvailable()) {
612
- throw new Error("Native module required. Run: bun run build:core");
613
- }
614
-
615
- const nativeOptions: NativeFinalizeReportOptions = {
616
- homeDir: undefined,
617
- localMessages: options.localMessages,
618
- includeCursor: options.includeCursor,
619
- since: options.since,
620
- until: options.until,
621
- year: options.year,
622
- sinceTs: options.sinceTs,
623
- untilTs: options.untilTs,
624
- };
625
-
626
- const result = await runInSubprocess<NativeReportAndGraph>("finalizeReportAndGraph", [nativeOptions]);
627
- return {
628
- report: result.report,
629
- graph: fromNativeResult(result.graph),
630
- };
631
- }
@@ -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";
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
- }