@tokscale/cli 1.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 (211) hide show
  1. package/dist/auth.d.ts +17 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +162 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/claudecode.d.ts +39 -0
  6. package/dist/claudecode.d.ts.map +1 -0
  7. package/dist/claudecode.js +375 -0
  8. package/dist/claudecode.js.map +1 -0
  9. package/dist/cli.d.ts +9 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +761 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/credentials.d.ts +36 -0
  14. package/dist/credentials.d.ts.map +1 -0
  15. package/dist/credentials.js +109 -0
  16. package/dist/credentials.js.map +1 -0
  17. package/dist/cursor.d.ts +132 -0
  18. package/dist/cursor.d.ts.map +1 -0
  19. package/dist/cursor.js +432 -0
  20. package/dist/cursor.js.map +1 -0
  21. package/dist/gemini.d.ts +36 -0
  22. package/dist/gemini.d.ts.map +1 -0
  23. package/dist/gemini.js +125 -0
  24. package/dist/gemini.js.map +1 -0
  25. package/dist/graph-types.d.ts +152 -0
  26. package/dist/graph-types.d.ts.map +1 -0
  27. package/dist/graph-types.js +6 -0
  28. package/dist/graph-types.js.map +1 -0
  29. package/dist/graph.d.ts +29 -0
  30. package/dist/graph.d.ts.map +1 -0
  31. package/dist/graph.js +383 -0
  32. package/dist/graph.js.map +1 -0
  33. package/dist/native-runner.d.ts +12 -0
  34. package/dist/native-runner.d.ts.map +1 -0
  35. package/dist/native-runner.js +89 -0
  36. package/dist/native-runner.js.map +1 -0
  37. package/dist/native.d.ts +116 -0
  38. package/dist/native.d.ts.map +1 -0
  39. package/dist/native.js +359 -0
  40. package/dist/native.js.map +1 -0
  41. package/dist/opencode.d.ts +40 -0
  42. package/dist/opencode.d.ts.map +1 -0
  43. package/dist/opencode.js +69 -0
  44. package/dist/opencode.js.map +1 -0
  45. package/dist/pricing.d.ts +58 -0
  46. package/dist/pricing.d.ts.map +1 -0
  47. package/dist/pricing.js +232 -0
  48. package/dist/pricing.js.map +1 -0
  49. package/dist/sessions/claudecode.d.ts +8 -0
  50. package/dist/sessions/claudecode.d.ts.map +1 -0
  51. package/dist/sessions/claudecode.js +84 -0
  52. package/dist/sessions/claudecode.js.map +1 -0
  53. package/dist/sessions/codex.d.ts +8 -0
  54. package/dist/sessions/codex.d.ts.map +1 -0
  55. package/dist/sessions/codex.js +158 -0
  56. package/dist/sessions/codex.js.map +1 -0
  57. package/dist/sessions/gemini.d.ts +8 -0
  58. package/dist/sessions/gemini.d.ts.map +1 -0
  59. package/dist/sessions/gemini.js +66 -0
  60. package/dist/sessions/gemini.js.map +1 -0
  61. package/dist/sessions/index.d.ts +32 -0
  62. package/dist/sessions/index.d.ts.map +1 -0
  63. package/dist/sessions/index.js +96 -0
  64. package/dist/sessions/index.js.map +1 -0
  65. package/dist/sessions/opencode.d.ts +8 -0
  66. package/dist/sessions/opencode.d.ts.map +1 -0
  67. package/dist/sessions/opencode.js +54 -0
  68. package/dist/sessions/opencode.js.map +1 -0
  69. package/dist/sessions/reports.d.ts +58 -0
  70. package/dist/sessions/reports.d.ts.map +1 -0
  71. package/dist/sessions/reports.js +337 -0
  72. package/dist/sessions/reports.js.map +1 -0
  73. package/dist/sessions/types.d.ts +30 -0
  74. package/dist/sessions/types.d.ts.map +1 -0
  75. package/dist/sessions/types.js +29 -0
  76. package/dist/sessions/types.js.map +1 -0
  77. package/dist/spinner.d.ts +75 -0
  78. package/dist/spinner.d.ts.map +1 -0
  79. package/dist/spinner.js +203 -0
  80. package/dist/spinner.js.map +1 -0
  81. package/dist/submit.d.ts +21 -0
  82. package/dist/submit.d.ts.map +1 -0
  83. package/dist/submit.js +128 -0
  84. package/dist/submit.js.map +1 -0
  85. package/dist/table.d.ts +42 -0
  86. package/dist/table.d.ts.map +1 -0
  87. package/dist/table.js +181 -0
  88. package/dist/table.js.map +1 -0
  89. package/dist/test-selection.d.ts +2 -0
  90. package/dist/test-selection.d.ts.map +1 -0
  91. package/dist/test-selection.jsx +32 -0
  92. package/dist/test-selection.jsx.map +1 -0
  93. package/dist/tui/App.d.ts +4 -0
  94. package/dist/tui/App.d.ts.map +1 -0
  95. package/dist/tui/App.js +167 -0
  96. package/dist/tui/App.js.map +1 -0
  97. package/dist/tui/App.jsx +281 -0
  98. package/dist/tui/App.jsx.map +1 -0
  99. package/dist/tui/components/BarChart.d.ts +17 -0
  100. package/dist/tui/components/BarChart.d.ts.map +1 -0
  101. package/dist/tui/components/BarChart.js +63 -0
  102. package/dist/tui/components/BarChart.js.map +1 -0
  103. package/dist/tui/components/BarChart.jsx +163 -0
  104. package/dist/tui/components/BarChart.jsx.map +1 -0
  105. package/dist/tui/components/DailyView.d.ts +13 -0
  106. package/dist/tui/components/DailyView.d.ts.map +1 -0
  107. package/dist/tui/components/DailyView.js +32 -0
  108. package/dist/tui/components/DailyView.js.map +1 -0
  109. package/dist/tui/components/DailyView.jsx +84 -0
  110. package/dist/tui/components/DailyView.jsx.map +1 -0
  111. package/dist/tui/components/DateBreakdownPanel.d.ts +7 -0
  112. package/dist/tui/components/DateBreakdownPanel.d.ts.map +1 -0
  113. package/dist/tui/components/DateBreakdownPanel.jsx +61 -0
  114. package/dist/tui/components/DateBreakdownPanel.jsx.map +1 -0
  115. package/dist/tui/components/Footer.d.ts +26 -0
  116. package/dist/tui/components/Footer.d.ts.map +1 -0
  117. package/dist/tui/components/Footer.js +15 -0
  118. package/dist/tui/components/Footer.js.map +1 -0
  119. package/dist/tui/components/Footer.jsx +158 -0
  120. package/dist/tui/components/Footer.jsx.map +1 -0
  121. package/dist/tui/components/Header.d.ts +9 -0
  122. package/dist/tui/components/Header.d.ts.map +1 -0
  123. package/dist/tui/components/Header.js +12 -0
  124. package/dist/tui/components/Header.js.map +1 -0
  125. package/dist/tui/components/Header.jsx +38 -0
  126. package/dist/tui/components/Header.jsx.map +1 -0
  127. package/dist/tui/components/Legend.d.ts +7 -0
  128. package/dist/tui/components/Legend.d.ts.map +1 -0
  129. package/dist/tui/components/Legend.js +9 -0
  130. package/dist/tui/components/Legend.js.map +1 -0
  131. package/dist/tui/components/Legend.jsx +27 -0
  132. package/dist/tui/components/Legend.jsx.map +1 -0
  133. package/dist/tui/components/LoadingSpinner.d.ts +8 -0
  134. package/dist/tui/components/LoadingSpinner.d.ts.map +1 -0
  135. package/dist/tui/components/LoadingSpinner.jsx +62 -0
  136. package/dist/tui/components/LoadingSpinner.jsx.map +1 -0
  137. package/dist/tui/components/ModelListItem.d.ts +11 -0
  138. package/dist/tui/components/ModelListItem.d.ts.map +1 -0
  139. package/dist/tui/components/ModelListItem.js +18 -0
  140. package/dist/tui/components/ModelListItem.js.map +1 -0
  141. package/dist/tui/components/ModelListItem.jsx +17 -0
  142. package/dist/tui/components/ModelListItem.jsx.map +1 -0
  143. package/dist/tui/components/ModelRow.d.ts +13 -0
  144. package/dist/tui/components/ModelRow.d.ts.map +1 -0
  145. package/dist/tui/components/ModelRow.jsx +28 -0
  146. package/dist/tui/components/ModelRow.jsx.map +1 -0
  147. package/dist/tui/components/ModelView.d.ts +13 -0
  148. package/dist/tui/components/ModelView.d.ts.map +1 -0
  149. package/dist/tui/components/ModelView.js +34 -0
  150. package/dist/tui/components/ModelView.js.map +1 -0
  151. package/dist/tui/components/ModelView.jsx +111 -0
  152. package/dist/tui/components/ModelView.jsx.map +1 -0
  153. package/dist/tui/components/OverviewView.d.ts +14 -0
  154. package/dist/tui/components/OverviewView.d.ts.map +1 -0
  155. package/dist/tui/components/OverviewView.js +24 -0
  156. package/dist/tui/components/OverviewView.js.map +1 -0
  157. package/dist/tui/components/OverviewView.jsx +79 -0
  158. package/dist/tui/components/OverviewView.jsx.map +1 -0
  159. package/dist/tui/components/StatsView.d.ts +12 -0
  160. package/dist/tui/components/StatsView.d.ts.map +1 -0
  161. package/dist/tui/components/StatsView.js +43 -0
  162. package/dist/tui/components/StatsView.js.map +1 -0
  163. package/dist/tui/components/StatsView.jsx +180 -0
  164. package/dist/tui/components/StatsView.jsx.map +1 -0
  165. package/dist/tui/components/TokenBreakdown.d.ts +14 -0
  166. package/dist/tui/components/TokenBreakdown.d.ts.map +1 -0
  167. package/dist/tui/components/TokenBreakdown.jsx +27 -0
  168. package/dist/tui/components/TokenBreakdown.jsx.map +1 -0
  169. package/dist/tui/components/index.d.ts +16 -0
  170. package/dist/tui/components/index.d.ts.map +1 -0
  171. package/dist/tui/components/index.js +13 -0
  172. package/dist/tui/components/index.js.map +1 -0
  173. package/dist/tui/config/settings.d.ts +12 -0
  174. package/dist/tui/config/settings.d.ts.map +1 -0
  175. package/dist/tui/config/settings.js +105 -0
  176. package/dist/tui/config/settings.js.map +1 -0
  177. package/dist/tui/config/themes.d.ts +15 -0
  178. package/dist/tui/config/themes.d.ts.map +1 -0
  179. package/dist/tui/config/themes.js +82 -0
  180. package/dist/tui/config/themes.js.map +1 -0
  181. package/dist/tui/hooks/useData.d.ts +17 -0
  182. package/dist/tui/hooks/useData.d.ts.map +1 -0
  183. package/dist/tui/hooks/useData.js +430 -0
  184. package/dist/tui/hooks/useData.js.map +1 -0
  185. package/dist/tui/index.d.ts +4 -0
  186. package/dist/tui/index.d.ts.map +1 -0
  187. package/dist/tui/index.js +8 -0
  188. package/dist/tui/index.js.map +1 -0
  189. package/dist/tui/index.jsx +35 -0
  190. package/dist/tui/index.jsx.map +1 -0
  191. package/dist/tui/types/index.d.ts +133 -0
  192. package/dist/tui/types/index.d.ts.map +1 -0
  193. package/dist/tui/types/index.js +21 -0
  194. package/dist/tui/types/index.js.map +1 -0
  195. package/dist/tui/utils/cleanup.d.ts +22 -0
  196. package/dist/tui/utils/cleanup.d.ts.map +1 -0
  197. package/dist/tui/utils/cleanup.js +59 -0
  198. package/dist/tui/utils/cleanup.js.map +1 -0
  199. package/dist/tui/utils/colors.d.ts +18 -0
  200. package/dist/tui/utils/colors.d.ts.map +1 -0
  201. package/dist/tui/utils/colors.js +55 -0
  202. package/dist/tui/utils/colors.js.map +1 -0
  203. package/dist/tui/utils/format.d.ts +7 -0
  204. package/dist/tui/utils/format.d.ts.map +1 -0
  205. package/dist/tui/utils/format.js +45 -0
  206. package/dist/tui/utils/format.js.map +1 -0
  207. package/dist/tui/utils/responsive.d.ts +5 -0
  208. package/dist/tui/utils/responsive.d.ts.map +1 -0
  209. package/dist/tui/utils/responsive.js +5 -0
  210. package/dist/tui/utils/responsive.js.map +1 -0
  211. package/package.json +64 -0
@@ -0,0 +1,203 @@
1
+ /**
2
+ * OpenCode-style Knight Rider Spinner
3
+ * Accurate port from: https://github.com/sst/opencode/blob/dev/packages/opencode/src/cli/cmd/tui/ui/spinner.ts
4
+ *
5
+ * Features:
6
+ * - Bidirectional sweep (left→right→left)
7
+ * - Hold frames at each end (pause effect)
8
+ * - Color gradient trail using ANSI 256 colors
9
+ * - Same characters as OpenCode: ■ (active) / ⬝ (inactive)
10
+ */
11
+ // =============================================================================
12
+ // ANSI Color Helpers
13
+ // =============================================================================
14
+ function ansi256Fg(code) {
15
+ return `\x1b[38;5;${code}m`;
16
+ }
17
+ const RESET = "\x1b[0m";
18
+ const HIDE_CURSOR = "\x1B[?25l";
19
+ const SHOW_CURSOR = "\x1B[?25h";
20
+ const CLEAR_LINE = "\r\x1B[K";
21
+ const COLOR_GRADIENTS = {
22
+ // Bright → dim (6 steps for trail)
23
+ cyan: [51, 44, 37, 30, 23, 17],
24
+ green: [46, 40, 34, 28, 22, 22],
25
+ magenta: [201, 165, 129, 93, 57, 53],
26
+ yellow: [226, 220, 214, 178, 136, 94],
27
+ red: [196, 160, 124, 88, 52, 52],
28
+ blue: [33, 27, 21, 18, 17, 17],
29
+ white: [255, 250, 245, 240, 236, 232],
30
+ };
31
+ const INACTIVE_COLOR = 240; // Gray for ⬝
32
+ /**
33
+ * Calculate scanner state for a given frame index
34
+ * Matches OpenCode's getScannerState() exactly
35
+ */
36
+ function getScannerState(frameIndex, width, holdStart, holdEnd) {
37
+ const forwardFrames = width;
38
+ const backwardFrames = width - 1;
39
+ const totalCycle = forwardFrames + holdEnd + backwardFrames + holdStart;
40
+ // Normalize frame index to cycle
41
+ const normalizedFrame = frameIndex % totalCycle;
42
+ if (normalizedFrame < forwardFrames) {
43
+ // Phase 1: Moving forward (0 → width-1)
44
+ return {
45
+ activePosition: normalizedFrame,
46
+ isMovingForward: true,
47
+ };
48
+ }
49
+ else if (normalizedFrame < forwardFrames + holdEnd) {
50
+ // Phase 2: Holding at end
51
+ return {
52
+ activePosition: width - 1,
53
+ isMovingForward: true,
54
+ };
55
+ }
56
+ else if (normalizedFrame < forwardFrames + holdEnd + backwardFrames) {
57
+ // Phase 3: Moving backward (width-2 → 0)
58
+ const backwardIndex = normalizedFrame - forwardFrames - holdEnd;
59
+ return {
60
+ activePosition: width - 2 - backwardIndex,
61
+ isMovingForward: false,
62
+ };
63
+ }
64
+ else {
65
+ // Phase 4: Holding at start
66
+ return {
67
+ activePosition: 0,
68
+ isMovingForward: false,
69
+ };
70
+ }
71
+ }
72
+ /**
73
+ * Generate a single frame string with colors
74
+ */
75
+ function generateColoredFrame(frameIndex, width, holdStart, holdEnd, trailLength, gradient) {
76
+ const state = getScannerState(frameIndex, width, holdStart, holdEnd);
77
+ const { activePosition, isMovingForward } = state;
78
+ let result = "";
79
+ for (let i = 0; i < width; i++) {
80
+ // Calculate directional distance (positive = trailing behind)
81
+ const directionalDistance = isMovingForward
82
+ ? activePosition - i // Forward: trail is to the left
83
+ : i - activePosition; // Backward: trail is to the right
84
+ if (directionalDistance >= 0 && directionalDistance < trailLength) {
85
+ // Active position with color gradient
86
+ const colorIdx = Math.min(directionalDistance, gradient.length - 1);
87
+ result += ansi256Fg(gradient[colorIdx]) + "■" + RESET;
88
+ }
89
+ else {
90
+ // Inactive position
91
+ result += ansi256Fg(INACTIVE_COLOR) + "⬝" + RESET;
92
+ }
93
+ }
94
+ return result;
95
+ }
96
+ /**
97
+ * Calculate total frames in one complete cycle
98
+ */
99
+ function getTotalFrames(width, holdStart, holdEnd) {
100
+ return width + holdEnd + (width - 1) + holdStart;
101
+ }
102
+ // =============================================================================
103
+ // Spinner Class
104
+ // =============================================================================
105
+ export class Spinner {
106
+ intervalId = null;
107
+ frameIndex = 0;
108
+ width;
109
+ holdStart;
110
+ holdEnd;
111
+ trailLength;
112
+ gradient;
113
+ interval;
114
+ message = "";
115
+ totalFrames;
116
+ constructor(options = {}) {
117
+ this.width = options.width ?? 8;
118
+ this.holdStart = options.holdStart ?? 30;
119
+ this.holdEnd = options.holdEnd ?? 9;
120
+ this.trailLength = options.trailLength ?? 4;
121
+ this.interval = options.interval ?? 40;
122
+ const colorName = options.color ?? "cyan";
123
+ this.gradient = COLOR_GRADIENTS[colorName] || COLOR_GRADIENTS.cyan;
124
+ this.totalFrames = getTotalFrames(this.width, this.holdStart, this.holdEnd);
125
+ }
126
+ /**
127
+ * Start the spinner with a message
128
+ */
129
+ start(message) {
130
+ this.message = message;
131
+ this.frameIndex = 0;
132
+ // Hide cursor
133
+ process.stdout.write(HIDE_CURSOR);
134
+ this.intervalId = setInterval(() => {
135
+ const frame = generateColoredFrame(this.frameIndex, this.width, this.holdStart, this.holdEnd, this.trailLength, this.gradient);
136
+ process.stdout.write(`${CLEAR_LINE} ${frame} ${this.message}`);
137
+ this.frameIndex = (this.frameIndex + 1) % this.totalFrames;
138
+ }, this.interval);
139
+ }
140
+ /**
141
+ * Update the spinner message while running
142
+ */
143
+ update(message) {
144
+ this.message = message;
145
+ }
146
+ /**
147
+ * Stop the spinner and show a success message
148
+ */
149
+ success(message) {
150
+ this.stop();
151
+ console.log(` \x1b[32m✓\x1b[0m ${message}`);
152
+ }
153
+ /**
154
+ * Stop the spinner and show an error message
155
+ */
156
+ error(message) {
157
+ this.stop();
158
+ console.log(` \x1b[31m✗\x1b[0m ${message}`);
159
+ }
160
+ /**
161
+ * Stop the spinner without a message
162
+ */
163
+ stop() {
164
+ if (this.intervalId) {
165
+ clearInterval(this.intervalId);
166
+ this.intervalId = null;
167
+ }
168
+ process.stdout.write(CLEAR_LINE);
169
+ process.stdout.write(SHOW_CURSOR);
170
+ }
171
+ /**
172
+ * Check if spinner is currently running
173
+ */
174
+ isSpinning() {
175
+ return this.intervalId !== null;
176
+ }
177
+ }
178
+ // =============================================================================
179
+ // Convenience Functions
180
+ // =============================================================================
181
+ /**
182
+ * Create a spinner with default OpenCode settings
183
+ */
184
+ export function createSpinner(options) {
185
+ return new Spinner(options);
186
+ }
187
+ /**
188
+ * Run an async function with a spinner
189
+ */
190
+ export async function withSpinner(message, fn, options) {
191
+ const spinner = new Spinner(options);
192
+ spinner.start(message);
193
+ try {
194
+ const result = await fn();
195
+ spinner.success(options?.successMessage ?? message);
196
+ return result;
197
+ }
198
+ catch (error) {
199
+ spinner.error(options?.errorMessage ?? `Failed: ${message}`);
200
+ throw error;
201
+ }
202
+ }
203
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../src/spinner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Tokscale CLI Submit Command
3
+ * Submits local token usage data to the social platform
4
+ */
5
+ interface SubmitOptions {
6
+ opencode?: boolean;
7
+ claude?: boolean;
8
+ codex?: boolean;
9
+ gemini?: boolean;
10
+ cursor?: boolean;
11
+ since?: string;
12
+ until?: string;
13
+ year?: string;
14
+ dryRun?: boolean;
15
+ }
16
+ /**
17
+ * Submit command - sends usage data to the platform
18
+ */
19
+ export declare function submit(options?: SubmitOptions): Promise<void>;
20
+ export {};
21
+ //# sourceMappingURL=submit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../src/submit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAuBD;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2HvE"}
package/dist/submit.js ADDED
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Tokscale CLI Submit Command
3
+ * Submits local token usage data to the social platform
4
+ */
5
+ import pc from "picocolors";
6
+ import { loadCredentials, getApiBaseUrl } from "./credentials.js";
7
+ import { PricingFetcher } from "./pricing.js";
8
+ import { isNativeAvailable, generateGraphWithPricingAsync, } from "./native.js";
9
+ import { formatCurrency } from "./table.js";
10
+ /**
11
+ * Submit command - sends usage data to the platform
12
+ */
13
+ export async function submit(options = {}) {
14
+ // Step 1: Check if logged in
15
+ const credentials = loadCredentials();
16
+ if (!credentials) {
17
+ console.log(pc.yellow("\n Not logged in."));
18
+ console.log(pc.gray(" Run 'tokscale login' first.\n"));
19
+ process.exit(1);
20
+ }
21
+ // Step 2: Log native module status (TS fallback available)
22
+ if (!isNativeAvailable()) {
23
+ console.log(pc.yellow("\n Note: Using TypeScript fallback (native module not available)"));
24
+ console.log(pc.gray(" Run 'bun run build:core' for faster processing.\n"));
25
+ }
26
+ console.log(pc.cyan("\n Tokscale - Submit Usage Data\n"));
27
+ // Step 3: Generate graph data
28
+ console.log(pc.gray(" Scanning local session data..."));
29
+ const fetcher = new PricingFetcher();
30
+ await fetcher.fetchPricing();
31
+ const pricingEntries = fetcher.toPricingEntries();
32
+ // Determine sources
33
+ const hasFilter = options.opencode || options.claude || options.codex || options.gemini || options.cursor;
34
+ let sources;
35
+ if (hasFilter) {
36
+ sources = [];
37
+ if (options.opencode)
38
+ sources.push("opencode");
39
+ if (options.claude)
40
+ sources.push("claude");
41
+ if (options.codex)
42
+ sources.push("codex");
43
+ if (options.gemini)
44
+ sources.push("gemini");
45
+ if (options.cursor)
46
+ sources.push("cursor");
47
+ }
48
+ let data;
49
+ try {
50
+ data = await generateGraphWithPricingAsync({
51
+ sources,
52
+ pricing: pricingEntries,
53
+ since: options.since,
54
+ until: options.until,
55
+ year: options.year,
56
+ });
57
+ }
58
+ catch (error) {
59
+ console.error(pc.red(`\n Error generating data: ${error.message}\n`));
60
+ process.exit(1);
61
+ }
62
+ // Step 4: Show summary
63
+ console.log(pc.white(" Data to submit:"));
64
+ console.log(pc.gray(` Date range: ${data.meta.dateRange.start} to ${data.meta.dateRange.end}`));
65
+ console.log(pc.gray(` Active days: ${data.summary.activeDays}`));
66
+ console.log(pc.gray(` Total tokens: ${data.summary.totalTokens.toLocaleString()}`));
67
+ console.log(pc.gray(` Total cost: ${formatCurrency(data.summary.totalCost)}`));
68
+ console.log(pc.gray(` Sources: ${data.summary.sources.join(", ")}`));
69
+ console.log(pc.gray(` Models: ${data.summary.models.length} models`));
70
+ console.log();
71
+ if (data.summary.totalTokens === 0) {
72
+ console.log(pc.yellow(" No usage data found to submit.\n"));
73
+ return;
74
+ }
75
+ // Step 5: Dry run check
76
+ if (options.dryRun) {
77
+ console.log(pc.yellow(" Dry run - not submitting data.\n"));
78
+ return;
79
+ }
80
+ // Step 6: Submit to server
81
+ console.log(pc.gray(" Submitting to server..."));
82
+ const baseUrl = getApiBaseUrl();
83
+ try {
84
+ const response = await fetch(`${baseUrl}/api/submit`, {
85
+ method: "POST",
86
+ headers: {
87
+ "Content-Type": "application/json",
88
+ Authorization: `Bearer ${credentials.token}`,
89
+ },
90
+ body: JSON.stringify(data),
91
+ });
92
+ const result = await response.json();
93
+ if (!response.ok) {
94
+ console.error(pc.red(`\n Error: ${result.error || "Submission failed"}`));
95
+ if (result.details) {
96
+ for (const detail of result.details) {
97
+ console.error(pc.gray(` - ${detail}`));
98
+ }
99
+ }
100
+ console.log();
101
+ process.exit(1);
102
+ }
103
+ // Success!
104
+ console.log(pc.green("\n Successfully submitted!"));
105
+ console.log();
106
+ console.log(pc.white(" Summary:"));
107
+ console.log(pc.gray(` Submission ID: ${result.submissionId}`));
108
+ console.log(pc.gray(` Total tokens: ${result.metrics?.totalTokens?.toLocaleString()}`));
109
+ console.log(pc.gray(` Total cost: ${formatCurrency(result.metrics?.totalCost || 0)}`));
110
+ console.log(pc.gray(` Active days: ${result.metrics?.activeDays}`));
111
+ console.log();
112
+ console.log(pc.cyan(` View your profile: ${baseUrl}/u/${credentials.username}`));
113
+ console.log();
114
+ if (result.warnings && result.warnings.length > 0) {
115
+ console.log(pc.yellow(" Warnings:"));
116
+ for (const warning of result.warnings) {
117
+ console.log(pc.gray(` - ${warning}`));
118
+ }
119
+ console.log();
120
+ }
121
+ }
122
+ catch (error) {
123
+ console.error(pc.red(`\n Error: Failed to connect to server.`));
124
+ console.error(pc.gray(` ${error.message}\n`));
125
+ process.exit(1);
126
+ }
127
+ }
128
+ //# sourceMappingURL=submit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submit.js","sourceRoot":"","sources":["../src/submit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Dynamic width table rendering (inspired by ccusage)
3
+ */
4
+ export type TableCellAlign = "left" | "right" | "center";
5
+ export type TableRow = (string | number | {
6
+ content: string;
7
+ hAlign?: TableCellAlign;
8
+ })[];
9
+ export interface TableOptions {
10
+ head: string[];
11
+ colAligns?: TableCellAlign[];
12
+ style?: {
13
+ head?: string[];
14
+ };
15
+ compactHead?: string[];
16
+ compactColAligns?: TableCellAlign[];
17
+ compactThreshold?: number;
18
+ }
19
+ export declare class ResponsiveTable {
20
+ private head;
21
+ private rows;
22
+ private colAligns;
23
+ private style?;
24
+ private compactHead?;
25
+ private compactColAligns?;
26
+ private compactThreshold;
27
+ private compactMode;
28
+ constructor(options: TableOptions);
29
+ push(row: TableRow): void;
30
+ private filterRowToCompact;
31
+ private getCurrentTableConfig;
32
+ private getCompactIndices;
33
+ toString(): string;
34
+ }
35
+ export declare function formatNumber(num: number): string;
36
+ export declare function formatCurrency(amount: number): string;
37
+ export declare function formatModelName(modelName: string): string;
38
+ export declare function formatModelsMultiline(models: string[]): string;
39
+ export declare function createUsageTable(firstColumnName: string): ResponsiveTable;
40
+ export declare function formatUsageRow(firstCol: string, models: string[], input: number, output: number, cacheWrite: number, cacheRead: number, cost: number): TableRow;
41
+ export declare function formatTotalsRow(input: number, output: number, cacheWrite: number, cacheRead: number, cost: number): TableRow;
42
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AACzD,MAAM,MAAM,QAAQ,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC,EAAE,CAAC;AAE1F,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,CAAC,EAAE,cAAc,EAAE,CAAC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,IAAI,CAAW;IACvB,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,KAAK,CAAC,CAAsB;IACpC,OAAO,CAAC,WAAW,CAAC,CAAW;IAC/B,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAC5C,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,YAAY;IASjC,IAAI,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;IAIzB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,iBAAiB;IAUzB,QAAQ,IAAI,MAAM;CA8EnB;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAazD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAG9D;AAED,wBAAgB,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,eAAe,CAkBzE;AAED,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,QAAQ,CAYV;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,QAAQ,CAYV"}
package/dist/table.js ADDED
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Dynamic width table rendering (inspired by ccusage)
3
+ */
4
+ import Table from "cli-table3";
5
+ import pc from "picocolors";
6
+ import stringWidth from "string-width";
7
+ export class ResponsiveTable {
8
+ head;
9
+ rows = [];
10
+ colAligns;
11
+ style;
12
+ compactHead;
13
+ compactColAligns;
14
+ compactThreshold;
15
+ compactMode = false;
16
+ constructor(options) {
17
+ this.head = options.head;
18
+ this.colAligns = options.colAligns ?? Array.from({ length: this.head.length }, () => "left");
19
+ this.style = options.style;
20
+ this.compactHead = options.compactHead;
21
+ this.compactColAligns = options.compactColAligns;
22
+ this.compactThreshold = options.compactThreshold ?? 100;
23
+ }
24
+ push(row) {
25
+ this.rows.push(row);
26
+ }
27
+ filterRowToCompact(row, compactIndices) {
28
+ return compactIndices.map((index) => row[index] ?? "");
29
+ }
30
+ getCurrentTableConfig() {
31
+ if (this.compactMode && this.compactHead && this.compactColAligns) {
32
+ return { head: this.compactHead, colAligns: this.compactColAligns };
33
+ }
34
+ return { head: this.head, colAligns: this.colAligns };
35
+ }
36
+ getCompactIndices() {
37
+ if (!this.compactHead || !this.compactMode) {
38
+ return Array.from({ length: this.head.length }, (_, i) => i);
39
+ }
40
+ return this.compactHead.map((compactHeader) => {
41
+ const index = this.head.indexOf(compactHeader);
42
+ return index < 0 ? 0 : index;
43
+ });
44
+ }
45
+ toString() {
46
+ const terminalWidth = Number.parseInt(process.env.COLUMNS ?? "", 10) || process.stdout.columns || 120;
47
+ this.compactMode = terminalWidth < this.compactThreshold && this.compactHead != null;
48
+ const { head, colAligns } = this.getCurrentTableConfig();
49
+ const compactIndices = this.getCompactIndices();
50
+ const processedRows = this.compactMode
51
+ ? this.rows.map((row) => this.filterRowToCompact(row, compactIndices))
52
+ : this.rows;
53
+ const allRows = [
54
+ head.map(String),
55
+ ...processedRows.map((row) => row.map((cell) => {
56
+ if (typeof cell === "object" && cell != null && "content" in cell) {
57
+ return String(cell.content);
58
+ }
59
+ return String(cell ?? "");
60
+ })),
61
+ ];
62
+ const contentWidths = head.map((_, colIndex) => {
63
+ const maxLength = Math.max(...allRows.map((row) => stringWidth(String(row[colIndex] ?? ""))));
64
+ return maxLength;
65
+ });
66
+ const numColumns = head.length;
67
+ const tableOverhead = 3 * numColumns + 1;
68
+ const availableWidth = terminalWidth - tableOverhead;
69
+ const columnWidths = contentWidths.map((width, index) => {
70
+ const align = colAligns[index];
71
+ if (align === "right") {
72
+ return Math.max(width + 3, 11);
73
+ }
74
+ else if (index === 1) {
75
+ return Math.max(width + 2, 15);
76
+ }
77
+ return Math.max(width + 2, 10);
78
+ });
79
+ const totalRequiredWidth = columnWidths.reduce((sum, width) => sum + width, 0) + tableOverhead;
80
+ let finalWidths = columnWidths;
81
+ if (totalRequiredWidth > terminalWidth) {
82
+ const scaleFactor = availableWidth / columnWidths.reduce((sum, width) => sum + width, 0);
83
+ finalWidths = columnWidths.map((width, index) => {
84
+ const align = colAligns[index];
85
+ let adjustedWidth = Math.floor(width * scaleFactor);
86
+ if (align === "right") {
87
+ adjustedWidth = Math.max(adjustedWidth, 10);
88
+ }
89
+ else if (index === 0) {
90
+ adjustedWidth = Math.max(adjustedWidth, 10);
91
+ }
92
+ else {
93
+ adjustedWidth = Math.max(adjustedWidth, 8);
94
+ }
95
+ return adjustedWidth;
96
+ });
97
+ }
98
+ const table = new Table({
99
+ head,
100
+ style: this.style,
101
+ colAligns,
102
+ colWidths: finalWidths,
103
+ wordWrap: true,
104
+ wrapOnWordBoundary: true,
105
+ });
106
+ for (const row of processedRows) {
107
+ table.push(row);
108
+ }
109
+ return table.toString();
110
+ }
111
+ }
112
+ export function formatNumber(num) {
113
+ return num.toLocaleString("en-US");
114
+ }
115
+ export function formatCurrency(amount) {
116
+ return `$${amount.toFixed(2)}`;
117
+ }
118
+ export function formatModelName(modelName) {
119
+ // claude-sonnet-4-20250514 -> sonnet-4
120
+ // claude-opus-4-5-20251101 -> opus-4-5
121
+ const match = modelName.match(/claude-(\w+)-([\d-]+)-(\d{8})/);
122
+ if (match) {
123
+ return `${match[1]}-${match[2]}`;
124
+ }
125
+ // Handle OpenCode style: claude-opus-4-5-high -> opus-4-5-high
126
+ const openCodeMatch = modelName.match(/claude-(\w+)-(.+)/);
127
+ if (openCodeMatch) {
128
+ return `${openCodeMatch[1]}-${openCodeMatch[2]}`;
129
+ }
130
+ return modelName;
131
+ }
132
+ export function formatModelsMultiline(models) {
133
+ const unique = [...new Set(models.map(formatModelName))];
134
+ return unique.sort().map((m) => `- ${m}`).join("\n");
135
+ }
136
+ export function createUsageTable(firstColumnName) {
137
+ return new ResponsiveTable({
138
+ head: [
139
+ firstColumnName,
140
+ "Models",
141
+ "Input",
142
+ "Output",
143
+ "Cache Write",
144
+ "Cache Read",
145
+ "Total",
146
+ "Cost",
147
+ ],
148
+ style: { head: ["cyan"] },
149
+ colAligns: ["left", "left", "right", "right", "right", "right", "right", "right"],
150
+ compactHead: [firstColumnName, "Models", "Input", "Output", "Cost"],
151
+ compactColAligns: ["left", "left", "right", "right", "right"],
152
+ compactThreshold: 100,
153
+ });
154
+ }
155
+ export function formatUsageRow(firstCol, models, input, output, cacheWrite, cacheRead, cost) {
156
+ const total = input + output + cacheWrite + cacheRead;
157
+ return [
158
+ firstCol,
159
+ formatModelsMultiline(models),
160
+ formatNumber(input),
161
+ formatNumber(output),
162
+ formatNumber(cacheWrite),
163
+ formatNumber(cacheRead),
164
+ formatNumber(total),
165
+ formatCurrency(cost),
166
+ ];
167
+ }
168
+ export function formatTotalsRow(input, output, cacheWrite, cacheRead, cost) {
169
+ const total = input + output + cacheWrite + cacheRead;
170
+ return [
171
+ pc.yellow("Total"),
172
+ "",
173
+ pc.yellow(formatNumber(input)),
174
+ pc.yellow(formatNumber(output)),
175
+ pc.yellow(formatNumber(cacheWrite)),
176
+ pc.yellow(formatNumber(cacheRead)),
177
+ pc.yellow(formatNumber(total)),
178
+ pc.yellow(formatCurrency(cost)),
179
+ ];
180
+ }
181
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.js","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test-selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-selection.d.ts","sourceRoot":"","sources":["../src/test-selection.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import { createSignal, For, createMemo } from "solid-js";
2
+ import { render, useKeyboard } from "@opentui/solid";
3
+ function App() {
4
+ const [selectedIndex, setSelectedIndex] = createSignal(0);
5
+ const items = ["Item 0", "Item 1", "Item 2", "Item 3", "Item 4"];
6
+ useKeyboard((key) => {
7
+ if (key.name === "down") {
8
+ setSelectedIndex(Math.min(selectedIndex() + 1, items.length - 1));
9
+ }
10
+ if (key.name === "up") {
11
+ setSelectedIndex(Math.max(0, selectedIndex() - 1));
12
+ }
13
+ if (key.name === "q") {
14
+ process.exit(0);
15
+ }
16
+ });
17
+ return (<box flexDirection="column">
18
+ <text>Selected: {selectedIndex()}</text>
19
+ <For each={items}>
20
+ {(item, i) => {
21
+ const isActive = createMemo(() => i() === selectedIndex());
22
+ const rowBg = createMemo(() => isActive() ? "blue" : (i() % 2 === 0 ? "gray" : undefined));
23
+ return (<text bg={rowBg()} fg={isActive() ? "white" : undefined}>
24
+ {item} {isActive() ? "<-- SELECTED" : ""}
25
+ </text>);
26
+ }}
27
+ </For>
28
+ <text dim>Press up/down to move, q to quit</text>
29
+ </box>);
30
+ }
31
+ render(() => <App />);
32
+ //# sourceMappingURL=test-selection.jsx.map