@kodo/agent-meter 1.0.0 → 1.0.1
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 +21 -5
- package/dist/cli.js +56 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,24 +1,32 @@
|
|
|
1
|
-
# agent-meter
|
|
1
|
+
# @kodo/agent-meter
|
|
2
2
|
|
|
3
3
|
CLI tool for managing multiple Codex OAuth accounts and checking their rate limits / usage.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
|
-
|
|
10
|
+
npm install -g @kodo/agent-meter
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or run directly with npx:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @kodo/agent-meter list
|
|
9
17
|
```
|
|
10
18
|
|
|
11
19
|
## Usage
|
|
12
20
|
|
|
13
21
|
```bash
|
|
14
22
|
# Add a new account (opens browser for OAuth login, then auto-checks usage)
|
|
15
|
-
|
|
23
|
+
agent-meter add
|
|
16
24
|
|
|
17
25
|
# List all accounts with real-time usage check
|
|
18
|
-
|
|
26
|
+
agent-meter list
|
|
19
27
|
|
|
20
28
|
# Remove an account by email
|
|
21
|
-
|
|
29
|
+
agent-meter delete <email>
|
|
22
30
|
```
|
|
23
31
|
|
|
24
32
|
## How it works
|
|
@@ -28,6 +36,10 @@ pnpm dev delete <email>
|
|
|
28
36
|
- `delete` removes the account and its `CODEX_HOME` directory
|
|
29
37
|
- If a token expires during `list`, you'll be prompted to re-login on the spot
|
|
30
38
|
|
|
39
|
+
## Prerequisites
|
|
40
|
+
|
|
41
|
+
- [Codex CLI](https://github.com/openai/codex) installed and available on PATH
|
|
42
|
+
|
|
31
43
|
## Options
|
|
32
44
|
|
|
33
45
|
| Flag | Description |
|
|
@@ -35,3 +47,7 @@ pnpm dev delete <email>
|
|
|
35
47
|
| `--json` | Output raw JSON |
|
|
36
48
|
| `--verbose` | Enable verbose logging |
|
|
37
49
|
| `--data-dir <path>` | Override the default `.data` directory |
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
MIT
|
package/dist/cli.js
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
3
5
|
import readline from 'node:readline';
|
|
4
6
|
import { Command } from 'commander';
|
|
5
7
|
import { createCodexHome, createDataPaths, ensureDataPaths, makeId, markLastUsed, nowIso, normalizeAccount, readStore, removeAccountFromStore, resolveAccountRef, updateAccount, writeStore, } from './core/accounts.js';
|
|
6
8
|
import { ensureCodexInstalled, loadCredentials, runCodexLogin } from './core/auth.js';
|
|
7
9
|
import { printJson, renderAccountsTable } from './core/output.js';
|
|
8
10
|
import { checkAccount } from './core/usage.js';
|
|
11
|
+
const DEFAULT_DATA_DIR = path.join(os.homedir(), '.agent-meter');
|
|
9
12
|
function resolveDataDir(opts) {
|
|
10
13
|
if (!opts.dataDir)
|
|
11
|
-
return
|
|
14
|
+
return DEFAULT_DATA_DIR;
|
|
12
15
|
const resolved = opts.dataDir.startsWith('/') ? opts.dataDir : `${process.cwd()}/${opts.dataDir}`;
|
|
13
16
|
return fs.existsSync(resolved) ? fs.realpathSync(resolved) : resolved;
|
|
14
17
|
}
|
|
15
18
|
function getStore(opts) {
|
|
16
19
|
const dataDir = resolveDataDir(opts);
|
|
20
|
+
if (!opts.dataDir) {
|
|
21
|
+
migrateLegacyData(dataDir, Boolean(opts.verbose));
|
|
22
|
+
}
|
|
17
23
|
const paths = createDataPaths(dataDir);
|
|
18
24
|
ensureDataPaths(paths);
|
|
19
25
|
return {
|
|
@@ -30,13 +36,61 @@ function confirm(question) {
|
|
|
30
36
|
});
|
|
31
37
|
});
|
|
32
38
|
}
|
|
39
|
+
function migrateLegacyData(targetDir, verbose) {
|
|
40
|
+
if (fs.existsSync(path.join(targetDir, 'accounts.json')))
|
|
41
|
+
return;
|
|
42
|
+
const legacyDir = path.join(process.cwd(), '.data');
|
|
43
|
+
if (!fs.existsSync(path.join(legacyDir, 'accounts.json')))
|
|
44
|
+
return;
|
|
45
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
46
|
+
const copyRecursive = (src, dest) => {
|
|
47
|
+
let stat;
|
|
48
|
+
try {
|
|
49
|
+
stat = fs.statSync(src);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (stat.isDirectory()) {
|
|
55
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
56
|
+
for (const child of fs.readdirSync(src)) {
|
|
57
|
+
copyRecursive(path.join(src, child), path.join(dest, child));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
fs.copyFileSync(src, dest);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
for (const entry of fs.readdirSync(legacyDir)) {
|
|
65
|
+
copyRecursive(path.join(legacyDir, entry), path.join(targetDir, entry));
|
|
66
|
+
}
|
|
67
|
+
// Rewrite codexHome paths in accounts.json to point to the new location
|
|
68
|
+
const accountsFile = path.join(targetDir, 'accounts.json');
|
|
69
|
+
try {
|
|
70
|
+
const raw = JSON.parse(fs.readFileSync(accountsFile, 'utf8'));
|
|
71
|
+
const legacyHomesDir = path.join(legacyDir, 'codex-homes');
|
|
72
|
+
const newHomesDir = path.join(targetDir, 'codex-homes');
|
|
73
|
+
const accounts = Array.isArray(raw?.accounts) ? raw.accounts : (Array.isArray(raw) ? raw : []);
|
|
74
|
+
for (const account of accounts) {
|
|
75
|
+
if (typeof account.codexHome === 'string' && account.codexHome.startsWith(legacyHomesDir)) {
|
|
76
|
+
account.codexHome = account.codexHome.replace(legacyHomesDir, newHomesDir);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
fs.writeFileSync(accountsFile, JSON.stringify(raw, null, 2));
|
|
80
|
+
}
|
|
81
|
+
catch { /* best effort */ }
|
|
82
|
+
if (verbose) {
|
|
83
|
+
process.stderr.write(`Migrated data from ${legacyDir} → ${targetDir}\n`);
|
|
84
|
+
}
|
|
85
|
+
process.stdout.write(`✓ Data migrated from .data/ to ${targetDir}\n`);
|
|
86
|
+
}
|
|
33
87
|
const program = new Command();
|
|
34
88
|
program
|
|
35
89
|
.name('agent-meter')
|
|
36
90
|
.description('Multi-account Codex OAuth usage checker')
|
|
37
91
|
.option('--json', 'output JSON')
|
|
38
92
|
.option('--verbose', 'enable verbose logging')
|
|
39
|
-
.option('--data-dir <path>',
|
|
93
|
+
.option('--data-dir <path>', `override data directory (default: ~/.agent-meter)`);
|
|
40
94
|
program
|
|
41
95
|
.command('add')
|
|
42
96
|
.description('add a new account via codex login')
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kodo/agent-meter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI tool for managing multiple Codex OAuth accounts and checking rate limits",
|
|
6
6
|
"bin": {
|
|
7
|
-
"agent-meter": "
|
|
7
|
+
"agent-meter": "dist/cli.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist"
|