tokenmaxxing 1.161.0 → 1.162.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/lib/picker.ts +13 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokenmaxxing",
3
- "version": "1.161.0",
3
+ "version": "1.162.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/picker.ts CHANGED
@@ -164,6 +164,15 @@ export function seatHeadroom(a: Account, ctx: PickCtx): number {
164
164
  return (barFor(a, session, ctx.thresholds, ctx.now) - liveUsed(session, ctx.now)) / ((ctx.seats?.get(a.id) ?? 0) + 1);
165
165
  }
166
166
 
167
+ const MIN_SEAT_HEADROOM = 5;
168
+
169
+ function seatFull(a: Account, ctx: PickCtx): boolean {
170
+ const session = sessionWindow(a);
171
+ if (ctx.seats == null || session == null || spendsCredits(a, ctx.thresholds)) return false;
172
+ const fresh = barFor(a, session, ctx.thresholds, windowEnd(session)) / ((ctx.seats.get(a.id) ?? 0) + 1);
173
+ return seatHeadroom(a, ctx) < MIN_SEAT_HEADROOM && fresh >= MIN_SEAT_HEADROOM;
174
+ }
175
+
167
176
  export function onCredits(a: Account, ctx: PickCtx): boolean {
168
177
  return spendsCredits(a, ctx.thresholds) && isExhausted({ ...a, hasCredits: false }, ctx);
169
178
  }
@@ -178,13 +187,15 @@ const swapPreference = (ctx: PickCtx) => [
178
187
  ];
179
188
 
180
189
  export function pickBest(accounts: Account[], ctx: PickCtx): Account | null {
181
- const usable = accounts.filter((a) => a.id !== ctx.currentId && !a.needsReauth && !isExhausted(a, ctx));
190
+ const usable = accounts.filter((a) => a.id !== ctx.currentId && !a.needsReauth && !isExhausted(a, ctx) && !seatFull(a, ctx));
182
191
  return sortBy(usable, swapPreference(ctx))[0] ?? null;
183
192
  }
184
193
 
185
194
  export function usableAt(a: Account, ctx: PickCtx): number {
186
195
  const blocking = blockingUntil(a, ctx).filter((t) => t > ctx.now);
187
- return blocking.length ? Math.max(...blocking) : ctx.now;
196
+ const at = blocking.length ? Math.max(...blocking) : ctx.now;
197
+ const session = sessionWindow(a);
198
+ return session != null && seatFull(a, { ...ctx, now: at }) ? windowEnd(session) : at;
188
199
  }
189
200
 
190
201
  export type EarliestReset = { account: Account; availableAt: number };