tokelytics 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/tokelytics.mjs +48 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ prompts or responses.
|
|
|
9
9
|
|
|
10
10
|
```
|
|
11
11
|
npx tokelytics@latest login # opens your browser to approve — no setup, no keys
|
|
12
|
-
npx tokelytics@latest watch #
|
|
12
|
+
npx tokelytics@latest watch # one machine-wide watcher; cloud backup every 30m
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Keep `@latest` in install and onboarding commands. Agents older than 0.3.1
|
package/bin/tokelytics.mjs
CHANGED
|
@@ -1014,13 +1014,34 @@ async function loadUpdateState() {
|
|
|
1014
1014
|
async function saveUpdateState(state) {
|
|
1015
1015
|
await writeJson(updatePath(), state);
|
|
1016
1016
|
}
|
|
1017
|
-
|
|
1017
|
+
var AgentAlreadyRunningError = class extends Error {
|
|
1018
|
+
lock;
|
|
1019
|
+
constructor(lock, cause) {
|
|
1020
|
+
super(`Tokelytics is already running (PID ${lock.pid}).`, { cause });
|
|
1021
|
+
this.name = "AgentAlreadyRunningError";
|
|
1022
|
+
this.lock = lock;
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
async function activeAgentLock() {
|
|
1026
|
+
const lock = await readJson(watchLockPath());
|
|
1027
|
+
if (!lock?.pid || !processIsAlive(lock.pid)) return null;
|
|
1028
|
+
return lock;
|
|
1029
|
+
}
|
|
1030
|
+
async function acquireWatchLock(owner = "watch") {
|
|
1018
1031
|
await ensureDir();
|
|
1019
1032
|
const file = watchLockPath();
|
|
1020
1033
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
1021
1034
|
try {
|
|
1022
1035
|
const handle = await fs3.open(file, "wx");
|
|
1023
|
-
await handle.writeFile(
|
|
1036
|
+
await handle.writeFile(
|
|
1037
|
+
JSON.stringify({
|
|
1038
|
+
pid: process.pid,
|
|
1039
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1040
|
+
owner,
|
|
1041
|
+
scope: "machine"
|
|
1042
|
+
}),
|
|
1043
|
+
"utf-8"
|
|
1044
|
+
);
|
|
1024
1045
|
await handle.close();
|
|
1025
1046
|
let released = false;
|
|
1026
1047
|
return {
|
|
@@ -1036,7 +1057,7 @@ async function acquireWatchLock() {
|
|
|
1036
1057
|
if (code !== "EEXIST") throw error;
|
|
1037
1058
|
const lock = await readJson(file);
|
|
1038
1059
|
if (lock?.pid && processIsAlive(lock.pid)) {
|
|
1039
|
-
throw new
|
|
1060
|
+
throw new AgentAlreadyRunningError(lock, error);
|
|
1040
1061
|
}
|
|
1041
1062
|
await fs3.rm(file, { force: true });
|
|
1042
1063
|
}
|
|
@@ -1781,7 +1802,7 @@ var FirestoreSink = class {
|
|
|
1781
1802
|
};
|
|
1782
1803
|
|
|
1783
1804
|
// src/version.ts
|
|
1784
|
-
var AGENT_VERSION = "0.3.
|
|
1805
|
+
var AGENT_VERSION = "0.3.5";
|
|
1785
1806
|
|
|
1786
1807
|
// src/sync.ts
|
|
1787
1808
|
async function runSync(connectors, sink, state, device, limitCollectors = [], options = {}) {
|
|
@@ -3781,8 +3802,8 @@ var DEBOUNCE_MS = 1200;
|
|
|
3781
3802
|
var LIMIT_REFRESH_MS = 6e4;
|
|
3782
3803
|
var FALLBACK_SCAN_MS = 5e3;
|
|
3783
3804
|
var DEVICE_HEARTBEAT_MS = 60 * 6e4;
|
|
3784
|
-
var CLOUD_SYNC_INTERVAL_MS =
|
|
3785
|
-
var MAX_CLOUD_WRITES_PER_DAY =
|
|
3805
|
+
var CLOUD_SYNC_INTERVAL_MS = 30 * 6e4;
|
|
3806
|
+
var MAX_CLOUD_WRITES_PER_DAY = 16;
|
|
3786
3807
|
var QUOTA_RETRY_MS = 15 * 6e4;
|
|
3787
3808
|
var QUOTA_RETRY_JITTER_MS = 5 * 6e4;
|
|
3788
3809
|
async function watch2(runner) {
|
|
@@ -3979,7 +4000,7 @@ var USAGE = `Tokelytics agent
|
|
|
3979
4000
|
Usage:
|
|
3980
4001
|
tokelytics login Sign in by approving in your browser
|
|
3981
4002
|
tokelytics sync Run one incremental sync to your dashboard
|
|
3982
|
-
tokelytics watch Watch
|
|
4003
|
+
tokelytics watch Watch Claude Code and Codex usage across this machine
|
|
3983
4004
|
tokelytics status Show current sign-in and device
|
|
3984
4005
|
tokelytics logout Forget stored credentials
|
|
3985
4006
|
`;
|
|
@@ -4001,7 +4022,7 @@ async function main(argv) {
|
|
|
4001
4022
|
case "sync": {
|
|
4002
4023
|
const update = await agentUpdateMessage();
|
|
4003
4024
|
if (update) console.warn(update);
|
|
4004
|
-
const lock = await acquireWatchLock();
|
|
4025
|
+
const lock = await acquireWatchLock("sync");
|
|
4005
4026
|
try {
|
|
4006
4027
|
const runner = await createRunner();
|
|
4007
4028
|
const { processedTurns, processedLimits, byProvider, publicationError } = await runner.syncOnce();
|
|
@@ -4014,7 +4035,17 @@ async function main(argv) {
|
|
|
4014
4035
|
return 0;
|
|
4015
4036
|
}
|
|
4016
4037
|
case "watch": {
|
|
4017
|
-
|
|
4038
|
+
let lock;
|
|
4039
|
+
try {
|
|
4040
|
+
lock = await acquireWatchLock("watch");
|
|
4041
|
+
} catch (err) {
|
|
4042
|
+
if (err instanceof AgentAlreadyRunningError && err.lock.owner !== "sync") {
|
|
4043
|
+
console.log(`Tokelytics is already watching this machine (PID ${err.lock.pid}).`);
|
|
4044
|
+
console.log("Claude Code and Codex usage from every folder and repository is already covered.");
|
|
4045
|
+
return 0;
|
|
4046
|
+
}
|
|
4047
|
+
throw err;
|
|
4048
|
+
}
|
|
4018
4049
|
try {
|
|
4019
4050
|
const update = await agentUpdateMessage();
|
|
4020
4051
|
if (update) console.warn(update);
|
|
@@ -4028,7 +4059,15 @@ async function main(argv) {
|
|
|
4028
4059
|
case "status": {
|
|
4029
4060
|
const creds = await loadCredentials();
|
|
4030
4061
|
const state = await loadState();
|
|
4062
|
+
const lock = await activeAgentLock();
|
|
4031
4063
|
console.log(`Agent version: ${AGENT_VERSION}`);
|
|
4064
|
+
if (lock && lock.owner !== "sync") {
|
|
4065
|
+
console.log(`Watcher: active machine-wide (PID ${lock.pid}); all folders and repositories are covered.`);
|
|
4066
|
+
} else if (lock?.owner === "sync") {
|
|
4067
|
+
console.log(`Watcher: sync currently in progress (PID ${lock.pid}).`);
|
|
4068
|
+
} else {
|
|
4069
|
+
console.log('Watcher: not running. Run "tokelytics watch" once on this machine.');
|
|
4070
|
+
}
|
|
4032
4071
|
if (!creds) {
|
|
4033
4072
|
console.log('Not signed in. Run "tokelytics login".');
|
|
4034
4073
|
} else {
|