@tokscale/core 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.
package/index.d.ts ADDED
@@ -0,0 +1,286 @@
1
+ /* auto-generated by NAPI-RS */
2
+ /* eslint-disable */
3
+ /** Daily contribution data */
4
+ export interface DailyContribution {
5
+ date: string
6
+ totals: DailyTotals
7
+ intensity: number
8
+ tokenBreakdown: TokenBreakdown
9
+ sources: Array<SourceContribution>
10
+ }
11
+
12
+ /** Daily contribution totals */
13
+ export interface DailyTotals {
14
+ tokens: number
15
+ cost: number
16
+ messages: number
17
+ }
18
+
19
+ /** Data summary statistics */
20
+ export interface DataSummary {
21
+ totalTokens: number
22
+ totalCost: number
23
+ totalDays: number
24
+ activeDays: number
25
+ averagePerDay: number
26
+ maxCostInSingleDay: number
27
+ sources: Array<string>
28
+ models: Array<string>
29
+ }
30
+
31
+ /** Finalize graph with pricing */
32
+ export declare function finalizeGraph(options: FinalizeGraphOptions): GraphResult
33
+
34
+ /** Options for finalizing graph */
35
+ export interface FinalizeGraphOptions {
36
+ homeDir?: string
37
+ localMessages: ParsedMessages
38
+ pricing: Array<PricingEntry>
39
+ includeCursor: boolean
40
+ since?: string
41
+ until?: string
42
+ year?: string
43
+ }
44
+
45
+ /** Options for finalizing monthly report */
46
+ export interface FinalizeMonthlyOptions {
47
+ homeDir?: string
48
+ localMessages: ParsedMessages
49
+ pricing: Array<PricingEntry>
50
+ includeCursor: boolean
51
+ since?: string
52
+ until?: string
53
+ year?: string
54
+ }
55
+
56
+ /** Finalize monthly report with pricing */
57
+ export declare function finalizeMonthlyReport(options: FinalizeMonthlyOptions): MonthlyReport
58
+
59
+ /** Finalize model report: apply pricing to local messages, add Cursor, aggregate */
60
+ export declare function finalizeReport(options: FinalizeReportOptions): ModelReport
61
+
62
+ /** Options for finalizing report with pricing */
63
+ export interface FinalizeReportOptions {
64
+ homeDir?: string
65
+ localMessages: ParsedMessages
66
+ pricing: Array<PricingEntry>
67
+ includeCursor: boolean
68
+ since?: string
69
+ until?: string
70
+ year?: string
71
+ }
72
+
73
+ /**
74
+ * Generate graph data from all session sources
75
+ *
76
+ * This is the main entry point that orchestrates:
77
+ * 1. Parallel file scanning
78
+ * 2. Parallel session parsing
79
+ * 3. Date filtering
80
+ * 4. Parallel aggregation
81
+ */
82
+ export declare function generateGraph(options: GraphOptions): GraphResult
83
+
84
+ /** Generate graph data with pricing calculation */
85
+ export declare function generateGraphWithPricing(options: ReportOptions): GraphResult
86
+
87
+ /** Get model usage report with pricing calculation */
88
+ export declare function getModelReport(options: ReportOptions): ModelReport
89
+
90
+ /** Get monthly usage report with pricing calculation */
91
+ export declare function getMonthlyReport(options: ReportOptions): MonthlyReport
92
+
93
+ /** Metadata about the graph generation */
94
+ export interface GraphMeta {
95
+ generatedAt: string
96
+ version: string
97
+ dateRangeStart: string
98
+ dateRangeEnd: string
99
+ processingTimeMs: number
100
+ }
101
+
102
+ /** Configuration options for graph generation */
103
+ export interface GraphOptions {
104
+ /** Home directory path (defaults to user's home) */
105
+ homeDir?: string
106
+ /** Sources to include: "opencode", "claude", "codex", "gemini" */
107
+ sources?: Array<string>
108
+ /** Start date filter (YYYY-MM-DD) */
109
+ since?: string
110
+ /** End date filter (YYYY-MM-DD) */
111
+ until?: string
112
+ /** Filter to specific year */
113
+ year?: string
114
+ /** Number of parallel threads (defaults to CPU count) */
115
+ threads?: number
116
+ }
117
+
118
+ /** Complete graph result */
119
+ export interface GraphResult {
120
+ meta: GraphMeta
121
+ summary: DataSummary
122
+ years: Array<YearSummary>
123
+ contributions: Array<DailyContribution>
124
+ }
125
+
126
+ /** Simple health check to verify the native module is working */
127
+ export declare function healthCheck(): string
128
+
129
+ /** Options for parsing local sources only (no Cursor) */
130
+ export interface LocalParseOptions {
131
+ homeDir?: string
132
+ sources?: Array<string>
133
+ since?: string
134
+ until?: string
135
+ year?: string
136
+ }
137
+
138
+ /** Pricing data for a single model (passed from TypeScript) */
139
+ export interface ModelPricing {
140
+ inputCostPerToken: number
141
+ outputCostPerToken: number
142
+ cacheReadInputTokenCost?: number
143
+ cacheCreationInputTokenCost?: number
144
+ }
145
+
146
+ /** Model report result */
147
+ export interface ModelReport {
148
+ entries: Array<ModelUsage>
149
+ totalInput: number
150
+ totalOutput: number
151
+ totalCacheRead: number
152
+ totalCacheWrite: number
153
+ totalMessages: number
154
+ totalCost: number
155
+ processingTimeMs: number
156
+ }
157
+
158
+ /** Model usage summary for reports */
159
+ export interface ModelUsage {
160
+ source: string
161
+ model: string
162
+ provider: string
163
+ input: number
164
+ output: number
165
+ cacheRead: number
166
+ cacheWrite: number
167
+ reasoning: number
168
+ messageCount: number
169
+ cost: number
170
+ }
171
+
172
+ /** Monthly report result */
173
+ export interface MonthlyReport {
174
+ entries: Array<MonthlyUsage>
175
+ totalCost: number
176
+ processingTimeMs: number
177
+ }
178
+
179
+ /** Monthly usage summary */
180
+ export interface MonthlyUsage {
181
+ month: string
182
+ models: Array<string>
183
+ input: number
184
+ output: number
185
+ cacheRead: number
186
+ cacheWrite: number
187
+ messageCount: number
188
+ cost: number
189
+ }
190
+
191
+ /** Parsed message without cost (pricing applied in finalize step) */
192
+ export interface ParsedMessage {
193
+ source: string
194
+ modelId: string
195
+ providerId: string
196
+ sessionId: string
197
+ timestamp: number
198
+ date: string
199
+ input: number
200
+ output: number
201
+ cacheRead: number
202
+ cacheWrite: number
203
+ reasoning: number
204
+ }
205
+
206
+ /** Result of parsing local sources (excludes Cursor - it's network-synced) */
207
+ export interface ParsedMessages {
208
+ messages: Array<ParsedMessage>
209
+ opencodeCount: number
210
+ claudeCount: number
211
+ codexCount: number
212
+ geminiCount: number
213
+ processingTimeMs: number
214
+ }
215
+
216
+ /**
217
+ * Parse local sources only (OpenCode, Claude, Codex, Gemini - NO Cursor)
218
+ * This can run in parallel with network operations (Cursor sync, pricing fetch)
219
+ */
220
+ export declare function parseLocalSources(options: LocalParseOptions): ParsedMessages
221
+
222
+ /** Entry in the pricing map */
223
+ export interface PricingEntry {
224
+ modelId: string
225
+ pricing: ModelPricing
226
+ }
227
+
228
+ /** Options for reports with pricing */
229
+ export interface ReportOptions {
230
+ /** Home directory path (defaults to user's home) */
231
+ homeDir?: string
232
+ /** Sources to include: "opencode", "claude", "codex", "gemini" */
233
+ sources?: Array<string>
234
+ /** Pricing data for cost calculation */
235
+ pricing: Array<PricingEntry>
236
+ /** Start date filter (YYYY-MM-DD) */
237
+ since?: string
238
+ /** End date filter (YYYY-MM-DD) */
239
+ until?: string
240
+ /** Filter to specific year */
241
+ year?: string
242
+ }
243
+
244
+ /** Scan for session files (for debugging/testing) */
245
+ export declare function scanSessions(homeDir?: string | undefined | null, sources?: Array<string> | undefined | null): ScanStats
246
+
247
+ /** Scan session files and return file counts per source */
248
+ export interface ScanStats {
249
+ opencodeFiles: number
250
+ claudeFiles: number
251
+ codexFiles: number
252
+ geminiFiles: number
253
+ cursorFiles: number
254
+ totalFiles: number
255
+ }
256
+
257
+ /** Source contribution for a specific day */
258
+ export interface SourceContribution {
259
+ source: string
260
+ modelId: string
261
+ providerId: string
262
+ tokens: TokenBreakdown
263
+ cost: number
264
+ messages: number
265
+ }
266
+
267
+ /** Token breakdown by type */
268
+ export interface TokenBreakdown {
269
+ input: number
270
+ output: number
271
+ cacheRead: number
272
+ cacheWrite: number
273
+ reasoning: number
274
+ }
275
+
276
+ /** Version of the native module */
277
+ export declare function version(): string
278
+
279
+ /** Year summary */
280
+ export interface YearSummary {
281
+ year: string
282
+ totalTokens: number
283
+ totalCost: number
284
+ rangeStart: string
285
+ rangeEnd: string
286
+ }
package/index.js ADDED
@@ -0,0 +1,336 @@
1
+ /* eslint-disable */
2
+ /* auto-generated by NAPI-RS */
3
+
4
+ const { existsSync, readFileSync } = require('fs')
5
+ const { join } = require('path')
6
+
7
+ const { platform, arch } = process
8
+
9
+ let nativeBinding = null
10
+ let localFileExisted = false
11
+ let loadError = null
12
+
13
+ function isMusl() {
14
+ // For Node 10
15
+ if (!process.report || typeof process.report.getReport !== 'function') {
16
+ try {
17
+ const lddPath = require('child_process').execSync('which ldd').toString().trim()
18
+ return readFileSync(lddPath, 'utf8').includes('musl')
19
+ } catch (e) {
20
+ return true
21
+ }
22
+ } else {
23
+ const { glibcVersionRuntime } = process.report.getReport().header
24
+ return !glibcVersionRuntime
25
+ }
26
+ }
27
+
28
+ switch (platform) {
29
+ case 'android':
30
+ switch (arch) {
31
+ case 'arm64':
32
+ localFileExisted = existsSync(join(__dirname, 'tokscale-core.android-arm64.node'))
33
+ try {
34
+ if (localFileExisted) {
35
+ nativeBinding = require('./tokscale-core.android-arm64.node')
36
+ } else {
37
+ nativeBinding = require('@tokscale/core-android-arm64')
38
+ }
39
+ } catch (e) {
40
+ loadError = e
41
+ }
42
+ break
43
+ case 'arm':
44
+ localFileExisted = existsSync(join(__dirname, 'tokscale-core.android-arm-eabi.node'))
45
+ try {
46
+ if (localFileExisted) {
47
+ nativeBinding = require('./tokscale-core.android-arm-eabi.node')
48
+ } else {
49
+ nativeBinding = require('@tokscale/core-android-arm-eabi')
50
+ }
51
+ } catch (e) {
52
+ loadError = e
53
+ }
54
+ break
55
+ default:
56
+ throw new Error(`Unsupported architecture on Android ${arch}`)
57
+ }
58
+ break
59
+ case 'win32':
60
+ switch (arch) {
61
+ case 'x64':
62
+ localFileExisted = existsSync(
63
+ join(__dirname, 'tokscale-core.win32-x64-msvc.node')
64
+ )
65
+ try {
66
+ if (localFileExisted) {
67
+ nativeBinding = require('./tokscale-core.win32-x64-msvc.node')
68
+ } else {
69
+ nativeBinding = require('@tokscale/core-win32-x64-msvc')
70
+ }
71
+ } catch (e) {
72
+ loadError = e
73
+ }
74
+ break
75
+ case 'ia32':
76
+ localFileExisted = existsSync(
77
+ join(__dirname, 'tokscale-core.win32-ia32-msvc.node')
78
+ )
79
+ try {
80
+ if (localFileExisted) {
81
+ nativeBinding = require('./tokscale-core.win32-ia32-msvc.node')
82
+ } else {
83
+ nativeBinding = require('@tokscale/core-win32-ia32-msvc')
84
+ }
85
+ } catch (e) {
86
+ loadError = e
87
+ }
88
+ break
89
+ case 'arm64':
90
+ localFileExisted = existsSync(
91
+ join(__dirname, 'tokscale-core.win32-arm64-msvc.node')
92
+ )
93
+ try {
94
+ if (localFileExisted) {
95
+ nativeBinding = require('./tokscale-core.win32-arm64-msvc.node')
96
+ } else {
97
+ nativeBinding = require('@tokscale/core-win32-arm64-msvc')
98
+ }
99
+ } catch (e) {
100
+ loadError = e
101
+ }
102
+ break
103
+ default:
104
+ throw new Error(`Unsupported architecture on Windows: ${arch}`)
105
+ }
106
+ break
107
+ case 'darwin':
108
+ localFileExisted = existsSync(join(__dirname, 'tokscale-core.darwin-universal.node'))
109
+ try {
110
+ if (localFileExisted) {
111
+ nativeBinding = require('./tokscale-core.darwin-universal.node')
112
+ } else {
113
+ nativeBinding = require('@tokscale/core-darwin-universal')
114
+ }
115
+ break
116
+ } catch {}
117
+ switch (arch) {
118
+ case 'x64':
119
+ localFileExisted = existsSync(join(__dirname, 'tokscale-core.darwin-x64.node'))
120
+ try {
121
+ if (localFileExisted) {
122
+ nativeBinding = require('./tokscale-core.darwin-x64.node')
123
+ } else {
124
+ nativeBinding = require('@tokscale/core-darwin-x64')
125
+ }
126
+ } catch (e) {
127
+ loadError = e
128
+ }
129
+ break
130
+ case 'arm64':
131
+ localFileExisted = existsSync(
132
+ join(__dirname, 'tokscale-core.darwin-arm64.node')
133
+ )
134
+ try {
135
+ if (localFileExisted) {
136
+ nativeBinding = require('./tokscale-core.darwin-arm64.node')
137
+ } else {
138
+ nativeBinding = require('@tokscale/core-darwin-arm64')
139
+ }
140
+ } catch (e) {
141
+ loadError = e
142
+ }
143
+ break
144
+ default:
145
+ throw new Error(`Unsupported architecture on macOS: ${arch}`)
146
+ }
147
+ break
148
+ case 'freebsd':
149
+ if (arch !== 'x64') {
150
+ throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
151
+ }
152
+ localFileExisted = existsSync(join(__dirname, 'tokscale-core.freebsd-x64.node'))
153
+ try {
154
+ if (localFileExisted) {
155
+ nativeBinding = require('./tokscale-core.freebsd-x64.node')
156
+ } else {
157
+ nativeBinding = require('@tokscale/core-freebsd-x64')
158
+ }
159
+ } catch (e) {
160
+ loadError = e
161
+ }
162
+ break
163
+ case 'linux':
164
+ switch (arch) {
165
+ case 'x64':
166
+ if (isMusl()) {
167
+ localFileExisted = existsSync(
168
+ join(__dirname, 'tokscale-core.linux-x64-musl.node')
169
+ )
170
+ try {
171
+ if (localFileExisted) {
172
+ nativeBinding = require('./tokscale-core.linux-x64-musl.node')
173
+ } else {
174
+ nativeBinding = require('@tokscale/core-linux-x64-musl')
175
+ }
176
+ } catch (e) {
177
+ loadError = e
178
+ }
179
+ } else {
180
+ localFileExisted = existsSync(
181
+ join(__dirname, 'tokscale-core.linux-x64-gnu.node')
182
+ )
183
+ try {
184
+ if (localFileExisted) {
185
+ nativeBinding = require('./tokscale-core.linux-x64-gnu.node')
186
+ } else {
187
+ nativeBinding = require('@tokscale/core-linux-x64-gnu')
188
+ }
189
+ } catch (e) {
190
+ loadError = e
191
+ }
192
+ }
193
+ break
194
+ case 'arm64':
195
+ if (isMusl()) {
196
+ localFileExisted = existsSync(
197
+ join(__dirname, 'tokscale-core.linux-arm64-musl.node')
198
+ )
199
+ try {
200
+ if (localFileExisted) {
201
+ nativeBinding = require('./tokscale-core.linux-arm64-musl.node')
202
+ } else {
203
+ nativeBinding = require('@tokscale/core-linux-arm64-musl')
204
+ }
205
+ } catch (e) {
206
+ loadError = e
207
+ }
208
+ } else {
209
+ localFileExisted = existsSync(
210
+ join(__dirname, 'tokscale-core.linux-arm64-gnu.node')
211
+ )
212
+ try {
213
+ if (localFileExisted) {
214
+ nativeBinding = require('./tokscale-core.linux-arm64-gnu.node')
215
+ } else {
216
+ nativeBinding = require('@tokscale/core-linux-arm64-gnu')
217
+ }
218
+ } catch (e) {
219
+ loadError = e
220
+ }
221
+ }
222
+ break
223
+ case 'arm':
224
+ if (isMusl()) {
225
+ localFileExisted = existsSync(
226
+ join(__dirname, 'tokscale-core.linux-arm-musleabihf.node')
227
+ )
228
+ try {
229
+ if (localFileExisted) {
230
+ nativeBinding = require('./tokscale-core.linux-arm-musleabihf.node')
231
+ } else {
232
+ nativeBinding = require('@tokscale/core-linux-arm-musleabihf')
233
+ }
234
+ } catch (e) {
235
+ loadError = e
236
+ }
237
+ } else {
238
+ localFileExisted = existsSync(
239
+ join(__dirname, 'tokscale-core.linux-arm-gnueabihf.node')
240
+ )
241
+ try {
242
+ if (localFileExisted) {
243
+ nativeBinding = require('./tokscale-core.linux-arm-gnueabihf.node')
244
+ } else {
245
+ nativeBinding = require('@tokscale/core-linux-arm-gnueabihf')
246
+ }
247
+ } catch (e) {
248
+ loadError = e
249
+ }
250
+ }
251
+ break
252
+ case 'riscv64':
253
+ if (isMusl()) {
254
+ localFileExisted = existsSync(
255
+ join(__dirname, 'tokscale-core.linux-riscv64-musl.node')
256
+ )
257
+ try {
258
+ if (localFileExisted) {
259
+ nativeBinding = require('./tokscale-core.linux-riscv64-musl.node')
260
+ } else {
261
+ nativeBinding = require('@tokscale/core-linux-riscv64-musl')
262
+ }
263
+ } catch (e) {
264
+ loadError = e
265
+ }
266
+ } else {
267
+ localFileExisted = existsSync(
268
+ join(__dirname, 'tokscale-core.linux-riscv64-gnu.node')
269
+ )
270
+ try {
271
+ if (localFileExisted) {
272
+ nativeBinding = require('./tokscale-core.linux-riscv64-gnu.node')
273
+ } else {
274
+ nativeBinding = require('@tokscale/core-linux-riscv64-gnu')
275
+ }
276
+ } catch (e) {
277
+ loadError = e
278
+ }
279
+ }
280
+ break
281
+ case 's390x':
282
+ localFileExisted = existsSync(
283
+ join(__dirname, 'tokscale-core.linux-s390x-gnu.node')
284
+ )
285
+ try {
286
+ if (localFileExisted) {
287
+ nativeBinding = require('./tokscale-core.linux-s390x-gnu.node')
288
+ } else {
289
+ nativeBinding = require('@tokscale/core-linux-s390x-gnu')
290
+ }
291
+ } catch (e) {
292
+ loadError = e
293
+ }
294
+ break
295
+ default:
296
+ throw new Error(`Unsupported architecture on Linux: ${arch}`)
297
+ }
298
+ break
299
+ default:
300
+ throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
301
+ }
302
+
303
+ if (!nativeBinding) {
304
+ if (loadError) {
305
+ throw loadError
306
+ }
307
+ throw new Error(`Failed to load native binding`)
308
+ }
309
+
310
+ const {
311
+ version,
312
+ healthCheck,
313
+ generateGraph,
314
+ scanSessions,
315
+ getModelReport,
316
+ getMonthlyReport,
317
+ generateGraphWithPricing,
318
+ // Two-phase processing functions (parallel optimization)
319
+ parseLocalSources,
320
+ finalizeReport,
321
+ finalizeMonthlyReport,
322
+ finalizeGraph,
323
+ } = nativeBinding
324
+
325
+ module.exports.version = version
326
+ module.exports.healthCheck = healthCheck
327
+ module.exports.generateGraph = generateGraph
328
+ module.exports.scanSessions = scanSessions
329
+ module.exports.getModelReport = getModelReport
330
+ module.exports.getMonthlyReport = getMonthlyReport
331
+ module.exports.generateGraphWithPricing = generateGraphWithPricing
332
+ // Two-phase processing functions (parallel optimization)
333
+ module.exports.parseLocalSources = parseLocalSources
334
+ module.exports.finalizeReport = finalizeReport
335
+ module.exports.finalizeMonthlyReport = finalizeMonthlyReport
336
+ module.exports.finalizeGraph = finalizeGraph
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@tokscale/core",
3
+ "version": "1.0.0",
4
+ "description": "Native Rust core for tokscale CLI - high-performance session parsing",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "napi": {
8
+ "binaryName": "tokscale-core",
9
+ "targets": [
10
+ "x86_64-apple-darwin",
11
+ "aarch64-apple-darwin",
12
+ "x86_64-unknown-linux-gnu",
13
+ "aarch64-unknown-linux-gnu",
14
+ "x86_64-unknown-linux-musl",
15
+ "aarch64-unknown-linux-musl",
16
+ "x86_64-pc-windows-msvc",
17
+ "aarch64-pc-windows-msvc"
18
+ ]
19
+ },
20
+ "license": "MIT",
21
+ "publishConfig": {
22
+ "registry": "https://registry.npmjs.org/",
23
+ "access": "public"
24
+ },
25
+ "devDependencies": {
26
+ "@napi-rs/cli": "^3.4.1",
27
+ "ava": "^6.1.0"
28
+ },
29
+ "scripts": {
30
+ "artifacts": "napi artifacts",
31
+ "build": "napi build --release",
32
+ "build:platform": "napi build --platform --release",
33
+ "build:debug": "napi build",
34
+ "prepublishOnly": "napi prepublish -t npm",
35
+ "test": "ava",
36
+ "test:rust": "cargo test --features noop",
37
+ "test:all": "bun run test:rust && bun run test",
38
+ "bench": "cargo bench --features noop",
39
+ "universal": "napi universal",
40
+ "version": "napi version"
41
+ },
42
+ "ava": {
43
+ "timeout": "2m",
44
+ "workerThreads": false,
45
+ "files": [
46
+ "__test__/**/*.spec.mjs"
47
+ ]
48
+ },
49
+ "files": [
50
+ "index.js",
51
+ "index.d.ts",
52
+ "*.node"
53
+ ],
54
+ "engines": {
55
+ "node": ">= 16"
56
+ },
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "https://github.com/junhoyeo/tokscale.git",
60
+ "directory": "packages/core"
61
+ },
62
+ "keywords": [
63
+ "napi-rs",
64
+ "rust",
65
+ "tokscale",
66
+ "performance",
67
+ "native"
68
+ ],
69
+ "optionalDependencies": {
70
+ "@tokscale/core-darwin-x64": "1.0.0",
71
+ "@tokscale/core-darwin-arm64": "1.0.0",
72
+ "@tokscale/core-linux-x64-gnu": "1.0.0",
73
+ "@tokscale/core-linux-arm64-gnu": "1.0.0",
74
+ "@tokscale/core-linux-x64-musl": "1.0.0",
75
+ "@tokscale/core-linux-arm64-musl": "1.0.0",
76
+ "@tokscale/core-win32-x64-msvc": "1.0.0",
77
+ "@tokscale/core-win32-arm64-msvc": "1.0.0"
78
+ }
79
+ }
Binary file
Binary file
Binary file