tokenmaxxing 1.72.0 → 1.73.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/DESIGN.md +1 -1
- package/package.json +1 -1
- package/src/lib/sessions.ts +2 -27
package/DESIGN.md
CHANGED
|
@@ -42,7 +42,7 @@ It is a process manager only - spawn with inherited stdio (stdin through a relay
|
|
|
42
42
|
- `sessions/<sid>.json`, `onboard/`, `hub-key`, `update.json`, `spawnrate.json`, `tokenmaxxing.log`, the codex `codex-onboard/`, `codex-respawn/`, and `codex-live/`, and the `grok-*` and `opencode-go-*` state of the status-only pools: the full table is in [State directory layout](docs/content/docs/state-directory.mdx).
|
|
43
43
|
- Per-account **credential stores** follow the platform's Claude Code store: macOS = a login-keychain item keyed by the store path (never plaintext on disk); Linux = a 0600 `.credentials.json` inside the 0700 store directory (the same plaintext model claude itself uses - its Linux build has no keyring path at all, binary-verified 2.1.205). One `credstore` facade dispatches on a `{kind: keychain|file}` target; call sites never branch on platform. tokenmaxxing writes a store once, at onboarding; Claude Code's own refresh is the only writer afterwards.
|
|
44
44
|
|
|
45
|
-
- A periodic check job (`com.tokenmaxxing.check` launchd agent on macOS, `tokenmaxxing-check.timer` systemd user timer on Linux) running `tokenmaxxing check` once per tick (`policy.checkIntervalMs`, 60s by default): it runs the decision with no seat (nothing moves), folds fresh tees into the index, samples up to three accounts whose last sample attempt is oldest (the direct no-spend usage GET), deletes leftover
|
|
45
|
+
- A periodic check job (`com.tokenmaxxing.check` launchd agent on macOS, `tokenmaxxing-check.timer` systemd user timer on Linux) running `tokenmaxxing check` once per tick (`policy.checkIntervalMs`, 60s by default): it runs the decision with no seat (nothing moves), folds fresh tees into the index, samples up to three accounts whose last sample attempt is oldest (the direct no-spend usage GET), deletes leftover atomic-write temp files under the state root, and on a Bun global install checks npm for a newer version once a day, so the cached figures every placement reads stay fresh.
|
|
46
46
|
- A usage hub service (`com.tokenmaxxing.hub` launchd agent on macOS, `tokenmaxxing-hub.service` systemd user service on Linux) running `tokenmaxxing serve`, so the [usage hub](docs/content/docs/hub.mdx) is up in the background beside the check timer.
|
|
47
47
|
|
|
48
48
|
The switching path runs no long-lived daemon. The statusline pushes usage. Hooks and the supervisor react. The periodic check job above is the only recurring process in the switching path. The [usage hub](docs/content/docs/hub.mdx) that answers the CLIProxyAPI management subset for a dashboard from the cached figures runs outside the switching path, as a background service beside the check timer (`tokenmaxxing serve` runs the same server in the foreground). The `claude` binary, `~/.claude.json`, and Claude Code's default credential store are untouched; inside `~/.claude` only `settings.json` gets the five entries.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tokenmaxxing",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.73.0",
|
|
4
4
|
"description": "Automatic Claude Code account switching: pool multiple accounts, start each session on its own account, and resume a session on a fresher account when quota fills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/lib/sessions.ts
CHANGED
|
@@ -43,24 +43,6 @@ function recordLiveSession(sid: string, current: string): void {
|
|
|
43
43
|
writeFileAtomic(sessionFile(sid), JSON.stringify({ flags: session?.flags ?? [], cwd: session?.cwd ?? process.cwd(), current }));
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const DEAD_STATE_ENTRIES = [
|
|
47
|
-
"model-usage.json",
|
|
48
|
-
"accounts.json.v1-backup",
|
|
49
|
-
"codex-accounts.json.v1-backup",
|
|
50
|
-
"nextcheck.json",
|
|
51
|
-
"usage.json",
|
|
52
|
-
"lastswap.json",
|
|
53
|
-
"depleted.json",
|
|
54
|
-
"codex-lastswap.json",
|
|
55
|
-
"creds",
|
|
56
|
-
"codex-creds",
|
|
57
|
-
"codex-reconcile",
|
|
58
|
-
"sample",
|
|
59
|
-
"setup-tokens.json",
|
|
60
|
-
"setup-token",
|
|
61
|
-
"cloud",
|
|
62
|
-
];
|
|
63
|
-
|
|
64
46
|
const TMP_MARKER = ".tmp.";
|
|
65
47
|
const TMP_GRACE_MS = 3600 * 1000;
|
|
66
48
|
|
|
@@ -88,14 +70,7 @@ function tmpSweepDirs(root: string): string[] {
|
|
|
88
70
|
return dirs;
|
|
89
71
|
}
|
|
90
72
|
|
|
91
|
-
function
|
|
92
|
-
for (const name of DEAD_STATE_ENTRIES) {
|
|
93
|
-
try {
|
|
94
|
-
rmSync(join(paths.home, name), { recursive: true, force: true });
|
|
95
|
-
} catch (e) {
|
|
96
|
-
log("state.dead_entry_failed", { name, err: errorMessage(e) });
|
|
97
|
-
}
|
|
98
|
-
}
|
|
73
|
+
function pruneTmpFiles(now: number, root: string): void {
|
|
99
74
|
for (const dir of tmpSweepDirs(root)) {
|
|
100
75
|
for (const f of listDir(dir, root)) {
|
|
101
76
|
if (!f.isFile() || !f.name.includes(TMP_MARKER)) continue;
|
|
@@ -115,7 +90,7 @@ export function pruneStaleSessions(now: number): void {
|
|
|
115
90
|
} catch {
|
|
116
91
|
return;
|
|
117
92
|
}
|
|
118
|
-
|
|
93
|
+
pruneTmpFiles(now, root);
|
|
119
94
|
const dir = sessionsDir();
|
|
120
95
|
for (const f of listDir(dir, root)) {
|
|
121
96
|
const p = join(dir, f.name);
|