awarts 0.2.5 → 0.2.7

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 (2) hide show
  1. package/dist/index.js +103 -11
  2. package/package.json +9 -11
package/dist/index.js CHANGED
@@ -6181,11 +6181,20 @@ var CONFIG_DIRS = [
6181
6181
  var CODEX_PRICING = {
6182
6182
  "gpt-5.4": { input: 2.5, output: 15 },
6183
6183
  "gpt-5.4-pro": { input: 30, output: 180 },
6184
- "gpt-5.2": { input: 1.75, output: 14 },
6184
+ "gpt-5.3": { input: 1.75, output: 14 },
6185
+ "gpt-5.3-codex": { input: 1.75, output: 14 },
6186
+ "gpt-5.2": { input: 0.875, output: 7 },
6187
+ "gpt-5.2-codex": { input: 1.75, output: 14 },
6188
+ "gpt-5.2-pro": { input: 10.5, output: 84 },
6185
6189
  "gpt-5.1": { input: 1.25, output: 10 },
6190
+ "gpt-5.1-codex": { input: 1.25, output: 10 },
6191
+ "gpt-5.1-codex-mini": { input: 0.25, output: 2 },
6192
+ "gpt-5.1-codex-max": { input: 1.25, output: 10 },
6186
6193
  "gpt-5": { input: 1.25, output: 10 },
6194
+ "gpt-5-codex": { input: 1.25, output: 10 },
6187
6195
  "gpt-5-mini": { input: 0.25, output: 2 },
6188
6196
  "gpt-5-nano": { input: 0.05, output: 0.4 },
6197
+ "gpt-5-pro": { input: 15, output: 120 },
6189
6198
  "gpt-4.1": { input: 2, output: 8 },
6190
6199
  "gpt-4.1-mini": { input: 0.4, output: 1.6 },
6191
6200
  "gpt-4.1-nano": { input: 0.1, output: 0.4 },
@@ -6193,13 +6202,14 @@ var CODEX_PRICING = {
6193
6202
  "gpt-4o-mini": { input: 0.15, output: 0.6 },
6194
6203
  o3: { input: 2, output: 8 },
6195
6204
  "o3-pro": { input: 20, output: 80 },
6205
+ "o3-mini": { input: 0.55, output: 2.2 },
6196
6206
  "o4-mini": { input: 1.1, output: 4.4 },
6197
6207
  o1: { input: 15, output: 60 },
6208
+ "o1-mini": { input: 0.55, output: 2.2 },
6198
6209
  "o1-pro": { input: 150, output: 600 },
6199
- "codex-mini": { input: 1.5, output: 6 },
6200
- "openai-codex": { input: 2, output: 8 }
6210
+ "codex-mini": { input: 0.75, output: 3 }
6201
6211
  };
6202
- var DEFAULT_PRICING2 = { input: 2, output: 8 };
6212
+ var DEFAULT_PRICING2 = { input: 1.1, output: 4.4 };
6203
6213
  async function fetchOpenAICosts(apiKey) {
6204
6214
  const entries = [];
6205
6215
  const now = Math.floor(Date.now() / 1000);
@@ -6328,12 +6338,22 @@ async function findSqliteDb() {
6328
6338
  }
6329
6339
  return null;
6330
6340
  }
6341
+ async function readConfigModel() {
6342
+ const configPath = path7.join(HOME, ".codex", "config.toml");
6343
+ try {
6344
+ const content = await fs11.readFile(configPath, "utf-8");
6345
+ const match = content.match(/^\s*model\s*=\s*"([^"]+)"/m);
6346
+ return match ? match[1] : null;
6347
+ } catch {
6348
+ return null;
6349
+ }
6350
+ }
6331
6351
  async function readSqliteThreads() {
6332
6352
  const dbPath = await findSqliteDb();
6333
6353
  if (!dbPath)
6334
6354
  return [];
6335
6355
  try {
6336
- const query = `SELECT date(created_at/1000000000, 'unixepoch') as day, tokens_used, model_provider FROM threads WHERE tokens_used > 0 ORDER BY created_at;`;
6356
+ const query = `SELECT date(created_at, 'unixepoch') as day, tokens_used, model_provider FROM threads WHERE tokens_used > 0 ORDER BY created_at;`;
6337
6357
  const result = execFileSync2("sqlite3", [dbPath, query], {
6338
6358
  timeout: 5000,
6339
6359
  encoding: "utf-8",
@@ -6341,11 +6361,12 @@ async function readSqliteThreads() {
6341
6361
  }).trim();
6342
6362
  if (!result)
6343
6363
  return [];
6364
+ const configModel = await readConfigModel();
6344
6365
  const dayMap = new Map;
6345
6366
  for (const line of result.split(`
6346
6367
  `)) {
6347
6368
  const [day, tokensStr, model] = line.split("|");
6348
- if (!day)
6369
+ if (!day || day === "")
6349
6370
  continue;
6350
6371
  const tokens2 = Number(tokensStr) || 0;
6351
6372
  if (!dayMap.has(day))
@@ -6359,8 +6380,8 @@ async function readSqliteThreads() {
6359
6380
  for (const [date, { tokens: tokens2, models }] of dayMap) {
6360
6381
  const inputTokens = Math.round(tokens2 * 0.4);
6361
6382
  const outputTokens = Math.round(tokens2 * 0.6);
6362
- const modelName = [...models][0] ?? "openai-codex";
6363
- const pricing = CODEX_PRICING[modelName] || DEFAULT_PRICING2;
6383
+ const resolvedModel = configModel ?? [...models][0] ?? null;
6384
+ const pricing = resolvedModel && CODEX_PRICING[resolvedModel] || DEFAULT_PRICING2;
6364
6385
  const cost = (inputTokens * pricing.input + outputTokens * pricing.output) / 1e6;
6365
6386
  entries.push({
6366
6387
  date,
@@ -6368,7 +6389,7 @@ async function readSqliteThreads() {
6368
6389
  cost_usd: cost,
6369
6390
  input_tokens: inputTokens,
6370
6391
  output_tokens: outputTokens,
6371
- models: [...models].length > 0 ? [...models] : ["openai-codex"],
6392
+ models: resolvedModel ? [resolvedModel] : ["codex"],
6372
6393
  cost_source: "estimated"
6373
6394
  });
6374
6395
  }
@@ -6439,6 +6460,7 @@ var GEMINI_PRICING = {
6439
6460
  "gemini-3.1-pro": { input: 2, output: 12 },
6440
6461
  "gemini-3.1-flash-lite": { input: 0.25, output: 1.5 },
6441
6462
  "gemini-3-flash": { input: 0.5, output: 3 },
6463
+ "gemini-3-flash-preview": { input: 0.5, output: 3 },
6442
6464
  "gemini-2.0-flash": { input: 0.1, output: 0.4 },
6443
6465
  "gemini-2.0-flash-lite": { input: 0.075, output: 0.3 },
6444
6466
  "gemini-1.5-pro": { input: 1.25, output: 5 },
@@ -6522,6 +6544,73 @@ async function readLocalFiles2() {
6522
6544
  }
6523
6545
  return entries;
6524
6546
  }
6547
+ async function readSessionFiles() {
6548
+ const geminiDir = path8.join(HOME2, ".gemini", "tmp");
6549
+ if (!await dirExists3(geminiDir))
6550
+ return [];
6551
+ const entries = [];
6552
+ try {
6553
+ const userDirs = await fs12.readdir(geminiDir);
6554
+ for (const userDir of userDirs) {
6555
+ const chatsDir = path8.join(geminiDir, userDir, "chats");
6556
+ if (!await dirExists3(chatsDir))
6557
+ continue;
6558
+ let files;
6559
+ try {
6560
+ files = await fs12.readdir(chatsDir);
6561
+ } catch {
6562
+ continue;
6563
+ }
6564
+ const sessionFiles = files.filter((f) => f.startsWith("session-") && f.endsWith(".json"));
6565
+ const dayMap = new Map;
6566
+ for (const file of sessionFiles) {
6567
+ try {
6568
+ const raw = await fs12.readFile(path8.join(chatsDir, file), "utf-8");
6569
+ const session = JSON.parse(raw);
6570
+ let date = null;
6571
+ if (session.startTime) {
6572
+ date = session.startTime.split("T")[0];
6573
+ } else {
6574
+ const match = file.match(/session-(\d{4}-\d{2}-\d{2})/);
6575
+ if (match)
6576
+ date = match[1];
6577
+ }
6578
+ if (!date)
6579
+ continue;
6580
+ if (!dayMap.has(date))
6581
+ dayMap.set(date, { input: 0, output: 0, cached: 0, models: new Set });
6582
+ const day = dayMap.get(date);
6583
+ for (const msg of session.messages ?? []) {
6584
+ if (msg.type !== "gemini" || !msg.tokens)
6585
+ continue;
6586
+ day.input += msg.tokens.input ?? 0;
6587
+ day.output += msg.tokens.output ?? 0;
6588
+ day.cached += msg.tokens.cached ?? 0;
6589
+ if (msg.model)
6590
+ day.models.add(msg.model);
6591
+ }
6592
+ } catch {}
6593
+ }
6594
+ for (const [date, { input, output, cached, models }] of dayMap) {
6595
+ if (input === 0 && output === 0)
6596
+ continue;
6597
+ const modelName = [...models][0];
6598
+ const cost = calculateCost(input, output, modelName);
6599
+ entries.push({
6600
+ date,
6601
+ provider: "gemini",
6602
+ cost_usd: cost,
6603
+ input_tokens: input,
6604
+ output_tokens: output,
6605
+ cache_read_tokens: cached,
6606
+ models: [...models].length > 0 ? [...models] : ["gemini"],
6607
+ cost_source: "estimated"
6608
+ });
6609
+ }
6610
+ }
6611
+ } catch {}
6612
+ return entries;
6613
+ }
6525
6614
  var geminiAdapter = {
6526
6615
  name: "gemini",
6527
6616
  displayName: "Gemini",
@@ -6538,7 +6627,10 @@ var geminiAdapter = {
6538
6627
  return false;
6539
6628
  },
6540
6629
  async read() {
6541
- return readLocalFiles2();
6630
+ const localEntries = await readLocalFiles2();
6631
+ if (localEntries.length > 0)
6632
+ return localEntries;
6633
+ return readSessionFiles();
6542
6634
  }
6543
6635
  };
6544
6636
 
@@ -7258,7 +7350,7 @@ async function checkForUpdates() {
7258
7350
 
7259
7351
  // src/index.ts
7260
7352
  var program2 = new Command;
7261
- program2.name("awarts").description("Track your AI coding spend across Claude, Codex, Gemini & Antigravity").version("0.2.5").hook("preAction", () => checkForUpdates());
7353
+ program2.name("awarts").description("Track your AI coding spend across Claude, Codex, Gemini & Antigravity").version("0.2.6").hook("preAction", () => checkForUpdates());
7262
7354
  program2.command("login").description("Authenticate with your AWARTS account via device auth").option("--force", "Re-authenticate even if already logged in").action(async (opts) => {
7263
7355
  try {
7264
7356
  if (opts.force) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "awarts",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Track your AI coding across Claude, Codex, Gemini & Antigravity",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -36,25 +36,23 @@
36
36
  "README.md",
37
37
  "LICENSE"
38
38
  ],
39
+ "sideEffects": false,
39
40
  "scripts": {
40
41
  "dev": "bun --watch src/index.ts",
41
42
  "build": "bun build src/index.ts --outdir dist --target node",
42
- "prepublishOnly": "bun run build",
43
43
  "test": "vitest run",
44
44
  "test:watch": "vitest"
45
45
  },
46
- "dependencies": {
46
+ "devDependencies": {
47
+ "@types/node": "^22.16.0",
47
48
  "chalk": "^5.4.0",
48
- "ora": "^8.2.0",
49
- "open": "^10.1.0",
50
49
  "commander": "^13.1.0",
51
50
  "jose": "^5.10.0",
52
- "nanoid": "^5.1.0"
53
- },
54
- "devDependencies": {
55
- "@types/node": "^22.16.0",
56
- "vitest": "^3.2.0",
57
- "typescript": "^5.8.0"
51
+ "nanoid": "^5.1.0",
52
+ "open": "^10.1.0",
53
+ "ora": "^8.2.0",
54
+ "typescript": "^5.8.0",
55
+ "vitest": "^3.2.0"
58
56
  },
59
57
  "engines": {
60
58
  "node": ">=18.0.0"