opencode-token-tracker 1.2.0 → 1.3.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/README.md +30 -0
- package/dist/bin/opencode-tokens.js +257 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,6 +94,36 @@ Breakdown options (`--by`):
|
|
|
94
94
|
- `daily` - Show day-by-day breakdown
|
|
95
95
|
- `all` - Show all breakdowns
|
|
96
96
|
|
|
97
|
+
### Pricing & Config Commands
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Show built-in pricing table
|
|
101
|
+
opencode-tokens pricing
|
|
102
|
+
|
|
103
|
+
# Show your used models and their pricing status
|
|
104
|
+
opencode-tokens models
|
|
105
|
+
|
|
106
|
+
# Show current config
|
|
107
|
+
opencode-tokens config
|
|
108
|
+
|
|
109
|
+
# Generate example config based on your usage
|
|
110
|
+
opencode-tokens config init
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Example `models` output:
|
|
114
|
+
```
|
|
115
|
+
Model Provider Msgs Pricing
|
|
116
|
+
------------------------ ---------------- -------- ------------
|
|
117
|
+
claude-opus-4.5 github-copilot 379 provider cfg
|
|
118
|
+
deepseek-chat deepseek 6 built-in
|
|
119
|
+
gpt-5.2 openai 18 built-in
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This helps you understand:
|
|
123
|
+
- Which models/providers you're using
|
|
124
|
+
- Whether pricing is from built-in table, your config, or default fallback
|
|
125
|
+
- What to add to your config file
|
|
126
|
+
|
|
97
127
|
## Log Files
|
|
98
128
|
|
|
99
129
|
Token usage is logged to:
|
|
@@ -1,8 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { readFileSync, existsSync } from "fs";
|
|
2
|
+
import { readFileSync, existsSync, writeFileSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import { homedir } from "os";
|
|
5
|
-
const
|
|
5
|
+
const CONFIG_DIR = join(homedir(), ".config", "opencode");
|
|
6
|
+
const CONFIG_FILE = join(CONFIG_DIR, "token-tracker.json");
|
|
7
|
+
const LOG_FILE = join(CONFIG_DIR, "logs", "token-tracker", "tokens.jsonl");
|
|
8
|
+
const BUILTIN_PRICING = {
|
|
9
|
+
// Anthropic Claude
|
|
10
|
+
"claude-opus-4.5": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
11
|
+
"claude-sonnet-4.5": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
12
|
+
"claude-sonnet-4": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
13
|
+
"claude-haiku-4.5": { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
|
|
14
|
+
"claude-haiku-4": { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
|
|
15
|
+
// OpenAI GPT
|
|
16
|
+
"gpt-5.2": { input: 2.5, output: 10 },
|
|
17
|
+
"gpt-5.2-codex": { input: 3, output: 12 },
|
|
18
|
+
"gpt-5.1": { input: 2, output: 8 },
|
|
19
|
+
"gpt-5": { input: 5, output: 15 },
|
|
20
|
+
"gpt-4.1": { input: 2, output: 8 },
|
|
21
|
+
"gpt-4.1-mini": { input: 0.4, output: 1.6 },
|
|
22
|
+
"gpt-4.1-nano": { input: 0.1, output: 0.4 },
|
|
23
|
+
"gpt-4o": { input: 2.5, output: 10 },
|
|
24
|
+
"gpt-4o-mini": { input: 0.15, output: 0.6 },
|
|
25
|
+
"o3": { input: 10, output: 40 },
|
|
26
|
+
"o3-mini": { input: 1.1, output: 4.4 },
|
|
27
|
+
"o1": { input: 15, output: 60 },
|
|
28
|
+
"o1-mini": { input: 1.1, output: 4.4 },
|
|
29
|
+
// DeepSeek
|
|
30
|
+
"deepseek-chat": { input: 0.14, output: 0.28, cacheRead: 0.014 },
|
|
31
|
+
"deepseek-reasoner": { input: 0.55, output: 2.19, cacheRead: 0.055 },
|
|
32
|
+
// Google Gemini
|
|
33
|
+
"gemini-3-pro": { input: 1.25, output: 5 },
|
|
34
|
+
"gemini-3-pro-preview": { input: 1.25, output: 5 },
|
|
35
|
+
"gemini-3-flash": { input: 0.1, output: 0.4 },
|
|
36
|
+
"gemini-2.5-pro": { input: 1.25, output: 5 },
|
|
37
|
+
"gemini-2.5-flash": { input: 0.075, output: 0.3 },
|
|
38
|
+
"gemini-2.0-flash": { input: 0.1, output: 0.4 },
|
|
39
|
+
// Fallback
|
|
40
|
+
"_default": { input: 1, output: 4 },
|
|
41
|
+
};
|
|
6
42
|
// ============================================================================
|
|
7
43
|
// Helpers
|
|
8
44
|
// ============================================================================
|
|
@@ -34,7 +70,7 @@ function getStartOfDay(date) {
|
|
|
34
70
|
function getStartOfWeek(date) {
|
|
35
71
|
const d = new Date(date);
|
|
36
72
|
const day = d.getDay();
|
|
37
|
-
const diff = d.getDate() - day + (day === 0 ? -6 : 1);
|
|
73
|
+
const diff = d.getDate() - day + (day === 0 ? -6 : 1);
|
|
38
74
|
d.setDate(diff);
|
|
39
75
|
d.setHours(0, 0, 0, 0);
|
|
40
76
|
return d.getTime();
|
|
@@ -63,7 +99,7 @@ function loadEntries(since) {
|
|
|
63
99
|
if (since && entry._ts < since)
|
|
64
100
|
continue;
|
|
65
101
|
if (!entry.input && !entry.output)
|
|
66
|
-
continue;
|
|
102
|
+
continue;
|
|
67
103
|
entries.push(entry);
|
|
68
104
|
}
|
|
69
105
|
catch {
|
|
@@ -72,6 +108,15 @@ function loadEntries(since) {
|
|
|
72
108
|
}
|
|
73
109
|
return entries;
|
|
74
110
|
}
|
|
111
|
+
function loadConfig() {
|
|
112
|
+
try {
|
|
113
|
+
if (existsSync(CONFIG_FILE)) {
|
|
114
|
+
return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch { }
|
|
118
|
+
return {};
|
|
119
|
+
}
|
|
75
120
|
// ============================================================================
|
|
76
121
|
// Stats Aggregation
|
|
77
122
|
// ============================================================================
|
|
@@ -129,13 +174,11 @@ function printSummary(title, stats) {
|
|
|
129
174
|
console.log();
|
|
130
175
|
}
|
|
131
176
|
function printTable(title, groups, labelHeader) {
|
|
132
|
-
// Sort by cost descending
|
|
133
177
|
const sorted = Array.from(groups.entries()).sort((a, b) => b[1].cost - a[1].cost);
|
|
134
178
|
if (sorted.length === 0) {
|
|
135
179
|
console.log(`\n No data for ${title}\n`);
|
|
136
180
|
return;
|
|
137
181
|
}
|
|
138
|
-
// Calculate column widths
|
|
139
182
|
const labelWidth = Math.max(labelHeader.length, ...sorted.map(([k]) => k.length));
|
|
140
183
|
const tokensWidth = 10;
|
|
141
184
|
const costWidth = 10;
|
|
@@ -143,10 +186,8 @@ function printTable(title, groups, labelHeader) {
|
|
|
143
186
|
console.log();
|
|
144
187
|
console.log(` ${title}`);
|
|
145
188
|
console.log(` ${"─".repeat(labelWidth + tokensWidth + costWidth + countWidth + 12)}`);
|
|
146
|
-
// Header
|
|
147
189
|
console.log(` ${padRight(labelHeader, labelWidth)} ${padLeft("Tokens", tokensWidth)} ${padLeft("Cost", costWidth)} ${padLeft("Msgs", countWidth)}`);
|
|
148
190
|
console.log(` ${"-".repeat(labelWidth)} ${"-".repeat(tokensWidth)} ${"-".repeat(costWidth)} ${"-".repeat(countWidth)}`);
|
|
149
|
-
// Rows
|
|
150
191
|
for (const [label, stats] of sorted) {
|
|
151
192
|
const totalTokens = stats.input + stats.output;
|
|
152
193
|
console.log(` ${padRight(label, labelWidth)} ${padLeft(formatTokens(totalTokens), tokensWidth)} ${padLeft(formatCost(stats.cost), costWidth)} ${padLeft(stats.count.toString(), countWidth)}`);
|
|
@@ -156,9 +197,8 @@ function printTable(title, groups, labelHeader) {
|
|
|
156
197
|
function printDailyBreakdown(entries) {
|
|
157
198
|
const byDay = groupBy(entries, (e) => {
|
|
158
199
|
const date = new Date(e._ts);
|
|
159
|
-
return date.toISOString().slice(0, 10);
|
|
200
|
+
return date.toISOString().slice(0, 10);
|
|
160
201
|
});
|
|
161
|
-
// Sort by date descending
|
|
162
202
|
const sorted = Array.from(byDay.entries()).sort((a, b) => b[0].localeCompare(a[0]));
|
|
163
203
|
if (sorted.length === 0) {
|
|
164
204
|
console.log("\n No data\n");
|
|
@@ -210,10 +250,8 @@ function cmdStats(period, breakdown) {
|
|
|
210
250
|
console.log(`\n No data for ${title.toLowerCase()}\n`);
|
|
211
251
|
return;
|
|
212
252
|
}
|
|
213
|
-
// Overall summary
|
|
214
253
|
const total = aggregateStats(entries);
|
|
215
254
|
printSummary(title, total);
|
|
216
|
-
// Breakdown
|
|
217
255
|
switch (breakdown) {
|
|
218
256
|
case "model":
|
|
219
257
|
printTable("By Model", groupBy(entries, (e) => e.model ?? "unknown"), "Model");
|
|
@@ -235,32 +273,209 @@ function cmdStats(period, breakdown) {
|
|
|
235
273
|
break;
|
|
236
274
|
}
|
|
237
275
|
}
|
|
276
|
+
function cmdPricing() {
|
|
277
|
+
const config = loadConfig();
|
|
278
|
+
console.log(`
|
|
279
|
+
Built-in Pricing Table (USD per 1M tokens)
|
|
280
|
+
══════════════════════════════════════════════════════════════════
|
|
281
|
+
`);
|
|
282
|
+
// Group by provider
|
|
283
|
+
const groups = {
|
|
284
|
+
"Anthropic Claude": ["claude-opus-4.5", "claude-sonnet-4.5", "claude-sonnet-4", "claude-haiku-4.5", "claude-haiku-4"],
|
|
285
|
+
"OpenAI": ["gpt-5.2", "gpt-5.2-codex", "gpt-5.1", "gpt-5", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "gpt-4o", "gpt-4o-mini", "o3", "o3-mini", "o1", "o1-mini"],
|
|
286
|
+
"DeepSeek": ["deepseek-chat", "deepseek-reasoner"],
|
|
287
|
+
"Google Gemini": ["gemini-3-pro", "gemini-3-pro-preview", "gemini-3-flash", "gemini-2.5-pro", "gemini-2.5-flash", "gemini-2.0-flash"],
|
|
288
|
+
};
|
|
289
|
+
const modelWidth = 20;
|
|
290
|
+
const priceWidth = 10;
|
|
291
|
+
for (const [group, models] of Object.entries(groups)) {
|
|
292
|
+
console.log(` ${group}`);
|
|
293
|
+
console.log(` ${"-".repeat(modelWidth + priceWidth * 4 + 12)}`);
|
|
294
|
+
console.log(` ${padRight("Model", modelWidth)} ${padLeft("Input", priceWidth)} ${padLeft("Output", priceWidth)} ${padLeft("CacheRd", priceWidth)} ${padLeft("CacheWr", priceWidth)}`);
|
|
295
|
+
for (const model of models) {
|
|
296
|
+
const p = BUILTIN_PRICING[model];
|
|
297
|
+
if (!p)
|
|
298
|
+
continue;
|
|
299
|
+
const overridden = config.models?.[model] ? " *" : "";
|
|
300
|
+
console.log(` ${padRight(model + overridden, modelWidth)} ${padLeft("$" + p.input.toString(), priceWidth)} ${padLeft("$" + p.output.toString(), priceWidth)} ${padLeft(p.cacheRead ? "$" + p.cacheRead.toString() : "-", priceWidth)} ${padLeft(p.cacheWrite ? "$" + p.cacheWrite.toString() : "-", priceWidth)}`);
|
|
301
|
+
}
|
|
302
|
+
console.log();
|
|
303
|
+
}
|
|
304
|
+
console.log(` Default (unknown models)`);
|
|
305
|
+
console.log(` ${"-".repeat(modelWidth + priceWidth * 4 + 12)}`);
|
|
306
|
+
const def = BUILTIN_PRICING["_default"];
|
|
307
|
+
console.log(` ${padRight("_default", modelWidth)} ${padLeft("$" + def.input.toString(), priceWidth)} ${padLeft("$" + def.output.toString(), priceWidth)} ${padLeft("-", priceWidth)} ${padLeft("-", priceWidth)}`);
|
|
308
|
+
console.log();
|
|
309
|
+
if (Object.keys(config.models || {}).length > 0) {
|
|
310
|
+
console.log(` * = overridden in config`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function cmdModels() {
|
|
314
|
+
const entries = loadEntries();
|
|
315
|
+
if (entries.length === 0) {
|
|
316
|
+
console.log(`\n No usage data found. Start using OpenCode to collect data.\n`);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
// Get unique model+provider combinations
|
|
320
|
+
const modelProviders = new Map();
|
|
321
|
+
for (const e of entries) {
|
|
322
|
+
const model = e.model ?? "unknown";
|
|
323
|
+
const provider = e.provider ?? "unknown";
|
|
324
|
+
const key = `${model}|${provider}`;
|
|
325
|
+
if (!modelProviders.has(key)) {
|
|
326
|
+
modelProviders.set(key, { provider, count: 0, lastUsed: 0 });
|
|
327
|
+
}
|
|
328
|
+
const info = modelProviders.get(key);
|
|
329
|
+
info.count++;
|
|
330
|
+
info.lastUsed = Math.max(info.lastUsed, e._ts);
|
|
331
|
+
}
|
|
332
|
+
// Sort by last used
|
|
333
|
+
const sorted = Array.from(modelProviders.entries())
|
|
334
|
+
.map(([key, info]) => ({ model: key.split("|")[0], ...info }))
|
|
335
|
+
.sort((a, b) => b.lastUsed - a.lastUsed);
|
|
336
|
+
const config = loadConfig();
|
|
337
|
+
console.log(`
|
|
338
|
+
Your Used Models
|
|
339
|
+
══════════════════════════════════════════════════════════════════
|
|
340
|
+
`);
|
|
341
|
+
const modelWidth = 24;
|
|
342
|
+
const providerWidth = 16;
|
|
343
|
+
const countWidth = 8;
|
|
344
|
+
const statusWidth = 12;
|
|
345
|
+
console.log(` ${padRight("Model", modelWidth)} ${padRight("Provider", providerWidth)} ${padLeft("Msgs", countWidth)} ${padRight("Pricing", statusWidth)}`);
|
|
346
|
+
console.log(` ${"-".repeat(modelWidth)} ${"-".repeat(providerWidth)} ${"-".repeat(countWidth)} ${"-".repeat(statusWidth)}`);
|
|
347
|
+
for (const { model, provider, count } of sorted) {
|
|
348
|
+
let status = "built-in";
|
|
349
|
+
if (config.providers?.[provider]) {
|
|
350
|
+
status = "provider cfg";
|
|
351
|
+
}
|
|
352
|
+
else if (config.models?.[model]) {
|
|
353
|
+
status = "model cfg";
|
|
354
|
+
}
|
|
355
|
+
else if (!BUILTIN_PRICING[model]) {
|
|
356
|
+
// Check partial match
|
|
357
|
+
const hasMatch = Object.keys(BUILTIN_PRICING).some(k => k !== "_default" && model.toLowerCase().includes(k.toLowerCase()));
|
|
358
|
+
status = hasMatch ? "built-in" : "default";
|
|
359
|
+
}
|
|
360
|
+
console.log(` ${padRight(model, modelWidth)} ${padRight(provider, providerWidth)} ${padLeft(count.toString(), countWidth)} ${padRight(status, statusWidth)}`);
|
|
361
|
+
}
|
|
362
|
+
console.log();
|
|
363
|
+
console.log(` Pricing status:`);
|
|
364
|
+
console.log(` built-in = using built-in pricing table`);
|
|
365
|
+
console.log(` provider cfg = overridden by providers config`);
|
|
366
|
+
console.log(` model cfg = overridden by models config`);
|
|
367
|
+
console.log(` default = unknown model, using $1/$4 per 1M tokens`);
|
|
368
|
+
console.log();
|
|
369
|
+
}
|
|
370
|
+
function cmdConfig(action) {
|
|
371
|
+
const config = loadConfig();
|
|
372
|
+
const entries = loadEntries();
|
|
373
|
+
if (action === "init" || action === "generate") {
|
|
374
|
+
// Get unique providers from logs
|
|
375
|
+
const providers = new Set();
|
|
376
|
+
const models = new Set();
|
|
377
|
+
for (const e of entries) {
|
|
378
|
+
if (e.provider)
|
|
379
|
+
providers.add(e.provider);
|
|
380
|
+
if (e.model)
|
|
381
|
+
models.add(e.model);
|
|
382
|
+
}
|
|
383
|
+
// Find providers/models without built-in pricing
|
|
384
|
+
const unknownModels = Array.from(models).filter(m => {
|
|
385
|
+
if (BUILTIN_PRICING[m])
|
|
386
|
+
return false;
|
|
387
|
+
const hasMatch = Object.keys(BUILTIN_PRICING).some(k => k !== "_default" && m.toLowerCase().includes(k.toLowerCase()));
|
|
388
|
+
return !hasMatch;
|
|
389
|
+
});
|
|
390
|
+
const exampleConfig = {
|
|
391
|
+
providers: {},
|
|
392
|
+
models: {},
|
|
393
|
+
toast: {
|
|
394
|
+
enabled: true,
|
|
395
|
+
duration: 3000,
|
|
396
|
+
showOnIdle: true,
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
// Add providers as comments/examples
|
|
400
|
+
for (const provider of providers) {
|
|
401
|
+
// Common free providers
|
|
402
|
+
if (provider.includes("copilot") || provider.includes("cursor") || provider.includes("free")) {
|
|
403
|
+
exampleConfig.providers[provider] = { input: 0, output: 0 };
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// Add unknown models
|
|
407
|
+
for (const model of unknownModels) {
|
|
408
|
+
exampleConfig.models[model] = { input: 1, output: 4 };
|
|
409
|
+
}
|
|
410
|
+
if (action === "generate") {
|
|
411
|
+
const json = JSON.stringify(exampleConfig, null, 2);
|
|
412
|
+
writeFileSync(CONFIG_FILE, json);
|
|
413
|
+
console.log(`\n Config file generated: ${CONFIG_FILE}\n`);
|
|
414
|
+
console.log(json);
|
|
415
|
+
console.log();
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
console.log(`
|
|
419
|
+
Example config based on your usage:
|
|
420
|
+
────────────────────────────────────────────────────────────────
|
|
421
|
+
`);
|
|
422
|
+
console.log(JSON.stringify(exampleConfig, null, 2));
|
|
423
|
+
console.log(`
|
|
424
|
+
To create this config file, run:
|
|
425
|
+
opencode-tokens config generate
|
|
426
|
+
|
|
427
|
+
Or manually create: ${CONFIG_FILE}
|
|
428
|
+
`);
|
|
429
|
+
}
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
// Show current config
|
|
433
|
+
console.log(`
|
|
434
|
+
Current Configuration
|
|
435
|
+
══════════════════════════════════════════════════════════════════
|
|
436
|
+
|
|
437
|
+
Config file: ${CONFIG_FILE}
|
|
438
|
+
Status: ${existsSync(CONFIG_FILE) ? "exists" : "not found (using defaults)"}
|
|
439
|
+
`);
|
|
440
|
+
if (existsSync(CONFIG_FILE)) {
|
|
441
|
+
console.log(` Contents:`);
|
|
442
|
+
console.log(` ${"-".repeat(60)}`);
|
|
443
|
+
console.log(JSON.stringify(config, null, 2).split("\n").map(l => " " + l).join("\n"));
|
|
444
|
+
console.log();
|
|
445
|
+
}
|
|
446
|
+
console.log(` Commands:`);
|
|
447
|
+
console.log(` opencode-tokens config init Show example config based on your usage`);
|
|
448
|
+
console.log(` opencode-tokens config generate Create config file with example`);
|
|
449
|
+
console.log();
|
|
450
|
+
}
|
|
238
451
|
function cmdHelp() {
|
|
239
452
|
console.log(`
|
|
240
453
|
opencode-tokens - Token usage statistics CLI
|
|
241
454
|
|
|
242
455
|
Usage:
|
|
243
|
-
opencode-tokens [
|
|
456
|
+
opencode-tokens [command] [options]
|
|
244
457
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
458
|
+
Commands:
|
|
459
|
+
(default) Show usage statistics
|
|
460
|
+
pricing Show built-in pricing table
|
|
461
|
+
models Show your used models and their pricing status
|
|
462
|
+
config Show/generate configuration
|
|
250
463
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
464
|
+
Statistics Options:
|
|
465
|
+
today Show today's usage
|
|
466
|
+
week Show this week's usage
|
|
467
|
+
month Show this month's usage
|
|
468
|
+
all Show all-time usage (default)
|
|
469
|
+
|
|
470
|
+
--by <type> Group by: model, agent, provider, daily, all
|
|
257
471
|
|
|
258
472
|
Examples:
|
|
259
473
|
opencode-tokens # All-time summary
|
|
260
474
|
opencode-tokens today # Today's summary
|
|
261
|
-
opencode-tokens week --by model # This week,
|
|
262
|
-
opencode-tokens
|
|
263
|
-
opencode-tokens
|
|
475
|
+
opencode-tokens week --by model # This week, by model
|
|
476
|
+
opencode-tokens pricing # Show pricing table
|
|
477
|
+
opencode-tokens models # Show your models
|
|
478
|
+
opencode-tokens config init # Generate example config
|
|
264
479
|
`);
|
|
265
480
|
}
|
|
266
481
|
// ============================================================================
|
|
@@ -268,11 +483,25 @@ function cmdHelp() {
|
|
|
268
483
|
// ============================================================================
|
|
269
484
|
function main() {
|
|
270
485
|
const args = process.argv.slice(2);
|
|
486
|
+
const command = args[0];
|
|
271
487
|
if (args.includes("--help") || args.includes("-h")) {
|
|
272
488
|
cmdHelp();
|
|
273
489
|
return;
|
|
274
490
|
}
|
|
275
|
-
//
|
|
491
|
+
// Handle subcommands
|
|
492
|
+
if (command === "pricing") {
|
|
493
|
+
cmdPricing();
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
if (command === "models") {
|
|
497
|
+
cmdModels();
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (command === "config") {
|
|
501
|
+
cmdConfig(args[1]);
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
// Parse stats arguments
|
|
276
505
|
let period = "all";
|
|
277
506
|
let breakdown;
|
|
278
507
|
for (let i = 0; i < args.length; i++) {
|
package/package.json
CHANGED