tokenmaxxing 1.108.0 → 1.109.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokenmaxxing",
3
- "version": "1.108.0",
3
+ "version": "1.109.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/cli/seat.ts CHANGED
@@ -6,18 +6,18 @@ import { emitError } from "./render.ts";
6
6
  const POOLS = {
7
7
  claude: {
8
8
  borrow: borrowClaudeSeat,
9
- usage: "usage: tokenmaxxing seat <pid> - print the CLAUDE_SECURESTORAGE_CONFIG_DIR of one pooled claude account, lent to <pid> alone until it exits",
10
- none: "no usable claude account (pool empty, every account lent to another borrower, or every account at a limit or flagged for reauthentication)",
9
+ usage: "usage: tokenmaxxing seat <pid> - print the CLAUDE_SECURESTORAGE_CONFIG_DIR of one pooled claude account, lent to <pid> until it exits and shared with host sessions and other borrowers",
10
+ none: "no usable claude account (pool empty, or every account at a limit or flagged for reauthentication)",
11
11
  },
12
12
  codex: {
13
13
  borrow: borrowCodexSeat,
14
- usage: "usage: tokenmaxxing seat --codex <pid> - print the CODEX_HOME of one pooled account, reserved until <pid> exits",
14
+ usage: "usage: tokenmaxxing seat --codex <pid> - print the CODEX_HOME of one pooled account, reserved to <pid> alone until it exits, because one codex auth.json serves one machine or one serialized job stream (https://learn.chatgpt.com/docs/auth/ci-cd-auth)",
15
15
  none: "no usable codex account (pool empty, every account live in another session, or every account at a limit) - use the ambient codex login",
16
16
  },
17
17
  "opencode-go": {
18
18
  borrow: borrowOpencodeGoSeat,
19
- usage: "usage: tokenmaxxing seat --opencode-go <pid> - print the store directory of one pooled opencode-go key, whose auth.json is an opencode auth file, lent to <pid> alone until it exits",
20
- none: "no usable opencode-go key (pool empty, every key lent to another borrower, or no store holds a usable key)",
19
+ usage: "usage: tokenmaxxing seat --opencode-go <pid> - print the store directory of one pooled opencode-go key, whose auth.json is an opencode auth file, lent to <pid> until it exits and shared with other borrowers",
20
+ none: "no usable opencode-go key (pool empty, or no store holds a usable key)",
21
21
  },
22
22
  };
23
23
 
package/src/lib/claude.ts CHANGED
@@ -163,8 +163,7 @@ export async function borrowClaudeSeat(pid: number): Promise<SeatBorrow> {
163
163
  }
164
164
  return { store: storeDirFor(heldAccount.id), id: heldAccount.id, reused: true };
165
165
  }
166
- const lent = new Set(living.filter((p) => p.id.startsWith("seat-")).map((p) => p.accountId));
167
- const open = idx.accounts.filter((a) => a.needsReauth !== true && !lent.has(a.id));
166
+ const open = idx.accounts.filter((a) => a.needsReauth !== true);
168
167
  const usable = await Promise.all(open.map(storeUsable));
169
168
  const ctx: PickCtx = { now: Date.now(), thresholds: bars, currentId: null, families: gatedFamilies(null, cfg.policy.switchModels), seats: presence() };
170
169
  const picked = pickBest(open.filter((_, i) => usable[i]), ctx);
@@ -1,4 +1,5 @@
1
1
  import { join } from "node:path";
2
+ import { countBy, minBy } from "es-toolkit";
2
3
  import { z } from "zod";
3
4
  import { writeFileAtomic } from "./atomic.ts";
4
5
  import { env, HOME, opencodeGoAuthJsonFor, opencodeGoPaths, opencodeGoPool, opencodeGoStoreDirFor } from "./paths.ts";
@@ -63,10 +64,9 @@ export async function borrowOpencodeGoSeat(pid: number): Promise<SeatBorrow> {
63
64
  }
64
65
  return { store: opencodeGoStoreDirFor(heldAccount.id), id: heldAccount.id, reused: true };
65
66
  }
66
- const lent = new Set(living.map((p) => p.accountId));
67
- const open = accounts.filter((a) => !lent.has(a.id));
68
- const usable = await Promise.all(open.map(opencodeGo.storeUsable));
69
- const picked = open.find((_, i) => usable[i]);
67
+ const lent = countBy(living, (p) => p.accountId);
68
+ const usable = await Promise.all(accounts.map(opencodeGo.storeUsable));
69
+ const picked = minBy(accounts.filter((_, i) => usable[i]), (a) => lent[a.id] ?? 0);
70
70
  if (!picked) return null;
71
71
  writePresence({ dir: opencodeGoPaths.presenceDir, id: seatId, accountId: picked.id, pid });
72
72
  return { store: opencodeGoStoreDirFor(picked.id), id: picked.id, reused: false };
package/src/lib/picker.ts CHANGED
@@ -122,6 +122,7 @@ const swapPreference = (ctx: PickCtx) => [
122
122
  (a: Account) => -pacePressure(a, ctx),
123
123
  (a: Account) => weeklyExpiry(a, ctx.now),
124
124
  (a: Account) => weeklyWindow(a)?.usedPercentage ?? 101,
125
+ ...(ctx.seats == null ? [] : [(a: Account) => ctx.seats?.get(a.id) ?? 0]),
125
126
  ];
126
127
 
127
128
  export function pickBest(accounts: Account[], ctx: PickCtx): Account | null {
package/src/main.ts CHANGED
@@ -60,9 +60,9 @@ function printHelp(): void {
60
60
  ${c.cyan("tokenmaxxing doctor")} verify the install is intact
61
61
  ${c.cyan("tokenmaxxing rename")} [--codex | --grok | --opencode-go] <sel> <label>
62
62
  ${c.cyan("tokenmaxxing rm")} [--codex | --grok | --opencode-go] <sel>
63
- ${c.cyan("tokenmaxxing seat")} <pid> lend one pooled Claude account to an unattended consumer until <pid> exits: prints the store directory to set as CLAUDE_SECURESTORAGE_CONFIG_DIR (the directory itself, as its owner, never a copy of its credential); host sessions keep using the account, other borrowers do not; exit 1 = none usable
64
- ${c.cyan("tokenmaxxing seat --codex")} <pid> borrow one pooled codex account for an unattended consumer (plugin, script): prints the CODEX_HOME to set, reserved until <pid> exits; exit 1 = none usable, fall back to the ambient login
65
- ${c.cyan("tokenmaxxing seat --opencode-go")} <pid> lend one pooled opencode-go key to an unattended consumer until <pid> exits: prints the store directory, whose auth.json is an opencode auth file (mount it at $XDG_DATA_HOME/opencode/auth.json, then run a model such as opencode-go/mimo-v2.6-pro); other borrowers do not get the key; exit 1 = none usable
63
+ ${c.cyan("tokenmaxxing seat")} <pid> lend one pooled Claude account to an unattended consumer until <pid> exits: prints the store directory to set as CLAUDE_SECURESTORAGE_CONFIG_DIR (the directory itself, as its owner, never a copy of its credential); host sessions and other borrowers share the account; exit 1 = none usable
64
+ ${c.cyan("tokenmaxxing seat --codex")} <pid> borrow one pooled codex account for an unattended consumer (plugin, script): prints the CODEX_HOME to set, reserved to <pid> alone until it exits because one auth.json serves one serialized job stream; exit 1 = none usable, fall back to the ambient login
65
+ ${c.cyan("tokenmaxxing seat --opencode-go")} <pid> lend one pooled opencode-go key to an unattended consumer until <pid> exits: prints the store directory, whose auth.json is an opencode auth file (mount it at $XDG_DATA_HOME/opencode/auth.json, then run a model such as opencode-go/mimo-v2.6-pro); other borrowers share the key; exit 1 = none usable
66
66
  ${c.cyan("tokenmaxxing serve")} serve the CLIProxyAPI-compatible usage API on http://localhost:<hub.port> (default 8317) so a dashboard such as T3 Code's "Add a CLIProxyAPI hub" shows every pooled Claude and Codex account's quota; the management key is the contents of hub-key in the state directory
67
67
  ${c.cyan("tokenmaxxing uninstall")} [--yes] print the targets, then remove supervisor + settings entries (refused without ${c.cyan("--yes")} when HOME is the login home)
68
68