tokenmaxxing 1.132.0 → 1.133.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.132.0",
3
+ "version": "1.133.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",
@@ -10,7 +10,7 @@ import { codexStoreUsable, ensureCodexStoreHome } from "../lib/codexauth.ts";
10
10
  import { CODEX_CRED_ENV, CODEX_SUPERVISOR_ID_ENV, borrowCodexSeat, codexPickCtx, pickCodexSeat } from "../lib/codex.ts";
11
11
  import { clearPresence, livingPresences } from "../lib/presence.ts";
12
12
  import { isExhausted } from "../lib/picker.ts";
13
- import { exitStatus, loopGuardTripped, raceMarkerOrExit, recordPresenceOrStop, runPassthrough } from "../lib/supervise.ts";
13
+ import { childStdout, exitStatus, loopGuardTripped, raceMarkerOrExit, recordPresenceOrStop, relayStdout, runPassthrough } from "../lib/supervise.ts";
14
14
  import { saveTermios } from "../lib/tty.ts";
15
15
  import { loadAccounts, readJsonFile } from "../lib/state.ts";
16
16
  import { CodexRespawnMarkerSchema, type Account } from "../lib/types.ts";
@@ -137,14 +137,14 @@ export async function runCodexSupervisor(input: { argv: string[] }): Promise<num
137
137
  if (existsSync(marker)) rmSync(marker, { force: true });
138
138
 
139
139
  const launchedAt = Date.now();
140
- const { child, seat } = await withLock(codexPool.lockFile, async () => {
140
+ const { child, seat, drain } = await withLock(codexPool.lockFile, async () => {
141
141
  clearPresence({ dir: codexPaths.presenceDir, id: supervisorId });
142
142
  const picked = validWanted({ wanted, now: launchedAt, supervisorId }) ?? pickCodexSeat(launchedAt);
143
143
  log("codexsupervisor.launch", { supervisorId: supervisorId.slice(0, 8), respawns, seat: picked?.id.slice(0, 8) ?? null, args: launchArgs.join(" ") });
144
144
  const store = picked ? ensureCodexStoreHome(picked.id) : undefined;
145
145
  const spawned = Bun.spawn([real, ...launchArgs], {
146
146
  stdin: "inherit",
147
- stdout: "inherit",
147
+ stdout: childStdout(),
148
148
  stderr: "inherit",
149
149
  env: {
150
150
  ...(store ? omit(childEnv, CODEX_CRED_ENV) : childEnv),
@@ -152,6 +152,7 @@ export async function runCodexSupervisor(input: { argv: string[] }): Promise<num
152
152
  ...(store ? { CODEX_HOME: store } : {}),
153
153
  },
154
154
  });
155
+ const drain = spawned.stdout instanceof ReadableStream ? relayStdout(spawned.stdout) : null;
155
156
  if (picked) {
156
157
  await recordPresenceOrStop({
157
158
  child: spawned,
@@ -163,10 +164,10 @@ export async function runCodexSupervisor(input: { argv: string[] }): Promise<num
163
164
  savedTermios,
164
165
  });
165
166
  }
166
- return { child: spawned, seat: picked };
167
+ return { child: spawned, seat: picked, drain };
167
168
  });
168
169
  if (respawns > 0) {
169
- process.stdout.write(`\n\x1b[36m↻ tokenmaxxing: switched codex to ${seat?.label ?? "the ambient codex login"} - resuming...\x1b[0m\n`);
170
+ process.stderr.write(`\n\x1b[36m↻ tokenmaxxing: switched codex to ${seat?.label ?? "the ambient codex login"} - resuming...\x1b[0m\n`);
170
171
  }
171
172
 
172
173
  await raceMarkerOrExit({
@@ -178,6 +179,7 @@ export async function runCodexSupervisor(input: { argv: string[] }): Promise<num
178
179
  },
179
180
  savedTermios,
180
181
  });
182
+ await drain?.();
181
183
 
182
184
  const payload = existsSync(marker) ? readCodexMarker(marker) : null;
183
185
  if (payload) {
@@ -1,4 +1,3 @@
1
- import { once } from "node:events";
2
1
  import { existsSync, mkdirSync, rmSync, readdirSync, statSync } from "node:fs";
3
2
  import { basename, join } from "node:path";
4
3
  import type { FileSink, Subprocess } from "bun";
@@ -15,7 +14,7 @@ import { thresholdBars, usableAt } from "../lib/picker.ts";
15
14
  import { clearPresence } from "../lib/presence.ts";
16
15
  import { readLines } from "../lib/proc.ts";
17
16
  import { teeObservation } from "../lib/sample.ts";
18
- import { countdownWait, exitStatus, loopGuardTripped, raceMarkerOrExit, recordPresenceOrStop, runPassthrough, SEAT_POLL_MS, SEAT_RETRY_MS, type Say } from "../lib/supervise.ts";
17
+ import { countdownWait, exitStatus, loopGuardTripped, raceMarkerOrExit, recordPresenceOrStop, relayStdout, runPassthrough, SEAT_POLL_MS, SEAT_RETRY_MS, type Say } from "../lib/supervise.ts";
19
18
  import { saveTermios } from "../lib/tty.ts";
20
19
  import { liveSessionId, loadSessionFlags, pruneStaleSessions, saveSessionFlags, writeRespawnMarker } from "../lib/sessions.ts";
21
20
  import { loadAccounts, loadConfig, readJsonFile, releaseWaitClaim, writeUsage } from "../lib/state.ts";
@@ -325,8 +324,6 @@ function userLine(text: string): string {
325
324
  return `${JSON.stringify({ type: "user", message: { role: "user", content: [{ type: "text", text }] } })}\n`;
326
325
  }
327
326
 
328
- const STDOUT_QUIET_MS = 1000;
329
-
330
327
  const TaskLineSchema = z.discriminatedUnion("subtype", [
331
328
  z.looseObject({ type: z.literal("system"), subtype: z.literal("task_started"), task_id: z.string(), description: z.string(), session_id: z.string() }),
332
329
  z.looseObject({ type: z.literal("system"), subtype: z.literal("task_notification"), task_id: z.string() }),
@@ -361,42 +358,6 @@ function seatTee(seatId: string | null, model: ModelInfo | null, open: OpenTasks
361
358
  };
362
359
  }
363
360
 
364
- function relayStdout(source: ReadableStream<Uint8Array>, onLine: (line: string) => void): () => Promise<void> {
365
- let ended = false;
366
- let blocked = false;
367
- let readAt = Date.now();
368
- const forwarded = source.pipeThrough(
369
- new TransformStream<Uint8Array, Uint8Array>({
370
- async transform(chunk, controller) {
371
- readAt = Date.now();
372
- if (!process.stdout.write(chunk)) {
373
- blocked = true;
374
- await once(process.stdout, "drain");
375
- blocked = false;
376
- }
377
- controller.enqueue(chunk);
378
- },
379
- }),
380
- );
381
- void (async () => {
382
- for await (const line of readLines(forwarded)) {
383
- try {
384
- onLine(line);
385
- } catch (e) {
386
- log("supervisor.tee_failed", { err: errorMessage(e) });
387
- }
388
- }
389
- })()
390
- .catch((e: unknown) => log("supervisor.stdout_relay_failed", { err: errorMessage(e) }))
391
- .finally(() => {
392
- ended = true;
393
- });
394
- return async () => {
395
- const exitedAt = Date.now();
396
- while (!ended && (blocked || Date.now() - Math.max(readAt, exitedAt) < STDOUT_QUIET_MS)) await Bun.sleep(50);
397
- };
398
- }
399
-
400
361
  const REPLAYED_REQUESTS = new Set(["initialize", "set_max_thinking_tokens", "set_model", "set_permission_mode"]);
401
362
 
402
363
  const RelayLineSchema = z.discriminatedUnion("type", [
@@ -1,7 +1,10 @@
1
+ import { once } from "node:events";
2
+ import { isatty } from "node:tty";
1
3
  import type { Subprocess } from "bun";
2
4
  import { LOOP_DIAGNOSIS, MAX_WRAP_DEPTH, WRAP_RATE_WINDOW_MS, wrapDepth, wrapperChainTripped } from "./claudebin.ts";
3
5
  import { errorMessage, log } from "./log.ts";
4
6
  import { paths } from "./paths.ts";
7
+ import { readLines } from "./proc.ts";
5
8
  import { writePresence } from "./presence.ts";
6
9
  import { restoreTermios } from "./tty.ts";
7
10
 
@@ -75,10 +78,57 @@ export function loopGuardTripped(product: WrappedProduct): boolean {
75
78
  return false;
76
79
  }
77
80
 
81
+ const STDOUT_QUIET_MS = 1000;
82
+
83
+ export function childStdout(): "inherit" | "pipe" {
84
+ return isatty(1) ? "inherit" : "pipe";
85
+ }
86
+
87
+ export function relayStdout(source: ReadableStream<Uint8Array>, onLine?: (line: string) => void): (abandoned?: () => boolean) => Promise<void> {
88
+ let ended = false;
89
+ let blocked = false;
90
+ let readAt = Date.now();
91
+ const forwarded = source.pipeThrough(
92
+ new TransformStream<Uint8Array, Uint8Array>({
93
+ async transform(chunk, controller) {
94
+ readAt = Date.now();
95
+ if (!process.stdout.write(chunk)) {
96
+ blocked = true;
97
+ await once(process.stdout, "drain");
98
+ blocked = false;
99
+ }
100
+ controller.enqueue(chunk);
101
+ },
102
+ }),
103
+ );
104
+ void (async () => {
105
+ if (onLine == null) return forwarded.pipeTo(new WritableStream());
106
+ for await (const line of readLines(forwarded)) {
107
+ try {
108
+ onLine(line);
109
+ } catch (e) {
110
+ log("supervisor.tee_failed", { err: errorMessage(e) });
111
+ }
112
+ }
113
+ })()
114
+ .catch((e: unknown) => log("supervisor.stdout_relay_failed", { err: errorMessage(e) }))
115
+ .finally(() => {
116
+ ended = true;
117
+ });
118
+ return async (abandoned = () => false) => {
119
+ const exitedAt = Date.now();
120
+ while (!ended && (blocked ? !abandoned() : Date.now() - Math.max(readAt, exitedAt) < STDOUT_QUIET_MS)) await Bun.sleep(50);
121
+ };
122
+ }
123
+
78
124
  export async function runPassthrough(input: { real: string; argv: string[]; env: Record<string, string | undefined>; onSpawn?: (child: Subprocess) => void | Promise<void> }): Promise<number> {
79
- const p = Bun.spawn([input.real, ...input.argv], { stdin: "inherit", stdout: "inherit", stderr: "inherit", env: input.env });
125
+ let terminated = false;
126
+ process.on("SIGTERM", () => { terminated = true; });
127
+ const p = Bun.spawn([input.real, ...input.argv], { stdin: "inherit", stdout: childStdout(), stderr: "inherit", env: input.env });
128
+ const drain = p.stdout instanceof ReadableStream ? relayStdout(p.stdout) : null;
80
129
  await input.onSpawn?.(p);
81
130
  await p.exited;
131
+ await drain?.(() => terminated);
82
132
  return exitStatus(p);
83
133
  }
84
134