codex-token-tracker 0.1.1 → 0.2.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/dist/preload.js CHANGED
@@ -16,6 +16,8 @@ var bridge = {
16
16
  cancelLogin: () => import_electron.ipcRenderer.invoke("auth:cancel"),
17
17
  logout: () => import_electron.ipcRenderer.invoke("auth:logout"),
18
18
  refresh: () => import_electron.ipcRenderer.invoke("refresh"),
19
+ checkUpdate: () => import_electron.ipcRenderer.invoke("update:check"),
20
+ installUpdate: () => import_electron.ipcRenderer.invoke("update:install"),
19
21
  quit: () => import_electron.ipcRenderer.invoke("quit")
20
22
  };
21
23
  import_electron.contextBridge.exposeInMainWorld("codexTracker", bridge);
@@ -12758,6 +12758,70 @@
12758
12758
  // src/renderer/App.tsx
12759
12759
  var import_react2 = __toESM(require_react());
12760
12760
 
12761
+ // ../shared/src/pricing.ts
12762
+ var LONG_CONTEXT_THRESHOLD = 272e3;
12763
+ var long = (threshold, input, cachedInput, output) => ({
12764
+ threshold,
12765
+ input,
12766
+ cachedInput,
12767
+ output
12768
+ });
12769
+ var DEFAULT_PRICING = {
12770
+ // GPT-5.6 family
12771
+ "gpt-5.6-sol": { input: 4, cachedInput: 0.4, output: 20, long: long(LONG_CONTEXT_THRESHOLD, 8, 0.8, 30) },
12772
+ "gpt-5.6-sol-codex": { input: 4, cachedInput: 0.4, output: 20, long: long(LONG_CONTEXT_THRESHOLD, 8, 0.8, 30) },
12773
+ "gpt-5.6-terra": { input: 2, cachedInput: 0.2, output: 12, long: long(LONG_CONTEXT_THRESHOLD, 4, 0.4, 18) },
12774
+ "gpt-5.6-terra-codex": { input: 2, cachedInput: 0.2, output: 12, long: long(LONG_CONTEXT_THRESHOLD, 4, 0.4, 18) },
12775
+ "gpt-5.6-luna": { input: 0.2, cachedInput: 0.02, output: 1.2, long: long(LONG_CONTEXT_THRESHOLD, 0.4, 0.04, 1.8) },
12776
+ "gpt-5.6-cyber": { input: 12.5, cachedInput: 1.25, output: 75 },
12777
+ // GPT-5.5 family
12778
+ "gpt-5.5": { input: 5, cachedInput: 0.5, output: 30, long: long(LONG_CONTEXT_THRESHOLD, 10, 1, 45) },
12779
+ "gpt-5.5-codex": { input: 5, cachedInput: 0.5, output: 30, long: long(LONG_CONTEXT_THRESHOLD, 10, 1, 45) },
12780
+ "gpt-5.5-pro": { input: 30, cachedInput: 30, output: 180, long: long(LONG_CONTEXT_THRESHOLD, 60, 60, 270) },
12781
+ "gpt-5.5-cyber": { input: 12.5, cachedInput: 1.25, output: 75 },
12782
+ // GPT-5.4 family
12783
+ "gpt-5.4": { input: 2.5, cachedInput: 0.25, output: 15, long: long(LONG_CONTEXT_THRESHOLD, 5, 0.5, 22.5) },
12784
+ "gpt-5.4-codex": { input: 2.5, cachedInput: 0.25, output: 15, long: long(LONG_CONTEXT_THRESHOLD, 5, 0.5, 22.5) },
12785
+ "gpt-5.4-mini": { input: 0.75, cachedInput: 0.075, output: 4.5 },
12786
+ "gpt-5.4-nano": { input: 0.2, cachedInput: 0.02, output: 1.25 },
12787
+ "gpt-5.4-pro": { input: 30, cachedInput: 30, output: 180, long: long(LONG_CONTEXT_THRESHOLD, 60, 60, 270) },
12788
+ // GPT-5.3 family (Codex-only release)
12789
+ "gpt-5.3": { input: 1.75, cachedInput: 0.175, output: 14 },
12790
+ "gpt-5.3-codex": { input: 1.75, cachedInput: 0.175, output: 14 },
12791
+ // GPT-5.2 family
12792
+ "gpt-5.2": { input: 1.75, cachedInput: 0.175, output: 14 },
12793
+ "gpt-5.2-codex": { input: 1.75, cachedInput: 0.175, output: 14 },
12794
+ "gpt-5.2-pro": { input: 21, cachedInput: 21, output: 168 },
12795
+ // GPT-5.1 family
12796
+ "gpt-5.1": { input: 1.25, cachedInput: 0.125, output: 10 },
12797
+ "gpt-5.1-codex": { input: 1.25, cachedInput: 0.125, output: 10 },
12798
+ "gpt-5.1-codex-max": { input: 1.25, cachedInput: 0.125, output: 10 },
12799
+ "gpt-5.1-codex-mini": { input: 0.25, cachedInput: 0.025, output: 2 },
12800
+ // GPT-5 family
12801
+ "gpt-5": { input: 1.25, cachedInput: 0.125, output: 10 },
12802
+ "gpt-5-codex": { input: 1.25, cachedInput: 0.125, output: 10 },
12803
+ "gpt-5-mini": { input: 0.25, cachedInput: 0.025, output: 2 },
12804
+ "gpt-5-nano": { input: 0.05, cachedInput: 5e-3, output: 0.4 },
12805
+ "gpt-5-pro": { input: 15, cachedInput: 15, output: 120 },
12806
+ "gpt-5-search-api": { input: 1.25, cachedInput: 0.125, output: 10 },
12807
+ // ChatGPT-tuned endpoint
12808
+ "chat-latest": { input: 5, cachedInput: 0.5, output: 30 },
12809
+ // GPT-4.1 / 4o family
12810
+ "gpt-4.1": { input: 2, cachedInput: 0.5, output: 8 },
12811
+ "gpt-4.1-mini": { input: 0.4, cachedInput: 0.1, output: 1.6 },
12812
+ "gpt-4.1-nano": { input: 0.1, cachedInput: 0.025, output: 0.4 },
12813
+ "gpt-4o": { input: 2.5, cachedInput: 1.25, output: 10 },
12814
+ "gpt-4o-mini": { input: 0.15, cachedInput: 0.075, output: 0.6 },
12815
+ // Reasoning models
12816
+ o1: { input: 15, cachedInput: 7.5, output: 60 },
12817
+ "o1-pro": { input: 150, cachedInput: 150, output: 600 },
12818
+ o3: { input: 2, cachedInput: 0.5, output: 8 },
12819
+ "o3-pro": { input: 20, cachedInput: 20, output: 80 },
12820
+ "o3-mini": { input: 1.1, cachedInput: 0.55, output: 4.4 },
12821
+ "o4-mini": { input: 1.1, cachedInput: 0.275, output: 4.4 },
12822
+ "codex-mini-latest": { input: 1.5, cachedInput: 0.375, output: 6 }
12823
+ };
12824
+
12761
12825
  // ../shared/src/time.ts
12762
12826
  var SECOND = 1e3;
12763
12827
  var MINUTE = 60 * SECOND;
@@ -12935,8 +12999,20 @@
12935
12999
  never: "never",
12936
13000
  local: "Local",
12937
13001
  remote: "Other devices",
13002
+ // updates
13003
+ update: "Update",
13004
+ updateAvailable: "Update to v{version}",
13005
+ updateNewVersion: "Version {version} is available (you have v{current})",
13006
+ updateUpToDate: "Up to date",
13007
+ updateChecking: "Checking\u2026",
13008
+ updateInstalling: "Installing\u2026",
13009
+ updateInstalled: "Updated to v{version} \u2014 restart to apply",
13010
+ updateFailed: "Update failed \u2014 run this yourself:",
13011
+ updateCheckFailed: "Update check failed: {message}",
13012
+ checkForUpdates: "Check for updates",
13013
+ releaseNotes: "Release notes",
12938
13014
  // CLI
12939
- cliUsage: `Usage: codex-tracker [command] [options]
13015
+ cliUsage: `Usage: codex-token-tracker [command] [options] (alias: codex-tracker)
12940
13016
 
12941
13017
  Commands:
12942
13018
  (none) Start the menu bar app (falls back to agent mode without a display)
@@ -12947,10 +13023,12 @@ Commands:
12947
13023
  logout Disconnect this device
12948
13024
  status Print today's usage, live session and rate limits
12949
13025
  paths Show detected session directories (Codex, pi, OpenCode, Cline/Roo/Kilo, Hermes, custom)
13026
+ update Install the newest published version (--check only reports)
12950
13027
  config get|set Read or change settings (config set uploadIntervalSec 30, config set sources.pi false)
12951
13028
  lang <en|zh|auto> Set the display language
12952
13029
 
12953
13030
  Options:
13031
+ --check update: report the newest version without installing it
12954
13032
  --dashboard <url> Dashboard URL (self-hosted)
12955
13033
  --background Start the menu bar app detached and return
12956
13034
  --version, -v Print version
@@ -12992,7 +13070,13 @@ Options:
12992
13070
  cliConfigSet: "Set {key} = {value}",
12993
13071
  cliConfigUnknownKey: "Unknown config key: {key}. Keys: {keys}",
12994
13072
  cliLangSet: "Language set to {lang}",
12995
- cliConfigDir: "Config: {dir}"
13073
+ cliConfigDir: "Config: {dir}",
13074
+ cliUpdateLatest: "codex-token-tracker {version} is the latest version.",
13075
+ cliUpdateAvailable: "Update available: {current} \u2192 {latest}",
13076
+ cliUpdateRunning: "Running: {command}",
13077
+ cliUpdateDone: "Updated to {version}. Restart the menu bar app (or rerun the CLI) to use it.",
13078
+ cliUpdateFailed: "Update failed (exit {code}). Run it yourself: {command}",
13079
+ cliUpdateCheckFailed: "Could not reach the npm registry: {message}"
12996
13080
  };
12997
13081
 
12998
13082
  // src/i18n/zh.ts
@@ -13066,7 +13150,18 @@ Options:
13066
13150
  never: "\u4ECE\u672A",
13067
13151
  local: "\u672C\u673A",
13068
13152
  remote: "\u5176\u4ED6\u8BBE\u5907",
13069
- cliUsage: `\u7528\u6CD5\uFF1Acodex-tracker [\u547D\u4EE4] [\u9009\u9879]
13153
+ update: "\u66F4\u65B0",
13154
+ updateAvailable: "\u66F4\u65B0\u5230 v{version}",
13155
+ updateNewVersion: "\u6709\u65B0\u7248\u672C {version}\uFF08\u5F53\u524D v{current}\uFF09",
13156
+ updateUpToDate: "\u5DF2\u662F\u6700\u65B0\u7248\u672C",
13157
+ updateChecking: "\u68C0\u67E5\u4E2D\u2026",
13158
+ updateInstalling: "\u5B89\u88C5\u4E2D\u2026",
13159
+ updateInstalled: "\u5DF2\u66F4\u65B0\u5230 v{version} \u2014 \u91CD\u542F\u540E\u751F\u6548",
13160
+ updateFailed: "\u66F4\u65B0\u5931\u8D25 \u2014 \u8BF7\u624B\u52A8\u6267\u884C\uFF1A",
13161
+ updateCheckFailed: "\u68C0\u67E5\u66F4\u65B0\u5931\u8D25\uFF1A{message}",
13162
+ checkForUpdates: "\u68C0\u67E5\u66F4\u65B0",
13163
+ releaseNotes: "\u66F4\u65B0\u65E5\u5FD7",
13164
+ cliUsage: `\u7528\u6CD5\uFF1Acodex-token-tracker [\u547D\u4EE4] [\u9009\u9879] \uFF08\u522B\u540D\uFF1Acodex-tracker\uFF09
13070
13165
 
13071
13166
  \u547D\u4EE4\uFF1A
13072
13167
  (\u65E0) \u542F\u52A8\u83DC\u5355\u680F\u5E94\u7528\uFF08\u65E0\u663E\u793A\u73AF\u5883\u65F6\u81EA\u52A8\u5207\u6362\u4E3A agent \u6A21\u5F0F\uFF09
@@ -13077,10 +13172,12 @@ Options:
13077
13172
  logout \u65AD\u5F00\u672C\u8BBE\u5907
13078
13173
  status \u6253\u5370\u4ECA\u65E5\u7528\u91CF\u3001\u5B9E\u65F6\u4F1A\u8BDD\u4E0E\u9650\u989D
13079
13174
  paths \u663E\u793A\u68C0\u6D4B\u5230\u7684\u4F1A\u8BDD\u76EE\u5F55\uFF08Codex\u3001pi\u3001OpenCode\u3001Cline/Roo/Kilo\u3001Hermes\u3001\u81EA\u5B9A\u4E49\uFF09
13175
+ update \u5B89\u88C5\u6700\u65B0\u53D1\u5E03\u7248\u672C\uFF08--check \u53EA\u68C0\u67E5\u4E0D\u5B89\u88C5\uFF09
13080
13176
  config get|set \u8BFB\u53D6\u6216\u4FEE\u6539\u8BBE\u7F6E\uFF08config set uploadIntervalSec 30\uFF0Cconfig set sources.pi false\uFF09
13081
13177
  lang <en|zh|auto> \u8BBE\u7F6E\u663E\u793A\u8BED\u8A00
13082
13178
 
13083
13179
  \u9009\u9879\uFF1A
13180
+ --check update\uFF1A\u53EA\u62A5\u544A\u6700\u65B0\u7248\u672C\uFF0C\u4E0D\u6267\u884C\u5B89\u88C5
13084
13181
  --dashboard <url> \u4EEA\u8868\u76D8\u5730\u5740\uFF08\u81EA\u6258\u7BA1\uFF09
13085
13182
  --background \u4EE5\u540E\u53F0\u65B9\u5F0F\u542F\u52A8\u83DC\u5355\u680F\u5E94\u7528\u5E76\u7ACB\u5373\u8FD4\u56DE
13086
13183
  --version, -v \u663E\u793A\u7248\u672C
@@ -13122,7 +13219,13 @@ Options:
13122
13219
  cliConfigSet: "\u5DF2\u8BBE\u7F6E {key} = {value}",
13123
13220
  cliConfigUnknownKey: "\u672A\u77E5\u914D\u7F6E\u9879\uFF1A{key}\u3002\u53EF\u7528\uFF1A{keys}",
13124
13221
  cliLangSet: "\u8BED\u8A00\u5DF2\u8BBE\u7F6E\u4E3A {lang}",
13125
- cliConfigDir: "\u914D\u7F6E\u76EE\u5F55\uFF1A{dir}"
13222
+ cliConfigDir: "\u914D\u7F6E\u76EE\u5F55\uFF1A{dir}",
13223
+ cliUpdateLatest: "codex-token-tracker {version} \u5DF2\u662F\u6700\u65B0\u7248\u672C\u3002",
13224
+ cliUpdateAvailable: "\u53D1\u73B0\u65B0\u7248\u672C\uFF1A{current} \u2192 {latest}",
13225
+ cliUpdateRunning: "\u6B63\u5728\u6267\u884C\uFF1A{command}",
13226
+ cliUpdateDone: "\u5DF2\u66F4\u65B0\u5230 {version}\u3002\u8BF7\u91CD\u542F\u83DC\u5355\u680F\u5E94\u7528\uFF08\u6216\u91CD\u65B0\u8FD0\u884C CLI\uFF09\u4EE5\u751F\u6548\u3002",
13227
+ cliUpdateFailed: "\u66F4\u65B0\u5931\u8D25\uFF08\u9000\u51FA\u7801 {code}\uFF09\u3002\u8BF7\u624B\u52A8\u6267\u884C\uFF1A{command}",
13228
+ cliUpdateCheckFailed: "\u65E0\u6CD5\u8BBF\u95EE npm registry\uFF1A{message}"
13126
13229
  };
13127
13230
 
13128
13231
  // src/i18n/index.ts
@@ -13367,6 +13470,25 @@ Options:
13367
13470
  function levelClass(pct) {
13368
13471
  return pct >= 85 ? "critical" : pct >= 60 ? "warning" : "";
13369
13472
  }
13473
+ function UpdateBar({ update, t: t2 }) {
13474
+ if (update.status === "installed") {
13475
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "update-bar done", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "msg", children: t2("updateInstalled", { version: update.latest ?? "?" }) }) });
13476
+ }
13477
+ if (update.status === "failed") {
13478
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "update-bar failed", children: [
13479
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "msg", title: update.log ?? "", children: t2("updateFailed") }),
13480
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "cmd", children: update.command })
13481
+ ] });
13482
+ }
13483
+ if (update.status === "installing") {
13484
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "update-bar", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "msg", children: t2("updateInstalling") }) });
13485
+ }
13486
+ if (!update.available) return null;
13487
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "update-bar", children: [
13488
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "msg", children: t2("updateNewVersion", { version: update.latest ?? "?", current: update.current }) }),
13489
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "primary", onClick: () => void bridge().installUpdate(), children: t2("update") })
13490
+ ] });
13491
+ }
13370
13492
  function App() {
13371
13493
  const [snap, setSnap] = (0, import_react2.useState)(null);
13372
13494
  const [, setClock] = (0, import_react2.useState)(0);
@@ -13415,6 +13537,7 @@ Options:
13415
13537
  ] })
13416
13538
  ] }),
13417
13539
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "scroll", children: [
13540
+ snap.update ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UpdateBar, { update: snap.update, t: t2 }) : null,
13418
13541
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "card", children: [
13419
13542
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "card-title", children: [
13420
13543
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: t2("today") }),
@@ -543,3 +543,33 @@ button.ghost:hover {
543
543
  .source-line .dot { width: 6px; height: 6px; border-radius: 50%; background: #0ca30c; flex: none; }
544
544
  .source-line.stale .dot { background: #fab219; }
545
545
  .source-line .err-hint { color: #d03b3b; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
546
+
547
+ /* --- update banner --- */
548
+ .update-bar {
549
+ display: flex;
550
+ align-items: center;
551
+ gap: 8px;
552
+ margin: 10px 12px 0;
553
+ padding: 8px 10px;
554
+ border: 1px solid var(--border);
555
+ border-radius: 8px;
556
+ background: rgba(99, 102, 241, 0.09);
557
+ font-size: 11px;
558
+ color: var(--text);
559
+ }
560
+ .update-bar .msg {
561
+ flex: 1;
562
+ min-width: 0;
563
+ overflow: hidden;
564
+ text-overflow: ellipsis;
565
+ white-space: nowrap;
566
+ }
567
+ .update-bar.failed { background: rgba(208, 59, 59, 0.1); }
568
+ .update-bar.done { background: rgba(12, 163, 12, 0.1); }
569
+ .update-bar button { flex: none; }
570
+ .update-bar .cmd {
571
+ font-family: var(--mono);
572
+ font-size: 10px;
573
+ color: var(--muted);
574
+ user-select: text;
575
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-token-tracker",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Menu bar / system tray app and headless agent that tracks OpenAI Codex token usage, cache hits, model mix and API-equivalent cost — and syncs it to your team dashboard.",
5
5
  "license": "MIT",
6
6
  "author": "Chen Li",
@@ -25,6 +25,7 @@
25
25
  "convex"
26
26
  ],
27
27
  "bin": {
28
+ "codex-token-tracker": "bin/codex-tracker.js",
28
29
  "codex-tracker": "bin/codex-tracker.js"
29
30
  },
30
31
  "main": "dist/main.js",
@@ -32,7 +33,8 @@
32
33
  "bin",
33
34
  "dist",
34
35
  "assets",
35
- "README.md"
36
+ "README.md",
37
+ "CHANGELOG.md"
36
38
  ],
37
39
  "engines": {
38
40
  "node": ">=20"
@@ -45,6 +47,15 @@
45
47
  "publishConfig": {
46
48
  "access": "public"
47
49
  },
50
+ "scripts": {
51
+ "build": "node scripts/build.mjs",
52
+ "dev": "node scripts/build.mjs --watch",
53
+ "typecheck": "tsc --noEmit -p tsconfig.json",
54
+ "start": "node bin/codex-tracker.js",
55
+ "prepublishOnly": "pnpm build && pnpm typecheck",
56
+ "build:icons": "node scripts/gen-icons.mjs",
57
+ "test": "node scripts/test.mjs"
58
+ },
48
59
  "dependencies": {
49
60
  "menubar": "^9.5.3"
50
61
  },
@@ -52,6 +63,8 @@
52
63
  "electron": "^38.8.6"
53
64
  },
54
65
  "devDependencies": {
66
+ "@codex-tracker/backend": "workspace:*",
67
+ "@codex-tracker/shared": "workspace:*",
55
68
  "@types/node": "^22.15.0",
56
69
  "@types/react": "^19.2.0",
57
70
  "@types/react-dom": "^19.2.0",
@@ -59,16 +72,6 @@
59
72
  "esbuild": "^0.28.2",
60
73
  "react": "19.2.8",
61
74
  "react-dom": "19.2.8",
62
- "typescript": "~5.9.3",
63
- "@codex-tracker/backend": "0.1.0",
64
- "@codex-tracker/shared": "0.1.0"
65
- },
66
- "scripts": {
67
- "build": "node scripts/build.mjs",
68
- "dev": "node scripts/build.mjs --watch",
69
- "typecheck": "tsc --noEmit -p tsconfig.json",
70
- "start": "node bin/codex-tracker.js",
71
- "build:icons": "node scripts/gen-icons.mjs",
72
- "test": "node scripts/test.mjs"
75
+ "typescript": "~5.9.3"
73
76
  }
74
- }
77
+ }