codex-token-tracker 0.2.0 → 0.2.2
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/CHANGELOG.md +76 -0
- package/README.md +68 -5
- package/dist/cli.js +299 -25
- package/dist/main.js +936 -43
- package/dist/preload.js +1 -0
- package/dist/renderer/renderer.js +114 -7
- package/dist/renderer/styles.css +99 -0
- package/package.json +16 -20
package/dist/main.js
CHANGED
|
@@ -5,6 +5,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
9
|
+
try {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
throw mod = 0, e;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
8
15
|
var __copyProps = (to, from, except, desc) => {
|
|
9
16
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
17
|
for (let key of __getOwnPropNames(from))
|
|
@@ -22,13 +29,691 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
29
|
mod
|
|
23
30
|
));
|
|
24
31
|
|
|
32
|
+
// ../../node_modules/.pnpm/electron-positioner@4.1.0/node_modules/electron-positioner/index.js
|
|
33
|
+
var require_electron_positioner = __commonJS({
|
|
34
|
+
"../../node_modules/.pnpm/electron-positioner@4.1.0/node_modules/electron-positioner/index.js"(exports2, module2) {
|
|
35
|
+
"use strict";
|
|
36
|
+
module2.exports = class Positioner {
|
|
37
|
+
constructor(browserWindow) {
|
|
38
|
+
this.browserWindow = browserWindow;
|
|
39
|
+
this.electronScreen = require("electron").screen;
|
|
40
|
+
}
|
|
41
|
+
_getCoords(position, trayPosition) {
|
|
42
|
+
let screenSize = this._getScreenSize(trayPosition);
|
|
43
|
+
let windowSize = this._getWindowSize();
|
|
44
|
+
if (trayPosition === void 0) trayPosition = {};
|
|
45
|
+
let positions = {
|
|
46
|
+
trayLeft: {
|
|
47
|
+
x: Math.floor(trayPosition.x),
|
|
48
|
+
y: screenSize.y
|
|
49
|
+
},
|
|
50
|
+
trayBottomLeft: {
|
|
51
|
+
x: Math.floor(trayPosition.x),
|
|
52
|
+
y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y))
|
|
53
|
+
},
|
|
54
|
+
trayRight: {
|
|
55
|
+
x: Math.floor(trayPosition.x - windowSize[0] + trayPosition.width),
|
|
56
|
+
y: screenSize.y
|
|
57
|
+
},
|
|
58
|
+
trayBottomRight: {
|
|
59
|
+
x: Math.floor(trayPosition.x - windowSize[0] + trayPosition.width),
|
|
60
|
+
y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y))
|
|
61
|
+
},
|
|
62
|
+
trayCenter: {
|
|
63
|
+
x: Math.floor(trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2),
|
|
64
|
+
y: screenSize.y
|
|
65
|
+
},
|
|
66
|
+
trayBottomCenter: {
|
|
67
|
+
x: Math.floor(trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2),
|
|
68
|
+
y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y))
|
|
69
|
+
},
|
|
70
|
+
topLeft: {
|
|
71
|
+
x: screenSize.x,
|
|
72
|
+
y: screenSize.y
|
|
73
|
+
},
|
|
74
|
+
topRight: {
|
|
75
|
+
x: Math.floor(screenSize.x + (screenSize.width - windowSize[0])),
|
|
76
|
+
y: screenSize.y
|
|
77
|
+
},
|
|
78
|
+
bottomLeft: {
|
|
79
|
+
x: screenSize.x,
|
|
80
|
+
y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y))
|
|
81
|
+
},
|
|
82
|
+
bottomRight: {
|
|
83
|
+
x: Math.floor(screenSize.x + (screenSize.width - windowSize[0])),
|
|
84
|
+
y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y))
|
|
85
|
+
},
|
|
86
|
+
topCenter: {
|
|
87
|
+
x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)),
|
|
88
|
+
y: screenSize.y
|
|
89
|
+
},
|
|
90
|
+
bottomCenter: {
|
|
91
|
+
x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)),
|
|
92
|
+
y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y))
|
|
93
|
+
},
|
|
94
|
+
leftCenter: {
|
|
95
|
+
x: screenSize.x,
|
|
96
|
+
y: screenSize.y + Math.floor(screenSize.height / 2) - Math.floor(windowSize[1] / 2)
|
|
97
|
+
},
|
|
98
|
+
rightCenter: {
|
|
99
|
+
x: Math.floor(screenSize.x + (screenSize.width - windowSize[0])),
|
|
100
|
+
y: screenSize.y + Math.floor(screenSize.height / 2) - Math.floor(windowSize[1] / 2)
|
|
101
|
+
},
|
|
102
|
+
center: {
|
|
103
|
+
x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)),
|
|
104
|
+
y: Math.floor((screenSize.height + screenSize.y) / 2 - windowSize[1] / 2)
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
if (position.substr(0, 4) === "tray") {
|
|
108
|
+
if (positions[position].x + windowSize[0] > screenSize.width + screenSize.x) {
|
|
109
|
+
return {
|
|
110
|
+
x: positions["topRight"].x,
|
|
111
|
+
y: positions[position].y
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return positions[position];
|
|
116
|
+
}
|
|
117
|
+
_getWindowSize() {
|
|
118
|
+
return this.browserWindow.getSize();
|
|
119
|
+
}
|
|
120
|
+
_getScreenSize(trayPosition) {
|
|
121
|
+
if (trayPosition) {
|
|
122
|
+
return this.electronScreen.getDisplayMatching(trayPosition).workArea;
|
|
123
|
+
} else {
|
|
124
|
+
return this.electronScreen.getDisplayNearestPoint(this.electronScreen.getCursorScreenPoint()).workArea;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
move(position, trayPos) {
|
|
128
|
+
var coords = this._getCoords(position, trayPos);
|
|
129
|
+
this.browserWindow.setPosition(coords.x, coords.y);
|
|
130
|
+
}
|
|
131
|
+
calculate(position, trayPos) {
|
|
132
|
+
var coords = this._getCoords(position, trayPos);
|
|
133
|
+
return {
|
|
134
|
+
x: coords.x,
|
|
135
|
+
y: coords.y
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// ../../node_modules/.pnpm/menubar@9.5.3_electron@38.8.6/node_modules/menubar/lib/util/cleanOptions.js
|
|
143
|
+
var require_cleanOptions = __commonJS({
|
|
144
|
+
"../../node_modules/.pnpm/menubar@9.5.3_electron@38.8.6/node_modules/menubar/lib/util/cleanOptions.js"(exports2) {
|
|
145
|
+
"use strict";
|
|
146
|
+
var __assign = exports2 && exports2.__assign || function() {
|
|
147
|
+
__assign = Object.assign || function(t2) {
|
|
148
|
+
for (var s, i2 = 1, n = arguments.length; i2 < n; i2++) {
|
|
149
|
+
s = arguments[i2];
|
|
150
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
151
|
+
t2[p] = s[p];
|
|
152
|
+
}
|
|
153
|
+
return t2;
|
|
154
|
+
};
|
|
155
|
+
return __assign.apply(this, arguments);
|
|
156
|
+
};
|
|
157
|
+
var __importDefault = exports2 && exports2.__importDefault || function(mod) {
|
|
158
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
159
|
+
};
|
|
160
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
161
|
+
exports2.cleanOptions = void 0;
|
|
162
|
+
var path_1 = __importDefault(require("path"));
|
|
163
|
+
var url_1 = __importDefault(require("url"));
|
|
164
|
+
var electron_1 = require("electron");
|
|
165
|
+
var DEFAULT_WINDOW_HEIGHT = 400;
|
|
166
|
+
var DEFAULT_WINDOW_WIDTH = 400;
|
|
167
|
+
function cleanOptions(opts) {
|
|
168
|
+
var options = __assign({}, opts);
|
|
169
|
+
if (options.activateWithApp === void 0) {
|
|
170
|
+
options.activateWithApp = true;
|
|
171
|
+
}
|
|
172
|
+
if (!options.dir) {
|
|
173
|
+
options.dir = electron_1.app.getAppPath();
|
|
174
|
+
}
|
|
175
|
+
if (!path_1.default.isAbsolute(options.dir)) {
|
|
176
|
+
options.dir = path_1.default.resolve(options.dir);
|
|
177
|
+
}
|
|
178
|
+
if (options.index === void 0) {
|
|
179
|
+
options.index = url_1.default.format({
|
|
180
|
+
pathname: path_1.default.join(options.dir, "index.html"),
|
|
181
|
+
protocol: "file:",
|
|
182
|
+
slashes: true
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
options.loadUrlOptions = options.loadUrlOptions || {};
|
|
186
|
+
options.tooltip = options.tooltip || "";
|
|
187
|
+
if (!options.browserWindow) {
|
|
188
|
+
options.browserWindow = {};
|
|
189
|
+
}
|
|
190
|
+
options.browserWindow.width = // Note: not using `options.browserWindow.width || DEFAULT_WINDOW_WIDTH` so
|
|
191
|
+
// that users can put a 0 width
|
|
192
|
+
options.browserWindow.width !== void 0 ? options.browserWindow.width : DEFAULT_WINDOW_WIDTH;
|
|
193
|
+
options.browserWindow.height = options.browserWindow.height !== void 0 ? options.browserWindow.height : DEFAULT_WINDOW_HEIGHT;
|
|
194
|
+
return options;
|
|
195
|
+
}
|
|
196
|
+
exports2.cleanOptions = cleanOptions;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// ../../node_modules/.pnpm/menubar@9.5.3_electron@38.8.6/node_modules/menubar/lib/util/getWindowPosition.js
|
|
201
|
+
var require_getWindowPosition = __commonJS({
|
|
202
|
+
"../../node_modules/.pnpm/menubar@9.5.3_electron@38.8.6/node_modules/menubar/lib/util/getWindowPosition.js"(exports2) {
|
|
203
|
+
"use strict";
|
|
204
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
205
|
+
exports2.getWindowPosition = exports2.taskbarLocation = void 0;
|
|
206
|
+
var electron_1 = require("electron");
|
|
207
|
+
var isLinux = process.platform === "linux";
|
|
208
|
+
var trayToScreenRects = function(tray) {
|
|
209
|
+
var _a2 = electron_1.screen.getDisplayMatching(tray.getBounds()), workArea = _a2.workArea, screenBounds = _a2.bounds;
|
|
210
|
+
workArea.x -= screenBounds.x;
|
|
211
|
+
workArea.y -= screenBounds.y;
|
|
212
|
+
return [screenBounds, workArea];
|
|
213
|
+
};
|
|
214
|
+
function taskbarLocation(tray) {
|
|
215
|
+
var _a2 = trayToScreenRects(tray), screenBounds = _a2[0], workArea = _a2[1];
|
|
216
|
+
if (workArea.x > 0) {
|
|
217
|
+
if (isLinux && workArea.y > 0)
|
|
218
|
+
return "top";
|
|
219
|
+
return "left";
|
|
220
|
+
}
|
|
221
|
+
if (workArea.y > 0) {
|
|
222
|
+
return "top";
|
|
223
|
+
}
|
|
224
|
+
if (workArea.width < screenBounds.width) {
|
|
225
|
+
return "right";
|
|
226
|
+
}
|
|
227
|
+
return "bottom";
|
|
228
|
+
}
|
|
229
|
+
exports2.taskbarLocation = taskbarLocation;
|
|
230
|
+
function getWindowPosition(tray) {
|
|
231
|
+
switch (process.platform) {
|
|
232
|
+
// macOS
|
|
233
|
+
// Supports top taskbars
|
|
234
|
+
case "darwin":
|
|
235
|
+
return "trayCenter";
|
|
236
|
+
// Linux
|
|
237
|
+
// Windows
|
|
238
|
+
// Supports top/bottom/left/right taskbar
|
|
239
|
+
case "linux":
|
|
240
|
+
case "win32": {
|
|
241
|
+
var traySide = taskbarLocation(tray);
|
|
242
|
+
if (traySide === "top") {
|
|
243
|
+
return isLinux ? "topRight" : "trayCenter";
|
|
244
|
+
}
|
|
245
|
+
if (traySide === "bottom") {
|
|
246
|
+
return "bottomRight";
|
|
247
|
+
}
|
|
248
|
+
if (traySide === "left") {
|
|
249
|
+
return "bottomLeft";
|
|
250
|
+
}
|
|
251
|
+
if (traySide === "right") {
|
|
252
|
+
return "bottomRight";
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return "topRight";
|
|
257
|
+
}
|
|
258
|
+
exports2.getWindowPosition = getWindowPosition;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// ../../node_modules/.pnpm/menubar@9.5.3_electron@38.8.6/node_modules/menubar/lib/Menubar.js
|
|
263
|
+
var require_Menubar = __commonJS({
|
|
264
|
+
"../../node_modules/.pnpm/menubar@9.5.3_electron@38.8.6/node_modules/menubar/lib/Menubar.js"(exports2) {
|
|
265
|
+
"use strict";
|
|
266
|
+
var __extends = exports2 && exports2.__extends || /* @__PURE__ */ (function() {
|
|
267
|
+
var extendStatics = function(d, b) {
|
|
268
|
+
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
|
|
269
|
+
d2.__proto__ = b2;
|
|
270
|
+
} || function(d2, b2) {
|
|
271
|
+
for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p];
|
|
272
|
+
};
|
|
273
|
+
return extendStatics(d, b);
|
|
274
|
+
};
|
|
275
|
+
return function(d, b) {
|
|
276
|
+
if (typeof b !== "function" && b !== null)
|
|
277
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
278
|
+
extendStatics(d, b);
|
|
279
|
+
function __() {
|
|
280
|
+
this.constructor = d;
|
|
281
|
+
}
|
|
282
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
283
|
+
};
|
|
284
|
+
})();
|
|
285
|
+
var __assign = exports2 && exports2.__assign || function() {
|
|
286
|
+
__assign = Object.assign || function(t2) {
|
|
287
|
+
for (var s, i2 = 1, n = arguments.length; i2 < n; i2++) {
|
|
288
|
+
s = arguments[i2];
|
|
289
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
290
|
+
t2[p] = s[p];
|
|
291
|
+
}
|
|
292
|
+
return t2;
|
|
293
|
+
};
|
|
294
|
+
return __assign.apply(this, arguments);
|
|
295
|
+
};
|
|
296
|
+
var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
297
|
+
function adopt(value) {
|
|
298
|
+
return value instanceof P ? value : new P(function(resolve) {
|
|
299
|
+
resolve(value);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
return new (P || (P = Promise))(function(resolve, reject) {
|
|
303
|
+
function fulfilled(value) {
|
|
304
|
+
try {
|
|
305
|
+
step(generator.next(value));
|
|
306
|
+
} catch (e) {
|
|
307
|
+
reject(e);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function rejected(value) {
|
|
311
|
+
try {
|
|
312
|
+
step(generator["throw"](value));
|
|
313
|
+
} catch (e) {
|
|
314
|
+
reject(e);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
function step(result) {
|
|
318
|
+
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
319
|
+
}
|
|
320
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
var __generator = exports2 && exports2.__generator || function(thisArg, body) {
|
|
324
|
+
var _ = { label: 0, sent: function() {
|
|
325
|
+
if (t2[0] & 1) throw t2[1];
|
|
326
|
+
return t2[1];
|
|
327
|
+
}, trys: [], ops: [] }, f, y, t2, g;
|
|
328
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
329
|
+
return this;
|
|
330
|
+
}), g;
|
|
331
|
+
function verb(n) {
|
|
332
|
+
return function(v2) {
|
|
333
|
+
return step([n, v2]);
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
function step(op) {
|
|
337
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
338
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
339
|
+
if (f = 1, y && (t2 = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t2 = y["return"]) && t2.call(y), 0) : y.next) && !(t2 = t2.call(y, op[1])).done) return t2;
|
|
340
|
+
if (y = 0, t2) op = [op[0] & 2, t2.value];
|
|
341
|
+
switch (op[0]) {
|
|
342
|
+
case 0:
|
|
343
|
+
case 1:
|
|
344
|
+
t2 = op;
|
|
345
|
+
break;
|
|
346
|
+
case 4:
|
|
347
|
+
_.label++;
|
|
348
|
+
return { value: op[1], done: false };
|
|
349
|
+
case 5:
|
|
350
|
+
_.label++;
|
|
351
|
+
y = op[1];
|
|
352
|
+
op = [0];
|
|
353
|
+
continue;
|
|
354
|
+
case 7:
|
|
355
|
+
op = _.ops.pop();
|
|
356
|
+
_.trys.pop();
|
|
357
|
+
continue;
|
|
358
|
+
default:
|
|
359
|
+
if (!(t2 = _.trys, t2 = t2.length > 0 && t2[t2.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
360
|
+
_ = 0;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (op[0] === 3 && (!t2 || op[1] > t2[0] && op[1] < t2[3])) {
|
|
364
|
+
_.label = op[1];
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
if (op[0] === 6 && _.label < t2[1]) {
|
|
368
|
+
_.label = t2[1];
|
|
369
|
+
t2 = op;
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
if (t2 && _.label < t2[2]) {
|
|
373
|
+
_.label = t2[2];
|
|
374
|
+
_.ops.push(op);
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
if (t2[2]) _.ops.pop();
|
|
378
|
+
_.trys.pop();
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
op = body.call(thisArg, _);
|
|
382
|
+
} catch (e) {
|
|
383
|
+
op = [6, e];
|
|
384
|
+
y = 0;
|
|
385
|
+
} finally {
|
|
386
|
+
f = t2 = 0;
|
|
387
|
+
}
|
|
388
|
+
if (op[0] & 5) throw op[1];
|
|
389
|
+
return { value: op[0] ? op[1] : void 0, done: true };
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
var __importDefault = exports2 && exports2.__importDefault || function(mod) {
|
|
393
|
+
return mod && mod.__esModule ? mod : { "default": mod };
|
|
394
|
+
};
|
|
395
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
396
|
+
exports2.Menubar = void 0;
|
|
397
|
+
var events_1 = require("events");
|
|
398
|
+
var fs_1 = __importDefault(require("fs"));
|
|
399
|
+
var path_1 = __importDefault(require("path"));
|
|
400
|
+
var electron_1 = require("electron");
|
|
401
|
+
var electron_positioner_1 = __importDefault(require_electron_positioner());
|
|
402
|
+
var cleanOptions_1 = require_cleanOptions();
|
|
403
|
+
var getWindowPosition_1 = require_getWindowPosition();
|
|
404
|
+
var Menubar = (
|
|
405
|
+
/** @class */
|
|
406
|
+
(function(_super) {
|
|
407
|
+
__extends(Menubar2, _super);
|
|
408
|
+
function Menubar2(app2, options) {
|
|
409
|
+
var _this = _super.call(this) || this;
|
|
410
|
+
_this._blurTimeout = null;
|
|
411
|
+
_this._app = app2;
|
|
412
|
+
_this._options = (0, cleanOptions_1.cleanOptions)(options);
|
|
413
|
+
_this._isVisible = false;
|
|
414
|
+
if (app2.isReady()) {
|
|
415
|
+
process.nextTick(function() {
|
|
416
|
+
return _this.appReady().catch(function(err) {
|
|
417
|
+
return console.error("menubar: ", err);
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
} else {
|
|
421
|
+
app2.on("ready", function() {
|
|
422
|
+
_this.appReady().catch(function(err) {
|
|
423
|
+
return console.error("menubar: ", err);
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
return _this;
|
|
428
|
+
}
|
|
429
|
+
Object.defineProperty(Menubar2.prototype, "app", {
|
|
430
|
+
/**
|
|
431
|
+
* The Electron [App](https://electronjs.org/docs/api/app)
|
|
432
|
+
* instance.
|
|
433
|
+
*/
|
|
434
|
+
get: function() {
|
|
435
|
+
return this._app;
|
|
436
|
+
},
|
|
437
|
+
enumerable: false,
|
|
438
|
+
configurable: true
|
|
439
|
+
});
|
|
440
|
+
Object.defineProperty(Menubar2.prototype, "positioner", {
|
|
441
|
+
/**
|
|
442
|
+
* The [electron-positioner](https://github.com/jenslind/electron-positioner)
|
|
443
|
+
* instance.
|
|
444
|
+
*/
|
|
445
|
+
get: function() {
|
|
446
|
+
if (!this._positioner) {
|
|
447
|
+
throw new Error("Please access `this.positioner` after the `after-create-window` event has fired.");
|
|
448
|
+
}
|
|
449
|
+
return this._positioner;
|
|
450
|
+
},
|
|
451
|
+
enumerable: false,
|
|
452
|
+
configurable: true
|
|
453
|
+
});
|
|
454
|
+
Object.defineProperty(Menubar2.prototype, "tray", {
|
|
455
|
+
/**
|
|
456
|
+
* The Electron [Tray](https://electronjs.org/docs/api/tray) instance.
|
|
457
|
+
*/
|
|
458
|
+
get: function() {
|
|
459
|
+
if (!this._tray) {
|
|
460
|
+
throw new Error("Please access `this.tray` after the `ready` event has fired.");
|
|
461
|
+
}
|
|
462
|
+
return this._tray;
|
|
463
|
+
},
|
|
464
|
+
enumerable: false,
|
|
465
|
+
configurable: true
|
|
466
|
+
});
|
|
467
|
+
Object.defineProperty(Menubar2.prototype, "window", {
|
|
468
|
+
/**
|
|
469
|
+
* The Electron [BrowserWindow](https://electronjs.org/docs/api/browser-window)
|
|
470
|
+
* instance, if it's present.
|
|
471
|
+
*/
|
|
472
|
+
get: function() {
|
|
473
|
+
return this._browserWindow;
|
|
474
|
+
},
|
|
475
|
+
enumerable: false,
|
|
476
|
+
configurable: true
|
|
477
|
+
});
|
|
478
|
+
Menubar2.prototype.getOption = function(key) {
|
|
479
|
+
return this._options[key];
|
|
480
|
+
};
|
|
481
|
+
Menubar2.prototype.hideWindow = function() {
|
|
482
|
+
if (!this._browserWindow || !this._isVisible) {
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
this.emit("hide");
|
|
486
|
+
this._browserWindow.hide();
|
|
487
|
+
this.emit("after-hide");
|
|
488
|
+
this._isVisible = false;
|
|
489
|
+
if (this._blurTimeout) {
|
|
490
|
+
clearTimeout(this._blurTimeout);
|
|
491
|
+
this._blurTimeout = null;
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
Menubar2.prototype.setOption = function(key, value) {
|
|
495
|
+
this._options[key] = value;
|
|
496
|
+
};
|
|
497
|
+
Menubar2.prototype.showWindow = function(trayPos) {
|
|
498
|
+
return __awaiter(this, void 0, void 0, function() {
|
|
499
|
+
var noBoundsPosition, position, x, y;
|
|
500
|
+
return __generator(this, function(_a2) {
|
|
501
|
+
switch (_a2.label) {
|
|
502
|
+
case 0:
|
|
503
|
+
if (!this.tray) {
|
|
504
|
+
throw new Error("Tray should have been instantiated by now");
|
|
505
|
+
}
|
|
506
|
+
if (!!this._browserWindow) return [3, 2];
|
|
507
|
+
return [4, this.createWindow()];
|
|
508
|
+
case 1:
|
|
509
|
+
_a2.sent();
|
|
510
|
+
_a2.label = 2;
|
|
511
|
+
case 2:
|
|
512
|
+
if (!this._browserWindow) {
|
|
513
|
+
throw new Error("Window has been initialized just above. qed.");
|
|
514
|
+
}
|
|
515
|
+
if (["win32", "linux"].includes(process.platform)) {
|
|
516
|
+
this._options.windowPosition = (0, getWindowPosition_1.getWindowPosition)(this.tray);
|
|
517
|
+
}
|
|
518
|
+
this.emit("show");
|
|
519
|
+
if (trayPos && trayPos.x !== 0) {
|
|
520
|
+
this._cachedBounds = trayPos;
|
|
521
|
+
} else if (this._cachedBounds) {
|
|
522
|
+
trayPos = this._cachedBounds;
|
|
523
|
+
} else if (this.tray.getBounds) {
|
|
524
|
+
trayPos = this.tray.getBounds();
|
|
525
|
+
}
|
|
526
|
+
noBoundsPosition = void 0;
|
|
527
|
+
if ((trayPos === void 0 || trayPos.x === 0) && this._options.windowPosition && this._options.windowPosition.startsWith("tray")) {
|
|
528
|
+
noBoundsPosition = process.platform === "win32" ? "bottomRight" : "topRight";
|
|
529
|
+
}
|
|
530
|
+
position = this.positioner.calculate(this._options.windowPosition || noBoundsPosition, trayPos);
|
|
531
|
+
x = this._options.browserWindow.x !== void 0 ? this._options.browserWindow.x : position.x;
|
|
532
|
+
y = this._options.browserWindow.y !== void 0 ? this._options.browserWindow.y : position.y;
|
|
533
|
+
this._browserWindow.setPosition(Math.round(x), Math.round(y));
|
|
534
|
+
this._browserWindow.show();
|
|
535
|
+
this._isVisible = true;
|
|
536
|
+
this.emit("after-show");
|
|
537
|
+
return [
|
|
538
|
+
2
|
|
539
|
+
/*return*/
|
|
540
|
+
];
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
};
|
|
545
|
+
Menubar2.prototype.appReady = function() {
|
|
546
|
+
return __awaiter(this, void 0, void 0, function() {
|
|
547
|
+
var trayImage, defaultClickEvent;
|
|
548
|
+
var _this = this;
|
|
549
|
+
return __generator(this, function(_a2) {
|
|
550
|
+
switch (_a2.label) {
|
|
551
|
+
case 0:
|
|
552
|
+
if (this.app.dock && !this._options.showDockIcon) {
|
|
553
|
+
this.app.dock.hide();
|
|
554
|
+
}
|
|
555
|
+
if (this._options.activateWithApp) {
|
|
556
|
+
this.app.on("activate", function(_event, hasVisibleWindows) {
|
|
557
|
+
if (!hasVisibleWindows) {
|
|
558
|
+
_this.showWindow().catch(console.error);
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
trayImage = this._options.icon || path_1.default.join(this._options.dir, "IconTemplate.png");
|
|
563
|
+
if (typeof trayImage === "string" && !fs_1.default.existsSync(trayImage)) {
|
|
564
|
+
trayImage = path_1.default.join(__dirname, "..", "assets", "IconTemplate.png");
|
|
565
|
+
}
|
|
566
|
+
defaultClickEvent = this._options.showOnRightClick ? "right-click" : "click";
|
|
567
|
+
this._tray = this._options.tray || new electron_1.Tray(trayImage);
|
|
568
|
+
if (!this.tray) {
|
|
569
|
+
throw new Error("Tray has been initialized above");
|
|
570
|
+
}
|
|
571
|
+
this.tray.on(defaultClickEvent, this.clicked.bind(this));
|
|
572
|
+
this.tray.on("double-click", this.clicked.bind(this));
|
|
573
|
+
this.tray.setToolTip(this._options.tooltip);
|
|
574
|
+
if (!this._options.windowPosition) {
|
|
575
|
+
this._options.windowPosition = (0, getWindowPosition_1.getWindowPosition)(this.tray);
|
|
576
|
+
}
|
|
577
|
+
if (!this._options.preloadWindow) return [3, 2];
|
|
578
|
+
return [4, this.createWindow()];
|
|
579
|
+
case 1:
|
|
580
|
+
_a2.sent();
|
|
581
|
+
_a2.label = 2;
|
|
582
|
+
case 2:
|
|
583
|
+
this.emit("ready");
|
|
584
|
+
return [
|
|
585
|
+
2
|
|
586
|
+
/*return*/
|
|
587
|
+
];
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
};
|
|
592
|
+
Menubar2.prototype.clicked = function(event, bounds) {
|
|
593
|
+
return __awaiter(this, void 0, void 0, function() {
|
|
594
|
+
return __generator(this, function(_a2) {
|
|
595
|
+
switch (_a2.label) {
|
|
596
|
+
case 0:
|
|
597
|
+
if (event && (event.shiftKey || event.ctrlKey || event.metaKey)) {
|
|
598
|
+
return [2, this.hideWindow()];
|
|
599
|
+
}
|
|
600
|
+
if (this._blurTimeout) {
|
|
601
|
+
clearInterval(this._blurTimeout);
|
|
602
|
+
}
|
|
603
|
+
if (this._browserWindow && this._isVisible) {
|
|
604
|
+
return [2, this.hideWindow()];
|
|
605
|
+
}
|
|
606
|
+
this._cachedBounds = bounds || this._cachedBounds;
|
|
607
|
+
return [4, this.showWindow(this._cachedBounds)];
|
|
608
|
+
case 1:
|
|
609
|
+
_a2.sent();
|
|
610
|
+
return [
|
|
611
|
+
2
|
|
612
|
+
/*return*/
|
|
613
|
+
];
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
});
|
|
617
|
+
};
|
|
618
|
+
Menubar2.prototype.createWindow = function() {
|
|
619
|
+
return __awaiter(this, void 0, void 0, function() {
|
|
620
|
+
var defaults;
|
|
621
|
+
var _this = this;
|
|
622
|
+
return __generator(this, function(_a2) {
|
|
623
|
+
switch (_a2.label) {
|
|
624
|
+
case 0:
|
|
625
|
+
this.emit("create-window");
|
|
626
|
+
defaults = {
|
|
627
|
+
show: false,
|
|
628
|
+
frame: false
|
|
629
|
+
// Remove window frame
|
|
630
|
+
};
|
|
631
|
+
this._browserWindow = new electron_1.BrowserWindow(__assign(__assign({}, defaults), this._options.browserWindow));
|
|
632
|
+
this._positioner = new electron_positioner_1.default(this._browserWindow);
|
|
633
|
+
this._browserWindow.on("blur", function() {
|
|
634
|
+
if (!_this._browserWindow) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
_this._browserWindow.isAlwaysOnTop() ? _this.emit("focus-lost") : _this._blurTimeout = setTimeout(function() {
|
|
638
|
+
_this.hideWindow();
|
|
639
|
+
}, 100);
|
|
640
|
+
});
|
|
641
|
+
if (this._options.showOnAllWorkspaces !== false) {
|
|
642
|
+
this._browserWindow.setVisibleOnAllWorkspaces(true, {
|
|
643
|
+
skipTransformProcessType: true
|
|
644
|
+
// Avoid damaging the original visible state of app.dock
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
this._browserWindow.on("close", this.windowClear.bind(this));
|
|
648
|
+
this.emit("before-load");
|
|
649
|
+
if (!(this._options.index !== false)) return [3, 2];
|
|
650
|
+
return [4, this._browserWindow.loadURL(this._options.index, this._options.loadUrlOptions)];
|
|
651
|
+
case 1:
|
|
652
|
+
_a2.sent();
|
|
653
|
+
_a2.label = 2;
|
|
654
|
+
case 2:
|
|
655
|
+
this.emit("after-create-window");
|
|
656
|
+
return [
|
|
657
|
+
2
|
|
658
|
+
/*return*/
|
|
659
|
+
];
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
});
|
|
663
|
+
};
|
|
664
|
+
Menubar2.prototype.windowClear = function() {
|
|
665
|
+
this._browserWindow = void 0;
|
|
666
|
+
this.emit("after-close");
|
|
667
|
+
};
|
|
668
|
+
return Menubar2;
|
|
669
|
+
})(events_1.EventEmitter)
|
|
670
|
+
);
|
|
671
|
+
exports2.Menubar = Menubar;
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
// ../../node_modules/.pnpm/menubar@9.5.3_electron@38.8.6/node_modules/menubar/lib/index.js
|
|
676
|
+
var require_lib = __commonJS({
|
|
677
|
+
"../../node_modules/.pnpm/menubar@9.5.3_electron@38.8.6/node_modules/menubar/lib/index.js"(exports2) {
|
|
678
|
+
"use strict";
|
|
679
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
680
|
+
if (k2 === void 0) k2 = k;
|
|
681
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
682
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
683
|
+
desc = { enumerable: true, get: function() {
|
|
684
|
+
return m[k];
|
|
685
|
+
} };
|
|
686
|
+
}
|
|
687
|
+
Object.defineProperty(o, k2, desc);
|
|
688
|
+
}) : (function(o, m, k, k2) {
|
|
689
|
+
if (k2 === void 0) k2 = k;
|
|
690
|
+
o[k2] = m[k];
|
|
691
|
+
}));
|
|
692
|
+
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
693
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
694
|
+
};
|
|
695
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
696
|
+
exports2.menubar = exports2.Menubar = void 0;
|
|
697
|
+
var electron_1 = require("electron");
|
|
698
|
+
var Menubar_1 = require_Menubar();
|
|
699
|
+
Object.defineProperty(exports2, "Menubar", { enumerable: true, get: function() {
|
|
700
|
+
return Menubar_1.Menubar;
|
|
701
|
+
} });
|
|
702
|
+
__exportStar(require_getWindowPosition(), exports2);
|
|
703
|
+
function menubar2(options) {
|
|
704
|
+
return new Menubar_1.Menubar(electron_1.app, options);
|
|
705
|
+
}
|
|
706
|
+
exports2.menubar = menubar2;
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
|
|
25
710
|
// src/main.ts
|
|
26
711
|
var import_electron = require("electron");
|
|
27
712
|
var import_node_fs9 = __toESM(require("node:fs"));
|
|
28
713
|
var import_node_os7 = __toESM(require("node:os"));
|
|
29
714
|
var import_node_path11 = __toESM(require("node:path"));
|
|
30
715
|
var import_node_child_process4 = require("node:child_process");
|
|
31
|
-
var import_menubar =
|
|
716
|
+
var import_menubar = __toESM(require_lib());
|
|
32
717
|
|
|
33
718
|
// ../shared/src/usage.ts
|
|
34
719
|
function emptyUsage() {
|
|
@@ -1042,7 +1727,17 @@ var import_node_events = require("node:events");
|
|
|
1042
1727
|
var import_node_fs = __toESM(require("node:fs"));
|
|
1043
1728
|
var import_node_os = __toESM(require("node:os"));
|
|
1044
1729
|
var import_node_path = __toESM(require("node:path"));
|
|
1045
|
-
|
|
1730
|
+
|
|
1731
|
+
// src/version.ts
|
|
1732
|
+
var APP_VERSION = true ? "0.2.2" : "0.0.0-dev";
|
|
1733
|
+
var APP_CHANNEL = true ? "prod" : "dev";
|
|
1734
|
+
var IS_DEV_BUILD = APP_CHANNEL === "dev";
|
|
1735
|
+
var APP_NAME = IS_DEV_BUILD ? "Codex Tracker (dev)" : "Codex Tracker";
|
|
1736
|
+
|
|
1737
|
+
// src/core/config.ts
|
|
1738
|
+
var PROD_DASHBOARD_URL = "https://codex.chenli.dev";
|
|
1739
|
+
var DEV_DASHBOARD_URL = "http://localhost:3000";
|
|
1740
|
+
var DEFAULT_DASHBOARD_URL = IS_DEV_BUILD ? DEV_DASHBOARD_URL : PROD_DASHBOARD_URL;
|
|
1046
1741
|
var SOURCE_FORMATS = ["codex", "pi", "generic", "opencode", "cline"];
|
|
1047
1742
|
var DEFAULT_SOURCES = { codex: true, pi: true, hermes: true, opencode: true, cline: true, roo: true, kilo: true };
|
|
1048
1743
|
var SOURCE_IDS = Object.keys(DEFAULT_SOURCES);
|
|
@@ -1062,10 +1757,11 @@ var DEFAULT_CONFIG = {
|
|
|
1062
1757
|
trackAllProviders: false,
|
|
1063
1758
|
liveRateLimits: true,
|
|
1064
1759
|
usageRefreshSec: 60,
|
|
1065
|
-
|
|
1760
|
+
// a dev build must never offer to replace itself with the published package
|
|
1761
|
+
checkUpdates: !IS_DEV_BUILD
|
|
1066
1762
|
};
|
|
1067
1763
|
function configDir() {
|
|
1068
|
-
return process.env.CODEX_TRACKER_HOME || import_node_path.default.join(import_node_os.default.homedir(), ".codex-tracker");
|
|
1764
|
+
return process.env.CODEX_TRACKER_HOME || import_node_path.default.join(import_node_os.default.homedir(), IS_DEV_BUILD ? ".codex-tracker-dev" : ".codex-tracker");
|
|
1069
1765
|
}
|
|
1070
1766
|
function readJson(file, fallback) {
|
|
1071
1767
|
try {
|
|
@@ -1116,7 +1812,7 @@ function loadConfig() {
|
|
|
1116
1812
|
cfg.sources = normalizeSources(stored.sources);
|
|
1117
1813
|
cfg.trackAllProviders = stored.trackAllProviders === true;
|
|
1118
1814
|
cfg.liveRateLimits = stored.liveRateLimits !== false;
|
|
1119
|
-
cfg.checkUpdates = stored.checkUpdates
|
|
1815
|
+
cfg.checkUpdates = typeof stored.checkUpdates === "boolean" ? stored.checkUpdates : DEFAULT_CONFIG.checkUpdates;
|
|
1120
1816
|
if (!(cfg.usageRefreshSec >= 15)) cfg.usageRefreshSec = DEFAULT_CONFIG.usageRefreshSec;
|
|
1121
1817
|
if (!["auto", "en", "zh"].includes(cfg.language)) cfg.language = "auto";
|
|
1122
1818
|
if (!(cfg.uploadIntervalSec >= 10)) cfg.uploadIntervalSec = DEFAULT_CONFIG.uploadIntervalSec;
|
|
@@ -1230,6 +1926,7 @@ var en = {
|
|
|
1230
1926
|
estimatedPricingHint: "Pricing estimated: model not in the price table",
|
|
1231
1927
|
other: "Other",
|
|
1232
1928
|
lastUpload: "Last upload {time}",
|
|
1929
|
+
lastSync: "Last full sync {time}",
|
|
1233
1930
|
neverUploaded: "Not uploaded yet",
|
|
1234
1931
|
uploadError: "Upload error: {message}",
|
|
1235
1932
|
allDevicesToday: "All devices today",
|
|
@@ -1248,10 +1945,26 @@ var en = {
|
|
|
1248
1945
|
launchAtLogin: "Launch at login",
|
|
1249
1946
|
refresh: "Refresh",
|
|
1250
1947
|
quit: "Quit",
|
|
1948
|
+
// full sync
|
|
1949
|
+
syncNow: "Sync now",
|
|
1950
|
+
syncing: "Syncing\u2026",
|
|
1951
|
+
syncTitle: "Rescan every agent on this device and re-upload its full usage history",
|
|
1952
|
+
syncScanning: "Rescanning every agent's transcripts\u2026",
|
|
1953
|
+
syncComputing: "Recomputing token usage\u2026",
|
|
1954
|
+
syncUploading: "Re-uploading this device's history\u2026",
|
|
1955
|
+
syncDownloading: "Fetching other devices\u2026",
|
|
1956
|
+
syncLimits: "Refreshing rate limits\u2026",
|
|
1957
|
+
syncDone: "Synced {agents} \xB7 {files} files \xB7 {sessions} sessions \xB7 {buckets} hours re-uploaded",
|
|
1958
|
+
syncDoneLocal: "Rescanned {agents} \xB7 {files} files \xB7 {sessions} sessions \u2014 sign in to upload",
|
|
1959
|
+
syncFailed: "Sync failed: {message}",
|
|
1251
1960
|
sessions: "{n} sessions",
|
|
1252
1961
|
files: "{n} files",
|
|
1253
1962
|
noData: "No usage found yet. Run Codex and this will fill in.",
|
|
1254
1963
|
version: "v{version}",
|
|
1964
|
+
// dev builds
|
|
1965
|
+
devBuild: "DEV",
|
|
1966
|
+
devBuildTitle: "Local build \u2014 uploading to {url} (dev environment). Config: {dir}",
|
|
1967
|
+
devBuildMenu: "Dev build \u2192 {url}",
|
|
1255
1968
|
justNow: "just now",
|
|
1256
1969
|
never: "never",
|
|
1257
1970
|
local: "Local",
|
|
@@ -1279,6 +1992,7 @@ Commands:
|
|
|
1279
1992
|
login Connect this device to your dashboard (--dashboard <url>)
|
|
1280
1993
|
logout Disconnect this device
|
|
1281
1994
|
status Print today's usage, live session and rate limits
|
|
1995
|
+
sync Rescan every agent and re-upload this device's full history (calibrate)
|
|
1282
1996
|
paths Show detected session directories (Codex, pi, OpenCode, Cline/Roo/Kilo, Hermes, custom)
|
|
1283
1997
|
update Install the newest published version (--check only reports)
|
|
1284
1998
|
config get|set Read or change settings (config set uploadIntervalSec 30, config set sources.pi false)
|
|
@@ -1293,9 +2007,9 @@ Options:
|
|
|
1293
2007
|
cliVersion: "codex-token-tracker {version}",
|
|
1294
2008
|
cliUnknownCommand: "Unknown command: {command}",
|
|
1295
2009
|
cliNoDisplay: "No display detected \u2014 starting agent mode (run `codex-tracker menubar` on a desktop).",
|
|
1296
|
-
cliNoElectron: "Electron
|
|
2010
|
+
cliNoElectron: "No Electron runtime available \u2014 starting agent mode.",
|
|
1297
2011
|
cliDownloadingElectron: "Electron runtime not found \u2014 downloading it now (about 100 MB, one time)\u2026",
|
|
1298
|
-
cliElectronDownloadFailed: "Electron download failed.
|
|
2012
|
+
cliElectronDownloadFailed: "Electron download failed. Check the network (set ELECTRON_MIRROR, e.g. https://npmmirror.com/mirrors/electron/, or HTTPS_PROXY) and run `codex-tracker menubar` again; the headless `codex-tracker agent` works without Electron.",
|
|
1299
2013
|
cliStartingMenubar: "Starting menu bar app\u2026",
|
|
1300
2014
|
cliLoginStart: "Connecting this device to {dashboard}",
|
|
1301
2015
|
cliLoginCode: "Your code: {code}",
|
|
@@ -1333,7 +2047,15 @@ Options:
|
|
|
1333
2047
|
cliUpdateRunning: "Running: {command}",
|
|
1334
2048
|
cliUpdateDone: "Updated to {version}. Restart the menu bar app (or rerun the CLI) to use it.",
|
|
1335
2049
|
cliUpdateFailed: "Update failed (exit {code}). Run it yourself: {command}",
|
|
1336
|
-
cliUpdateCheckFailed: "Could not reach the npm registry: {message}"
|
|
2050
|
+
cliUpdateCheckFailed: "Could not reach the npm registry: {message}",
|
|
2051
|
+
cliSyncStart: "Full sync: rescanning every agent on this device\u2026",
|
|
2052
|
+
cliSyncScanned: " scanned {files} files in {roots} directories ({agents})",
|
|
2053
|
+
cliSyncUploaded: " re-uploaded {buckets} hour buckets and {sessions} sessions",
|
|
2054
|
+
cliSyncLocal: " not signed in \u2014 nothing uploaded (run `codex-tracker login` first)",
|
|
2055
|
+
cliSyncDone: "Sync complete in {seconds}s \u2014 {sessions} sessions, today {tokens} tok \xB7 {cost}",
|
|
2056
|
+
cliSyncFailed: "Sync failed: {message}",
|
|
2057
|
+
cliChannelDev: "Dev build \u2014 dashboard {url} \xB7 config {dir}",
|
|
2058
|
+
cliUpdateDevBuild: "This is a local dev build; `update` would install the published package over it. Run `pnpm build` in the repo instead."
|
|
1337
2059
|
};
|
|
1338
2060
|
|
|
1339
2061
|
// src/i18n/zh.ts
|
|
@@ -1381,6 +2103,7 @@ var zh = {
|
|
|
1381
2103
|
estimatedPricingHint: "\u4EF7\u683C\u4E3A\u4F30\u7B97\u503C\uFF1A\u8BE5\u6A21\u578B\u4E0D\u5728\u4EF7\u76EE\u8868\u4E2D",
|
|
1382
2104
|
other: "\u5176\u4ED6",
|
|
1383
2105
|
lastUpload: "\u4E0A\u6B21\u4E0A\u4F20 {time}",
|
|
2106
|
+
lastSync: "\u4E0A\u6B21\u5B8C\u6574\u540C\u6B65 {time}",
|
|
1384
2107
|
neverUploaded: "\u5C1A\u672A\u4E0A\u4F20",
|
|
1385
2108
|
uploadError: "\u4E0A\u4F20\u5931\u8D25\uFF1A{message}",
|
|
1386
2109
|
allDevicesToday: "\u6240\u6709\u8BBE\u5907\u4ECA\u65E5",
|
|
@@ -1399,10 +2122,26 @@ var zh = {
|
|
|
1399
2122
|
launchAtLogin: "\u5F00\u673A\u81EA\u542F\u52A8",
|
|
1400
2123
|
refresh: "\u5237\u65B0",
|
|
1401
2124
|
quit: "\u9000\u51FA",
|
|
2125
|
+
// 完整同步
|
|
2126
|
+
syncNow: "\u7ACB\u5373\u540C\u6B65",
|
|
2127
|
+
syncing: "\u540C\u6B65\u4E2D\u2026",
|
|
2128
|
+
syncTitle: "\u91CD\u65B0\u626B\u63CF\u672C\u8BBE\u5907\u4E0A\u7684\u6240\u6709\u667A\u80FD\u4F53\uFF0C\u5E76\u91CD\u65B0\u4E0A\u4F20\u5B8C\u6574\u7528\u91CF\u5386\u53F2",
|
|
2129
|
+
syncScanning: "\u6B63\u5728\u91CD\u65B0\u626B\u63CF\u6240\u6709\u667A\u80FD\u4F53\u7684\u4F1A\u8BDD\u8BB0\u5F55\u2026",
|
|
2130
|
+
syncComputing: "\u6B63\u5728\u91CD\u65B0\u8BA1\u7B97 token \u7528\u91CF\u2026",
|
|
2131
|
+
syncUploading: "\u6B63\u5728\u91CD\u65B0\u4E0A\u4F20\u672C\u8BBE\u5907\u7684\u5386\u53F2\u6570\u636E\u2026",
|
|
2132
|
+
syncDownloading: "\u6B63\u5728\u62C9\u53D6\u5176\u4ED6\u8BBE\u5907\u7684\u6570\u636E\u2026",
|
|
2133
|
+
syncLimits: "\u6B63\u5728\u5237\u65B0\u9650\u989D\u2026",
|
|
2134
|
+
syncDone: "\u5DF2\u540C\u6B65 {agents} \xB7 {files} \u4E2A\u6587\u4EF6 \xB7 {sessions} \u4E2A\u4F1A\u8BDD \xB7 \u91CD\u65B0\u4E0A\u4F20 {buckets} \u4E2A\u5C0F\u65F6\u6BB5",
|
|
2135
|
+
syncDoneLocal: "\u5DF2\u91CD\u65B0\u626B\u63CF {agents} \xB7 {files} \u4E2A\u6587\u4EF6 \xB7 {sessions} \u4E2A\u4F1A\u8BDD \u2014 \u767B\u5F55\u540E\u53EF\u4E0A\u4F20",
|
|
2136
|
+
syncFailed: "\u540C\u6B65\u5931\u8D25\uFF1A{message}",
|
|
1402
2137
|
sessions: "{n} \u4E2A\u4F1A\u8BDD",
|
|
1403
2138
|
files: "{n} \u4E2A\u6587\u4EF6",
|
|
1404
2139
|
noData: "\u8FD8\u6CA1\u6709\u7528\u91CF\u6570\u636E\u3002\u8FD0\u884C Codex \u540E\u8FD9\u91CC\u4F1A\u81EA\u52A8\u66F4\u65B0\u3002",
|
|
1405
2140
|
version: "v{version}",
|
|
2141
|
+
// 开发版
|
|
2142
|
+
devBuild: "\u5F00\u53D1\u7248",
|
|
2143
|
+
devBuildTitle: "\u672C\u5730\u6784\u5EFA \u2014\u2014 \u6570\u636E\u4E0A\u4F20\u81F3 {url}\uFF08\u5F00\u53D1\u73AF\u5883\uFF09\u3002\u914D\u7F6E\u76EE\u5F55\uFF1A{dir}",
|
|
2144
|
+
devBuildMenu: "\u5F00\u53D1\u7248 \u2192 {url}",
|
|
1406
2145
|
justNow: "\u521A\u521A",
|
|
1407
2146
|
never: "\u4ECE\u672A",
|
|
1408
2147
|
local: "\u672C\u673A",
|
|
@@ -1428,6 +2167,7 @@ var zh = {
|
|
|
1428
2167
|
login \u5C06\u672C\u8BBE\u5907\u8FDE\u63A5\u5230\u4EEA\u8868\u76D8\uFF08--dashboard <url>\uFF09
|
|
1429
2168
|
logout \u65AD\u5F00\u672C\u8BBE\u5907
|
|
1430
2169
|
status \u6253\u5370\u4ECA\u65E5\u7528\u91CF\u3001\u5B9E\u65F6\u4F1A\u8BDD\u4E0E\u9650\u989D
|
|
2170
|
+
sync \u91CD\u65B0\u626B\u63CF\u6240\u6709\u667A\u80FD\u4F53\u5E76\u91CD\u65B0\u4E0A\u4F20\u672C\u8BBE\u5907\u5B8C\u6574\u5386\u53F2\uFF08\u6821\u51C6\uFF09
|
|
1431
2171
|
paths \u663E\u793A\u68C0\u6D4B\u5230\u7684\u4F1A\u8BDD\u76EE\u5F55\uFF08Codex\u3001pi\u3001OpenCode\u3001Cline/Roo/Kilo\u3001Hermes\u3001\u81EA\u5B9A\u4E49\uFF09
|
|
1432
2172
|
update \u5B89\u88C5\u6700\u65B0\u53D1\u5E03\u7248\u672C\uFF08--check \u53EA\u68C0\u67E5\u4E0D\u5B89\u88C5\uFF09
|
|
1433
2173
|
config get|set \u8BFB\u53D6\u6216\u4FEE\u6539\u8BBE\u7F6E\uFF08config set uploadIntervalSec 30\uFF0Cconfig set sources.pi false\uFF09
|
|
@@ -1442,9 +2182,9 @@ var zh = {
|
|
|
1442
2182
|
cliVersion: "codex-token-tracker {version}",
|
|
1443
2183
|
cliUnknownCommand: "\u672A\u77E5\u547D\u4EE4\uFF1A{command}",
|
|
1444
2184
|
cliNoDisplay: "\u672A\u68C0\u6D4B\u5230\u663E\u793A\u73AF\u5883 \u2014 \u4EE5 agent \u6A21\u5F0F\u542F\u52A8\uFF08\u684C\u9762\u73AF\u5883\u8BF7\u8FD0\u884C `codex-tracker menubar`\uFF09\u3002",
|
|
1445
|
-
cliNoElectron: "\
|
|
2185
|
+
cliNoElectron: "\u6CA1\u6709\u53EF\u7528\u7684 Electron \u8FD0\u884C\u65F6 \u2014 \u4EE5 agent \u6A21\u5F0F\u542F\u52A8\u3002",
|
|
1446
2186
|
cliDownloadingElectron: "\u672A\u627E\u5230 Electron \u8FD0\u884C\u65F6\uFF0C\u6B63\u5728\u4E0B\u8F7D\uFF08\u7EA6 100 MB\uFF0C\u4EC5\u9700\u4E00\u6B21\uFF09\u2026",
|
|
1447
|
-
cliElectronDownloadFailed: "Electron \u4E0B\u8F7D\u5931\u8D25\u3002\u53EF\
|
|
2187
|
+
cliElectronDownloadFailed: "Electron \u4E0B\u8F7D\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\u7F51\u7EDC\uFF08\u53EF\u8BBE\u7F6E ELECTRON_MIRROR\uFF0C\u4F8B\u5982 https://npmmirror.com/mirrors/electron/\uFF0C\u6216 HTTPS_PROXY\uFF09\u540E\u518D\u6B21\u8FD0\u884C `codex-tracker menubar`\uFF1B\u65E0\u754C\u9762\u7684 `codex-tracker agent` \u65E0\u9700 Electron\u3002",
|
|
1448
2188
|
cliStartingMenubar: "\u6B63\u5728\u542F\u52A8\u83DC\u5355\u680F\u5E94\u7528\u2026",
|
|
1449
2189
|
cliLoginStart: "\u6B63\u5728\u5C06\u672C\u8BBE\u5907\u8FDE\u63A5\u5230 {dashboard}",
|
|
1450
2190
|
cliLoginCode: "\u4F60\u7684\u4EE3\u7801\uFF1A{code}",
|
|
@@ -1482,7 +2222,15 @@ var zh = {
|
|
|
1482
2222
|
cliUpdateRunning: "\u6B63\u5728\u6267\u884C\uFF1A{command}",
|
|
1483
2223
|
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",
|
|
1484
2224
|
cliUpdateFailed: "\u66F4\u65B0\u5931\u8D25\uFF08\u9000\u51FA\u7801 {code}\uFF09\u3002\u8BF7\u624B\u52A8\u6267\u884C\uFF1A{command}",
|
|
1485
|
-
cliUpdateCheckFailed: "\u65E0\u6CD5\u8BBF\u95EE npm registry\uFF1A{message}"
|
|
2225
|
+
cliUpdateCheckFailed: "\u65E0\u6CD5\u8BBF\u95EE npm registry\uFF1A{message}",
|
|
2226
|
+
cliSyncStart: "\u5B8C\u6574\u540C\u6B65\uFF1A\u6B63\u5728\u91CD\u65B0\u626B\u63CF\u672C\u8BBE\u5907\u4E0A\u7684\u6240\u6709\u667A\u80FD\u4F53\u2026",
|
|
2227
|
+
cliSyncScanned: " \u5DF2\u626B\u63CF {roots} \u4E2A\u76EE\u5F55\u4E2D\u7684 {files} \u4E2A\u6587\u4EF6\uFF08{agents}\uFF09",
|
|
2228
|
+
cliSyncUploaded: " \u5DF2\u91CD\u65B0\u4E0A\u4F20 {buckets} \u4E2A\u5C0F\u65F6\u6BB5\u4E0E {sessions} \u4E2A\u4F1A\u8BDD",
|
|
2229
|
+
cliSyncLocal: " \u672A\u767B\u5F55 \u2014 \u6CA1\u6709\u4E0A\u4F20\u4EFB\u4F55\u6570\u636E\uFF08\u8BF7\u5148\u8FD0\u884C `codex-tracker login`\uFF09",
|
|
2230
|
+
cliSyncDone: "\u540C\u6B65\u5B8C\u6210\uFF0C\u7528\u65F6 {seconds} \u79D2 \u2014 {sessions} \u4E2A\u4F1A\u8BDD\uFF0C\u4ECA\u65E5 {tokens} tok \xB7 {cost}",
|
|
2231
|
+
cliSyncFailed: "\u540C\u6B65\u5931\u8D25\uFF1A{message}",
|
|
2232
|
+
cliChannelDev: "\u5F00\u53D1\u7248 \u2014\u2014 \u4EEA\u8868\u76D8 {url} \xB7 \u914D\u7F6E\u76EE\u5F55 {dir}",
|
|
2233
|
+
cliUpdateDevBuild: "\u8FD9\u662F\u672C\u5730\u5F00\u53D1\u7248\uFF1B`update` \u4F1A\u7528\u5DF2\u53D1\u5E03\u7684\u5305\u8986\u76D6\u5B83\u3002\u8BF7\u6539\u4E3A\u5728\u4ED3\u5E93\u4E2D\u8FD0\u884C `pnpm build`\u3002"
|
|
1486
2234
|
};
|
|
1487
2235
|
|
|
1488
2236
|
// src/i18n/index.ts
|
|
@@ -2289,6 +3037,15 @@ var SessionStore = class {
|
|
|
2289
3037
|
onChange = null;
|
|
2290
3038
|
debounceTimer = null;
|
|
2291
3039
|
sessionCache = null;
|
|
3040
|
+
/**
|
|
3041
|
+
* Forget the parsed-file index so the next deep refresh re-reads and re-parses every transcript.
|
|
3042
|
+
* Used by the full sync: files are otherwise skipped while their size and mtime are unchanged, which
|
|
3043
|
+
* would keep stale numbers around after a parser or pricing change.
|
|
3044
|
+
*/
|
|
3045
|
+
reset() {
|
|
3046
|
+
this.files.clear();
|
|
3047
|
+
this.sessionCache = null;
|
|
3048
|
+
}
|
|
2292
3049
|
async refreshDeep() {
|
|
2293
3050
|
const o = this.getOptions();
|
|
2294
3051
|
this.roots = discoverSessionRoots({ extraSessionDirs: o.extraSessionDirs, sources: o.sources });
|
|
@@ -4086,7 +4843,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require2 !== "undefined" ? requir
|
|
|
4086
4843
|
if (typeof require2 !== "undefined") return require2.apply(this, arguments);
|
|
4087
4844
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
4088
4845
|
});
|
|
4089
|
-
var
|
|
4846
|
+
var __commonJS2 = (cb, mod) => function __require2() {
|
|
4090
4847
|
return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
4091
4848
|
};
|
|
4092
4849
|
var __copyProps2 = (to, from, except, desc) => {
|
|
@@ -4105,7 +4862,7 @@ var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__
|
|
|
4105
4862
|
isNodeMode || !mod || !mod.__esModule ? __defProp6(target, "default", { value: mod, enumerable: true }) : target,
|
|
4106
4863
|
mod
|
|
4107
4864
|
));
|
|
4108
|
-
var require_constants =
|
|
4865
|
+
var require_constants = __commonJS2({
|
|
4109
4866
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/constants.js"(exports2, module2) {
|
|
4110
4867
|
"use strict";
|
|
4111
4868
|
var BINARY_TYPES = ["nodebuffer", "arraybuffer", "fragments"];
|
|
@@ -4126,7 +4883,7 @@ var require_constants = __commonJS({
|
|
|
4126
4883
|
};
|
|
4127
4884
|
}
|
|
4128
4885
|
});
|
|
4129
|
-
var require_node_gyp_build =
|
|
4886
|
+
var require_node_gyp_build = __commonJS2({
|
|
4130
4887
|
"../node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/node-gyp-build.js"(exports2, module2) {
|
|
4131
4888
|
var fs10 = __require("fs");
|
|
4132
4889
|
var path12 = __require("path");
|
|
@@ -4293,7 +5050,7 @@ var require_node_gyp_build = __commonJS({
|
|
|
4293
5050
|
load.compareTuples = compareTuples;
|
|
4294
5051
|
}
|
|
4295
5052
|
});
|
|
4296
|
-
var require_node_gyp_build2 =
|
|
5053
|
+
var require_node_gyp_build2 = __commonJS2({
|
|
4297
5054
|
"../node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/index.js"(exports2, module2) {
|
|
4298
5055
|
var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
4299
5056
|
if (typeof runtimeRequire.addon === "function") {
|
|
@@ -4303,7 +5060,7 @@ var require_node_gyp_build2 = __commonJS({
|
|
|
4303
5060
|
}
|
|
4304
5061
|
}
|
|
4305
5062
|
});
|
|
4306
|
-
var require_fallback =
|
|
5063
|
+
var require_fallback = __commonJS2({
|
|
4307
5064
|
"../node_modules/.pnpm/bufferutil@4.0.9/node_modules/bufferutil/fallback.js"(exports2, module2) {
|
|
4308
5065
|
"use strict";
|
|
4309
5066
|
var mask = (source, mask2, output, offset, length) => {
|
|
@@ -4320,7 +5077,7 @@ var require_fallback = __commonJS({
|
|
|
4320
5077
|
module2.exports = { mask, unmask };
|
|
4321
5078
|
}
|
|
4322
5079
|
});
|
|
4323
|
-
var require_bufferutil =
|
|
5080
|
+
var require_bufferutil = __commonJS2({
|
|
4324
5081
|
"../node_modules/.pnpm/bufferutil@4.0.9/node_modules/bufferutil/index.js"(exports2, module2) {
|
|
4325
5082
|
"use strict";
|
|
4326
5083
|
try {
|
|
@@ -4330,7 +5087,7 @@ var require_bufferutil = __commonJS({
|
|
|
4330
5087
|
}
|
|
4331
5088
|
}
|
|
4332
5089
|
});
|
|
4333
|
-
var require_buffer_util =
|
|
5090
|
+
var require_buffer_util = __commonJS2({
|
|
4334
5091
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/buffer-util.js"(exports2, module2) {
|
|
4335
5092
|
"use strict";
|
|
4336
5093
|
var { EMPTY_BUFFER } = require_constants();
|
|
@@ -4403,7 +5160,7 @@ var require_buffer_util = __commonJS({
|
|
|
4403
5160
|
}
|
|
4404
5161
|
}
|
|
4405
5162
|
});
|
|
4406
|
-
var require_limiter =
|
|
5163
|
+
var require_limiter = __commonJS2({
|
|
4407
5164
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/limiter.js"(exports2, module2) {
|
|
4408
5165
|
"use strict";
|
|
4409
5166
|
var kDone = /* @__PURE__ */ Symbol("kDone");
|
|
@@ -4451,7 +5208,7 @@ var require_limiter = __commonJS({
|
|
|
4451
5208
|
module2.exports = Limiter;
|
|
4452
5209
|
}
|
|
4453
5210
|
});
|
|
4454
|
-
var require_permessage_deflate =
|
|
5211
|
+
var require_permessage_deflate = __commonJS2({
|
|
4455
5212
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/permessage-deflate.js"(exports2, module2) {
|
|
4456
5213
|
"use strict";
|
|
4457
5214
|
var zlib = __require("zlib");
|
|
@@ -4832,7 +5589,7 @@ var require_permessage_deflate = __commonJS({
|
|
|
4832
5589
|
}
|
|
4833
5590
|
}
|
|
4834
5591
|
});
|
|
4835
|
-
var require_validation =
|
|
5592
|
+
var require_validation = __commonJS2({
|
|
4836
5593
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/validation.js"(exports2, module2) {
|
|
4837
5594
|
"use strict";
|
|
4838
5595
|
var { isUtf8 } = __require("buffer");
|
|
@@ -5031,7 +5788,7 @@ var require_validation = __commonJS({
|
|
|
5031
5788
|
}
|
|
5032
5789
|
}
|
|
5033
5790
|
});
|
|
5034
|
-
var require_receiver =
|
|
5791
|
+
var require_receiver = __commonJS2({
|
|
5035
5792
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/receiver.js"(exports2, module2) {
|
|
5036
5793
|
"use strict";
|
|
5037
5794
|
var { Writable } = __require("stream");
|
|
@@ -5661,7 +6418,7 @@ var require_receiver = __commonJS({
|
|
|
5661
6418
|
module2.exports = Receiver2;
|
|
5662
6419
|
}
|
|
5663
6420
|
});
|
|
5664
|
-
var require_sender =
|
|
6421
|
+
var require_sender = __commonJS2({
|
|
5665
6422
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/sender.js"(exports2, module2) {
|
|
5666
6423
|
"use strict";
|
|
5667
6424
|
var { Duplex } = __require("stream");
|
|
@@ -6152,7 +6909,7 @@ var require_sender = __commonJS({
|
|
|
6152
6909
|
}
|
|
6153
6910
|
}
|
|
6154
6911
|
});
|
|
6155
|
-
var require_event_target =
|
|
6912
|
+
var require_event_target = __commonJS2({
|
|
6156
6913
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/event-target.js"(exports2, module2) {
|
|
6157
6914
|
"use strict";
|
|
6158
6915
|
var { kForOnEventAttribute, kListener } = require_constants();
|
|
@@ -6379,7 +7136,7 @@ var require_event_target = __commonJS({
|
|
|
6379
7136
|
}
|
|
6380
7137
|
}
|
|
6381
7138
|
});
|
|
6382
|
-
var require_extension =
|
|
7139
|
+
var require_extension = __commonJS2({
|
|
6383
7140
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/extension.js"(exports2, module2) {
|
|
6384
7141
|
"use strict";
|
|
6385
7142
|
var { tokenChars } = require_validation();
|
|
@@ -6530,7 +7287,7 @@ var require_extension = __commonJS({
|
|
|
6530
7287
|
module2.exports = { format, parse };
|
|
6531
7288
|
}
|
|
6532
7289
|
});
|
|
6533
|
-
var require_websocket =
|
|
7290
|
+
var require_websocket = __commonJS2({
|
|
6534
7291
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/websocket.js"(exports2, module2) {
|
|
6535
7292
|
"use strict";
|
|
6536
7293
|
var EventEmitter2 = __require("events");
|
|
@@ -7424,7 +8181,7 @@ var require_websocket = __commonJS({
|
|
|
7424
8181
|
}
|
|
7425
8182
|
}
|
|
7426
8183
|
});
|
|
7427
|
-
var require_stream =
|
|
8184
|
+
var require_stream = __commonJS2({
|
|
7428
8185
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/stream.js"(exports2, module2) {
|
|
7429
8186
|
"use strict";
|
|
7430
8187
|
var WebSocket2 = require_websocket();
|
|
@@ -7520,7 +8277,7 @@ var require_stream = __commonJS({
|
|
|
7520
8277
|
module2.exports = createWebSocketStream2;
|
|
7521
8278
|
}
|
|
7522
8279
|
});
|
|
7523
|
-
var require_subprotocol =
|
|
8280
|
+
var require_subprotocol = __commonJS2({
|
|
7524
8281
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/subprotocol.js"(exports2, module2) {
|
|
7525
8282
|
"use strict";
|
|
7526
8283
|
var { tokenChars } = require_validation();
|
|
@@ -7563,7 +8320,7 @@ var require_subprotocol = __commonJS({
|
|
|
7563
8320
|
module2.exports = { parse };
|
|
7564
8321
|
}
|
|
7565
8322
|
});
|
|
7566
|
-
var require_websocket_server =
|
|
8323
|
+
var require_websocket_server = __commonJS2({
|
|
7567
8324
|
"../node_modules/.pnpm/ws@8.21.0_bufferutil@4.0.9/node_modules/ws/lib/websocket-server.js"(exports2, module2) {
|
|
7568
8325
|
"use strict";
|
|
7569
8326
|
var EventEmitter2 = __require("events");
|
|
@@ -8847,11 +9604,25 @@ var Uploader = class {
|
|
|
8847
9604
|
throw err;
|
|
8848
9605
|
}
|
|
8849
9606
|
}
|
|
8850
|
-
/**
|
|
8851
|
-
async
|
|
9607
|
+
/** Wait for an in-flight incremental push to finish so a full sync isn't skipped by the guard. */
|
|
9608
|
+
async awaitIdle(timeoutMs = 15e3) {
|
|
9609
|
+
const deadline = Date.now() + timeoutMs;
|
|
9610
|
+
while (this.inFlight && Date.now() < deadline) await new Promise((r) => setTimeout(r, 100));
|
|
9611
|
+
}
|
|
9612
|
+
/**
|
|
9613
|
+
* Upload changed hour buckets and session summaries. Returns counts of pushed items.
|
|
9614
|
+
* With `full`, the record of what was already pushed is dropped first so *everything* is re-sent —
|
|
9615
|
+
* that is what recalibrates this device's totals on the dashboard after a parser or pricing change.
|
|
9616
|
+
*/
|
|
9617
|
+
async pushAll(buckets, sessions, sessionCosts, opts = {}) {
|
|
9618
|
+
if (opts.full) await this.awaitIdle();
|
|
8852
9619
|
if (this.inFlight) return { buckets: 0, sessions: 0 };
|
|
8853
9620
|
this.inFlight = true;
|
|
8854
9621
|
try {
|
|
9622
|
+
if (opts.full) {
|
|
9623
|
+
this.state.pushedBuckets = {};
|
|
9624
|
+
this.state.pushedSessions = {};
|
|
9625
|
+
}
|
|
8855
9626
|
const changed = [];
|
|
8856
9627
|
const hashes = /* @__PURE__ */ new Map();
|
|
8857
9628
|
for (const b of buckets.sort((a, b2) => a.hourStart - b2.hourStart)) {
|
|
@@ -9061,13 +9832,7 @@ async function fetchLiveRateLimits(appVersion, timeoutMs = 1e4) {
|
|
|
9061
9832
|
var import_node_fs8 = __toESM(require("node:fs"));
|
|
9062
9833
|
var import_node_path10 = __toESM(require("node:path"));
|
|
9063
9834
|
var import_node_child_process3 = require("node:child_process");
|
|
9064
|
-
|
|
9065
|
-
// src/version.ts
|
|
9066
|
-
var APP_VERSION = true ? "0.2.0" : "0.0.0-dev";
|
|
9067
|
-
var APP_NAME = "Codex Tracker";
|
|
9068
|
-
|
|
9069
|
-
// src/core/update.ts
|
|
9070
|
-
var NPM_PACKAGE = "codex-token-tracker";
|
|
9835
|
+
var NPM_PACKAGE = true ? "codex-token-tracker" : "codex-token-tracker";
|
|
9071
9836
|
var CHECK_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
9072
9837
|
var REQUEST_TIMEOUT_MS = 8e3;
|
|
9073
9838
|
var INSTALL_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
@@ -9090,7 +9855,7 @@ function compareVersions(a, b) {
|
|
|
9090
9855
|
return A.pre < B.pre ? -1 : 1;
|
|
9091
9856
|
}
|
|
9092
9857
|
function isDevBuild(version2) {
|
|
9093
|
-
return version2.startsWith("0.0.0");
|
|
9858
|
+
return IS_DEV_BUILD || version2.startsWith("0.0.0");
|
|
9094
9859
|
}
|
|
9095
9860
|
function registryBase() {
|
|
9096
9861
|
const r = process.env.CODEX_TRACKER_REGISTRY || process.env.npm_config_registry || process.env.NPM_CONFIG_REGISTRY || "https://registry.npmjs.org";
|
|
@@ -9141,7 +9906,8 @@ function updateCommand(pm, spec) {
|
|
|
9141
9906
|
return `${pm} ${updateArgs(pm, spec).join(" ")}`;
|
|
9142
9907
|
}
|
|
9143
9908
|
function cachePath() {
|
|
9144
|
-
|
|
9909
|
+
const suffix = NPM_PACKAGE === "codex-token-tracker" ? "" : `-${NPM_PACKAGE}`;
|
|
9910
|
+
return import_node_path10.default.join(configDir(), `update${suffix}.json`);
|
|
9145
9911
|
}
|
|
9146
9912
|
function readCache() {
|
|
9147
9913
|
try {
|
|
@@ -9233,6 +9999,7 @@ var REMOTE_MS = 6e4;
|
|
|
9233
9999
|
var LIVE_LIMITS_DEBOUNCE_MS = 1e4;
|
|
9234
10000
|
var LIVE_LIMITS_MIN_GAP_MS = 2e4;
|
|
9235
10001
|
var UPDATE_CHECK_MS = 6 * 60 * 60 * 1e3;
|
|
10002
|
+
var SYNC_BANNER_MS = 25e3;
|
|
9236
10003
|
var Engine = class extends import_node_events.EventEmitter {
|
|
9237
10004
|
constructor(opts) {
|
|
9238
10005
|
super();
|
|
@@ -9272,6 +10039,13 @@ var Engine = class extends import_node_events.EventEmitter {
|
|
|
9272
10039
|
update = null;
|
|
9273
10040
|
updateStatus = "idle";
|
|
9274
10041
|
updateLog = null;
|
|
10042
|
+
syncStatus = "idle";
|
|
10043
|
+
syncPhase = null;
|
|
10044
|
+
syncStartedAt = null;
|
|
10045
|
+
syncFinishedAt = null;
|
|
10046
|
+
syncError = null;
|
|
10047
|
+
syncResult = null;
|
|
10048
|
+
syncBannerTimer = null;
|
|
9275
10049
|
get heatmapWeeks() {
|
|
9276
10050
|
return this.opts.heatmapWeeks ?? 16;
|
|
9277
10051
|
}
|
|
@@ -9322,6 +10096,8 @@ var Engine = class extends import_node_events.EventEmitter {
|
|
|
9322
10096
|
this.timers = [];
|
|
9323
10097
|
if (this.liveLimitsTimer) clearTimeout(this.liveLimitsTimer);
|
|
9324
10098
|
this.liveLimitsTimer = null;
|
|
10099
|
+
if (this.syncBannerTimer) clearTimeout(this.syncBannerTimer);
|
|
10100
|
+
this.syncBannerTimer = null;
|
|
9325
10101
|
this.store.stopWatching();
|
|
9326
10102
|
this.pending?.abort.abort();
|
|
9327
10103
|
}
|
|
@@ -9425,6 +10201,112 @@ var Engine = class extends import_node_events.EventEmitter {
|
|
|
9425
10201
|
await this.uploader.fetchRemote(this.heatmapWeeks);
|
|
9426
10202
|
this.recompute();
|
|
9427
10203
|
}
|
|
10204
|
+
/**
|
|
10205
|
+
* Full sync ("calibrate this device"). Unlike the periodic incremental upload this deliberately
|
|
10206
|
+
* throws away every cache on the way:
|
|
10207
|
+
* 1. re-read the config so sources enabled since start-up are picked up,
|
|
10208
|
+
* 2. drop the parsed-file index and re-discover + re-parse every transcript of every agent
|
|
10209
|
+
* (Codex plus the agents running on the Codex subscription: pi, OpenCode, Cline/Roo/Kilo,
|
|
10210
|
+
* Hermes and any custom `extraSessionDirs`),
|
|
10211
|
+
* 3. recompute the aggregates with the current pricing table,
|
|
10212
|
+
* 4. re-upload *everything* — not just what changed — so the dashboard's totals for this device
|
|
10213
|
+
* are replaced by the freshly computed ones,
|
|
10214
|
+
* 5. pull the other devices' rows and the live rate limits back down.
|
|
10215
|
+
*
|
|
10216
|
+
* Returns null when a sync is already running. Never throws: failures land in the returned state.
|
|
10217
|
+
*/
|
|
10218
|
+
async syncNow() {
|
|
10219
|
+
if (this.syncStatus === "running") return null;
|
|
10220
|
+
if (this.syncBannerTimer) {
|
|
10221
|
+
clearTimeout(this.syncBannerTimer);
|
|
10222
|
+
this.syncBannerTimer = null;
|
|
10223
|
+
}
|
|
10224
|
+
const startedAt = Date.now();
|
|
10225
|
+
this.syncStatus = "running";
|
|
10226
|
+
this.syncPhase = null;
|
|
10227
|
+
this.syncStartedAt = startedAt;
|
|
10228
|
+
this.syncFinishedAt = null;
|
|
10229
|
+
this.syncError = null;
|
|
10230
|
+
const phase = (p) => {
|
|
10231
|
+
this.syncPhase = p;
|
|
10232
|
+
this.emitSnapshot();
|
|
10233
|
+
};
|
|
10234
|
+
try {
|
|
10235
|
+
phase("scanning");
|
|
10236
|
+
this.reloadConfig();
|
|
10237
|
+
this.store.reset();
|
|
10238
|
+
await this.store.refreshDeep();
|
|
10239
|
+
phase("computing");
|
|
10240
|
+
this.recompute();
|
|
10241
|
+
let uploadedBuckets = 0;
|
|
10242
|
+
let uploadedSessions = 0;
|
|
10243
|
+
const uploaded = this.opts.upload && this.signedIn;
|
|
10244
|
+
if (uploaded) {
|
|
10245
|
+
phase("uploading");
|
|
10246
|
+
const r = await this.uploader.pushAll(this.stats.buckets, this.stats.sessions, this.stats.sessionCosts, { full: true });
|
|
10247
|
+
uploadedBuckets = r.buckets;
|
|
10248
|
+
uploadedSessions = r.sessions;
|
|
10249
|
+
await this.heartbeatNow().catch(() => {
|
|
10250
|
+
});
|
|
10251
|
+
phase("downloading");
|
|
10252
|
+
await this.fetchRemoteNow();
|
|
10253
|
+
}
|
|
10254
|
+
phase("limits");
|
|
10255
|
+
await this.refreshLiveLimits(true);
|
|
10256
|
+
const finishedAt = Date.now();
|
|
10257
|
+
this.syncResult = {
|
|
10258
|
+
startedAt,
|
|
10259
|
+
finishedAt,
|
|
10260
|
+
durationMs: finishedAt - startedAt,
|
|
10261
|
+
files: this.store.fileCount,
|
|
10262
|
+
sessions: this.store.sessions().length,
|
|
10263
|
+
roots: this.store.roots.length,
|
|
10264
|
+
agents: [...new Set(this.store.roots.map((r) => r.agent))].sort(),
|
|
10265
|
+
uploadedBuckets,
|
|
10266
|
+
uploadedSessions,
|
|
10267
|
+
uploaded
|
|
10268
|
+
};
|
|
10269
|
+
this.syncStatus = "done";
|
|
10270
|
+
this.syncFinishedAt = finishedAt;
|
|
10271
|
+
this.opts.log?.(
|
|
10272
|
+
`sync: ${this.syncResult.files} files, ${this.syncResult.sessions} sessions, ${uploadedBuckets} buckets / ${uploadedSessions} sessions uploaded in ${this.syncResult.durationMs} ms`
|
|
10273
|
+
);
|
|
10274
|
+
return this.syncResult;
|
|
10275
|
+
} catch (err) {
|
|
10276
|
+
this.syncStatus = "error";
|
|
10277
|
+
this.syncFinishedAt = Date.now();
|
|
10278
|
+
this.syncError = err instanceof SignedOutError ? "not signed in" : errorMessage(err);
|
|
10279
|
+
this.opts.log?.(`sync failed: ${this.syncError}`);
|
|
10280
|
+
return null;
|
|
10281
|
+
} finally {
|
|
10282
|
+
this.syncPhase = null;
|
|
10283
|
+
this.emitSnapshot();
|
|
10284
|
+
this.scheduleSyncBannerClear();
|
|
10285
|
+
}
|
|
10286
|
+
}
|
|
10287
|
+
/** Return the sync banner to "idle" a little after it finished, keeping `last` for the footer. */
|
|
10288
|
+
scheduleSyncBannerClear() {
|
|
10289
|
+
if (this.opts.watch === false) return;
|
|
10290
|
+
if (this.syncBannerTimer) clearTimeout(this.syncBannerTimer);
|
|
10291
|
+
this.syncBannerTimer = setTimeout(() => {
|
|
10292
|
+
this.syncBannerTimer = null;
|
|
10293
|
+
if (this.syncStatus === "done" || this.syncStatus === "error") {
|
|
10294
|
+
this.syncStatus = "idle";
|
|
10295
|
+
this.emitSnapshot();
|
|
10296
|
+
}
|
|
10297
|
+
}, SYNC_BANNER_MS);
|
|
10298
|
+
this.syncBannerTimer.unref?.();
|
|
10299
|
+
}
|
|
10300
|
+
syncState() {
|
|
10301
|
+
return {
|
|
10302
|
+
status: this.syncStatus,
|
|
10303
|
+
phase: this.syncPhase,
|
|
10304
|
+
startedAt: this.syncStartedAt,
|
|
10305
|
+
finishedAt: this.syncFinishedAt,
|
|
10306
|
+
error: this.syncError,
|
|
10307
|
+
last: this.syncResult
|
|
10308
|
+
};
|
|
10309
|
+
}
|
|
9428
10310
|
/**
|
|
9429
10311
|
* Ask the npm registry for the newest published version (cached for 6 h unless `force`).
|
|
9430
10312
|
* Best-effort: a failure is recorded on the snapshot, never thrown.
|
|
@@ -9542,6 +10424,7 @@ ${r.output}`.trim();
|
|
|
9542
10424
|
const sessions = this.store.sessions();
|
|
9543
10425
|
return {
|
|
9544
10426
|
version: APP_VERSION,
|
|
10427
|
+
channel: APP_CHANNEL,
|
|
9545
10428
|
generatedAt: Date.now(),
|
|
9546
10429
|
language: this.language(),
|
|
9547
10430
|
languageSetting: this.config.language,
|
|
@@ -9560,6 +10443,7 @@ ${r.output}`.trim();
|
|
|
9560
10443
|
rateLimitsError: this.config.liveRateLimits ? this.liveLimitsError : null,
|
|
9561
10444
|
rateLimitsUpdatedAt: this.liveLimits ? this.liveLimitsAt : s.logRateLimits?.observedAt ?? null,
|
|
9562
10445
|
update: this.updateState(),
|
|
10446
|
+
sync: this.syncState(),
|
|
9563
10447
|
modelsToday: s.modelsToday,
|
|
9564
10448
|
modelsMonth: s.modelsMonth,
|
|
9565
10449
|
byAgentToday: s.byAgentToday,
|
|
@@ -9576,6 +10460,7 @@ ${r.output}`.trim();
|
|
|
9576
10460
|
},
|
|
9577
10461
|
sessionDirs: SessionStore.rootDirs(this.store.roots),
|
|
9578
10462
|
sessionRoots: this.store.roots.map((r) => ({ dir: r.dir, agent: r.agent, format: r.format, origin: r.origin })),
|
|
10463
|
+
configDir: configDir(),
|
|
9579
10464
|
launchAtLogin: this.config.launchAtLogin,
|
|
9580
10465
|
trayTitle: this.config.trayTitle
|
|
9581
10466
|
};
|
|
@@ -9622,14 +10507,15 @@ function updateTray(s) {
|
|
|
9622
10507
|
mb.tray.setToolTip(`${APP_NAME} \u2014 ${t(L, "today")}: ${formatTokens(s.today.usage.total)} \xB7 ${formatUSD(s.today.cost)}${live}`);
|
|
9623
10508
|
if (isMac) mb.tray.setTitle(trayText(s), { fontType: "monospacedDigit" });
|
|
9624
10509
|
}
|
|
9625
|
-
var
|
|
10510
|
+
var launchAgentLabel = IS_DEV_BUILD ? "dev.codex-tracker.menubar.dev" : "dev.codex-tracker.menubar";
|
|
10511
|
+
var launchAgentPath = import_node_path11.default.join(import_node_os7.default.homedir(), "Library", "LaunchAgents", `${launchAgentLabel}.plist`);
|
|
9626
10512
|
function setLaunchAtLogin(enabled) {
|
|
9627
10513
|
if (isMac) {
|
|
9628
10514
|
if (enabled) {
|
|
9629
10515
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
9630
10516
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
9631
10517
|
<plist version="1.0"><dict>
|
|
9632
|
-
<key>Label</key><string
|
|
10518
|
+
<key>Label</key><string>${launchAgentLabel}</string>
|
|
9633
10519
|
<key>ProgramArguments</key><array><string>${process.execPath}</string><string>${import_node_path11.default.join(__dirname, "main.js")}</string></array>
|
|
9634
10520
|
<key>RunAtLoad</key><true/>
|
|
9635
10521
|
<key>KeepAlive</key><false/>
|
|
@@ -9664,6 +10550,7 @@ function buildMenu(s) {
|
|
|
9664
10550
|
});
|
|
9665
10551
|
const template = [
|
|
9666
10552
|
{ label: `${APP_NAME} ${t(L, "version", { version: APP_VERSION })}`, enabled: false },
|
|
10553
|
+
...IS_DEV_BUILD ? [{ label: t(L, "devBuildMenu", { url: s.auth.dashboardUrl }), enabled: false }] : [],
|
|
9667
10554
|
{
|
|
9668
10555
|
label: s.auth.status === "signedIn" ? t(L, "signedInAs", { name: s.auth.user?.name || s.auth.user?.email || "?" }) : t(L, "signedOut"),
|
|
9669
10556
|
enabled: false
|
|
@@ -9688,6 +10575,11 @@ function buildMenu(s) {
|
|
|
9688
10575
|
}
|
|
9689
10576
|
] : [],
|
|
9690
10577
|
{ label: t(L, "refresh"), click: () => void engine?.refresh(true) },
|
|
10578
|
+
{
|
|
10579
|
+
label: s.sync.status === "running" ? t(L, "syncing") : t(L, "syncNow"),
|
|
10580
|
+
enabled: s.sync.status !== "running",
|
|
10581
|
+
click: () => void engine?.syncNow()
|
|
10582
|
+
},
|
|
9691
10583
|
...s.update ? [
|
|
9692
10584
|
s.update.available ? { label: t(L, "updateAvailable", { version: s.update.latest ?? "?" }), click: () => void engine?.installUpdate() } : { label: t(L, "checkForUpdates"), click: () => void engine?.checkUpdate(true) }
|
|
9693
10585
|
] : [],
|
|
@@ -9704,10 +10596,10 @@ async function startLogin() {
|
|
|
9704
10596
|
log2("login failed", errorMessage(err));
|
|
9705
10597
|
}
|
|
9706
10598
|
}
|
|
10599
|
+
import_electron.app.setName(APP_NAME);
|
|
9707
10600
|
if (!import_electron.app.requestSingleInstanceLock()) {
|
|
9708
10601
|
import_electron.app.quit();
|
|
9709
10602
|
} else {
|
|
9710
|
-
import_electron.app.setName(APP_NAME);
|
|
9711
10603
|
import_electron.app.on("second-instance", () => mb?.showWindow());
|
|
9712
10604
|
import_electron.app.on("window-all-closed", () => {
|
|
9713
10605
|
});
|
|
@@ -9747,6 +10639,7 @@ if (!import_electron.app.requestSingleInstanceLock()) {
|
|
|
9747
10639
|
import_electron.ipcMain.handle("auth:cancel", () => engine?.cancelLogin());
|
|
9748
10640
|
import_electron.ipcMain.handle("auth:logout", () => engine?.logout());
|
|
9749
10641
|
import_electron.ipcMain.handle("refresh", () => engine?.refresh(true).then(() => void 0));
|
|
10642
|
+
import_electron.ipcMain.handle("sync:now", () => engine?.syncNow().then(() => void 0));
|
|
9750
10643
|
import_electron.ipcMain.handle("update:check", () => engine?.checkUpdate(true).then(() => void 0));
|
|
9751
10644
|
import_electron.ipcMain.handle("update:install", () => engine?.installUpdate().then(() => void 0));
|
|
9752
10645
|
import_electron.ipcMain.handle("quit", () => import_electron.app.quit());
|