tokenmaxxing 1.7.0 → 1.9.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 +2 -2
- package/README.md +1 -1
- package/agent-plugin/plugin.json +8 -2
- package/package.json +1 -1
- package/src/cli/add.ts +1 -8
- package/src/cli/auth.ts +0 -23
- package/src/cli/check.ts +19 -13
- package/src/cli/codexadd.ts +0 -17
- package/src/cli/codexinit.ts +11 -42
- package/src/cli/codexrm.ts +0 -13
- package/src/cli/codexswitch.ts +0 -15
- package/src/cli/config.ts +0 -30
- package/src/cli/doctor.ts +1 -14
- package/src/cli/init.ts +8 -34
- package/src/cli/ls.ts +0 -2
- package/src/cli/onboard.ts +0 -37
- package/src/cli/rename.ts +0 -19
- package/src/cli/render.ts +0 -23
- package/src/cli/rm.ts +0 -19
- package/src/cli/status.ts +0 -80
- package/src/cli/switch.ts +1 -49
- package/src/cli/watch.ts +0 -17
- package/src/entries/codexstophook.ts +2 -63
- package/src/entries/codexsupervisor.ts +1 -67
- package/src/entries/mcp.ts +0 -11
- package/src/entries/sessionstart.ts +1 -8
- package/src/entries/statusline.ts +0 -66
- package/src/entries/stopfailurehook.ts +93 -0
- package/src/entries/stophook.ts +3 -23
- package/src/entries/subagentstatusline.ts +0 -19
- package/src/entries/supervisor.ts +32 -132
- package/src/lib/atomic.ts +0 -16
- package/src/lib/claudebin.ts +4 -55
- package/src/lib/claudejson.ts +0 -10
- package/src/lib/claudelock.ts +13 -35
- package/src/lib/codexauth.ts +0 -29
- package/src/lib/codexbin.ts +0 -10
- package/src/lib/codexdecide.ts +1 -112
- package/src/lib/codexoauth.ts +0 -16
- package/src/lib/codexpick.ts +0 -31
- package/src/lib/codexpresence.ts +0 -35
- package/src/lib/codexsample.ts +0 -23
- package/src/lib/codexstate.ts +0 -7
- package/src/lib/codexswap.ts +0 -32
- package/src/lib/codexusage.ts +0 -28
- package/src/lib/credstore.ts +0 -24
- package/src/lib/decide.ts +127 -180
- package/src/lib/http.ts +0 -9
- package/src/lib/install.ts +57 -124
- package/src/lib/keychain.ts +1 -39
- package/src/lib/lock.ts +0 -24
- package/src/lib/log.ts +0 -14
- package/src/lib/oauth.ts +1 -31
- package/src/lib/paths.ts +1 -45
- package/src/lib/picker.ts +1 -84
- package/src/lib/proc.ts +0 -17
- package/src/lib/sample.ts +0 -68
- package/src/lib/sessions.ts +0 -13
- package/src/lib/settings.ts +15 -42
- package/src/lib/state.ts +23 -77
- package/src/lib/swap.ts +3 -87
- package/src/lib/tty.ts +0 -4
- package/src/lib/types.ts +13 -140
- package/src/lib/usage.ts +108 -196
- package/src/lib/worktree.ts +0 -8
- package/src/main.ts +5 -35
- package/src/sdk.ts +0 -59
package/src/sdk.ts
CHANGED
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
// Programmatic surface for pairing tokenmaxxing with the Claude Code Agent SDK
|
|
2
|
-
// (personal use across your own pooled accounts - user decision 2026-07-16).
|
|
3
|
-
//
|
|
4
|
-
// The Agent SDK spawns a claude CLI subprocess per query() and that subprocess
|
|
5
|
-
// reads credentials at spawn time: no statusLine tee, no supervisor, no
|
|
6
|
-
// mid-query hot-swap. So the integration is boundary-driven - run the switch
|
|
7
|
-
// decision BEFORE a spawn so it lands on the best account, and again at
|
|
8
|
-
// Stop-hook turn boundaries so the NEXT spawn does; a running subprocess keeps
|
|
9
|
-
// its snapshotted token either way, which is exactly the clean-boundary
|
|
10
|
-
// semantics the CLI supervisor enforces with markers.
|
|
11
|
-
//
|
|
12
|
-
// Nothing here imports the Agent SDK: the helpers return plain values that
|
|
13
|
-
// spread structurally into its Options, so tokenmaxxing keeps its exact
|
|
14
|
-
// dependency set (zod, es-toolkit, ky).
|
|
15
|
-
|
|
16
1
|
import { z } from "zod";
|
|
17
2
|
import { UNMANAGED_ENV, resolveRealClaude } from "./lib/claudebin.ts";
|
|
18
3
|
import { evaluateAndMaybeSwap, type SwapDecision } from "./lib/decide.ts";
|
|
@@ -22,49 +7,16 @@ import { log } from "./lib/log.ts";
|
|
|
22
7
|
export { evaluateAndMaybeSwap };
|
|
23
8
|
export type { SwapDecision };
|
|
24
9
|
|
|
25
|
-
/**
|
|
26
|
-
* Run the same greedy pace-pressure decision the hooks and check timer run
|
|
27
|
-
* (never anticipatory: there is no supervisor to pause an SDK session, so a
|
|
28
|
-
* depleted pre-park would yank it onto a known-blocked account for nothing).
|
|
29
|
-
* Call it right before query() so the subprocess spawns on the best account.
|
|
30
|
-
*/
|
|
31
10
|
export async function ensureBestAccount(now = Date.now()): Promise<SwapDecision> {
|
|
32
11
|
return evaluateAndMaybeSwap(now, false);
|
|
33
12
|
}
|
|
34
13
|
|
|
35
|
-
/** The pinned real claude binary, for Options.pathToClaudeCodeExecutable.
|
|
36
|
-
* Never the supervisor wrapper: an SDK subprocess is headless print mode, so
|
|
37
|
-
* the wrapper's respawn machinery buys nothing and only adds recursion risk. */
|
|
38
14
|
export function claudeExecutablePath(): string {
|
|
39
15
|
return resolveRealClaude();
|
|
40
16
|
}
|
|
41
17
|
|
|
42
|
-
/** The pooled surface requires the DEFAULT Claude Code credential store. An
|
|
43
|
-
* ambient config-dir override desyncs the two sides of a swap on Linux: the
|
|
44
|
-
* swap (running in THIS process) writes the live credential where these vars
|
|
45
|
-
* point (credDir() honors them), while the scrubbed subprocess reads the
|
|
46
|
-
* default store - so the subprocess silently runs on a stale or absent
|
|
47
|
-
* credential. Fail fast on both platforms rather than platform-split the
|
|
48
|
-
* behavior (adversarial review catch, 2026-07-16). */
|
|
49
18
|
const AMBIENT_STORE_VARS = ["CLAUDE_SECURESTORAGE_CONFIG_DIR", "CLAUDE_CONFIG_DIR"] as const;
|
|
50
19
|
|
|
51
|
-
/**
|
|
52
|
-
* The env an SDK-spawned claude must run under to meter the POOLED live
|
|
53
|
-
* credential: every ambient credential override is scrubbed (claude honors
|
|
54
|
-
* them BEFORE its keychain/file lookup, so one inherited ANTHROPIC_API_KEY
|
|
55
|
-
* silently meters the wrong account), and the unmanaged-zone sentinel is set
|
|
56
|
-
* so a descendant invoking `claude`/`codex` through the on-PATH wrapper gets a
|
|
57
|
-
* passthrough to the real binary instead of nested supervision (or, before
|
|
58
|
-
* this sentinel existed, a depth-cap abort that broke legitimate nested runs
|
|
59
|
-
* like a repo's `bun run validate` invoking `claude -p`). The wrap depth is
|
|
60
|
-
* NOT preset: it keeps counting real wrapper entries, so a poisoned claudeBin
|
|
61
|
-
* pin below here still dies at the cap.
|
|
62
|
-
*
|
|
63
|
-
* Returns a FULL environment, not a patch: the Agent SDK's Options.env
|
|
64
|
-
* REPLACES the subprocess env rather than merging over process.env (verified
|
|
65
|
-
* against the official TS reference 2026-07-16), which is what makes deleting
|
|
66
|
-
* keys from this copy effective.
|
|
67
|
-
*/
|
|
68
20
|
export function pooledSpawnEnv(): Record<string, string> {
|
|
69
21
|
for (const k of AMBIENT_STORE_VARS) {
|
|
70
22
|
if (process.env[k]) {
|
|
@@ -84,7 +36,6 @@ const PooledOptionsSchema = z.object({
|
|
|
84
36
|
});
|
|
85
37
|
export type PooledOptions = z.infer<typeof PooledOptionsSchema>;
|
|
86
38
|
|
|
87
|
-
/** Options fragment to spread into the Agent SDK's Options. */
|
|
88
39
|
export function pooledOptions(): PooledOptions {
|
|
89
40
|
return PooledOptionsSchema.parse({
|
|
90
41
|
pathToClaudeCodeExecutable: claudeExecutablePath(),
|
|
@@ -92,16 +43,6 @@ export function pooledOptions(): PooledOptions {
|
|
|
92
43
|
});
|
|
93
44
|
}
|
|
94
45
|
|
|
95
|
-
/**
|
|
96
|
-
* Agent SDK Stop-hook callback (structurally matches HookCallback; the args
|
|
97
|
-
* are irrelevant here; `{}` is the documented no-op output). Runs the switch
|
|
98
|
-
* decision at the turn boundary; a swap landed here takes effect on the next
|
|
99
|
-
* subprocess spawn. Errors are caught LOUDLY (stderr + log), not rethrown:
|
|
100
|
-
* the SDK hooks reference states an unhandled exception can interrupt the
|
|
101
|
-
* agent (verified 2026-07-16), and aborting the caller's turn because a
|
|
102
|
-
* switch check failed costs more than riding out the current account. Call
|
|
103
|
-
* ensureBestAccount() directly where a broken pool should throw.
|
|
104
|
-
*/
|
|
105
46
|
export async function stopHookCheck(): Promise<Record<string, never>> {
|
|
106
47
|
try {
|
|
107
48
|
await evaluateAndMaybeSwap(Date.now(), false);
|