oc-codex-multi-auth 6.3.4 → 6.4.1

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 (43) hide show
  1. package/README.md +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +18 -7
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/accounts/rotation.d.ts +30 -0
  6. package/dist/lib/accounts/rotation.d.ts.map +1 -1
  7. package/dist/lib/accounts/rotation.js +85 -28
  8. package/dist/lib/accounts/rotation.js.map +1 -1
  9. package/dist/lib/accounts/warm-request.d.ts +54 -0
  10. package/dist/lib/accounts/warm-request.d.ts.map +1 -0
  11. package/dist/lib/accounts/warm-request.js +134 -0
  12. package/dist/lib/accounts/warm-request.js.map +1 -0
  13. package/dist/lib/accounts/warm.d.ts +71 -0
  14. package/dist/lib/accounts/warm.d.ts.map +1 -0
  15. package/dist/lib/accounts/warm.js +86 -0
  16. package/dist/lib/accounts/warm.js.map +1 -0
  17. package/dist/lib/accounts.d.ts +9 -0
  18. package/dist/lib/accounts.d.ts.map +1 -1
  19. package/dist/lib/accounts.js +19 -0
  20. package/dist/lib/accounts.js.map +1 -1
  21. package/dist/lib/config.d.ts +17 -0
  22. package/dist/lib/config.d.ts.map +1 -1
  23. package/dist/lib/config.js +30 -0
  24. package/dist/lib/config.js.map +1 -1
  25. package/dist/lib/rotation.d.ts +15 -0
  26. package/dist/lib/rotation.d.ts.map +1 -1
  27. package/dist/lib/rotation.js +26 -0
  28. package/dist/lib/rotation.js.map +1 -1
  29. package/dist/lib/schemas.d.ts +5 -0
  30. package/dist/lib/schemas.d.ts.map +1 -1
  31. package/dist/lib/schemas.js +1 -0
  32. package/dist/lib/schemas.js.map +1 -1
  33. package/dist/lib/tools/codex-help.d.ts.map +1 -1
  34. package/dist/lib/tools/codex-help.js +1 -0
  35. package/dist/lib/tools/codex-help.js.map +1 -1
  36. package/dist/lib/tools/codex-warm.d.ts +33 -0
  37. package/dist/lib/tools/codex-warm.d.ts.map +1 -0
  38. package/dist/lib/tools/codex-warm.js +119 -0
  39. package/dist/lib/tools/codex-warm.js.map +1 -0
  40. package/dist/lib/tools/index.d.ts.map +1 -1
  41. package/dist/lib/tools/index.js +2 -0
  42. package/dist/lib/tools/index.js.map +1 -1
  43. package/package.json +1 -1
@@ -14,9 +14,39 @@ import type { AccountState, ManagedAccount } from "./state.js";
14
14
  export declare class AccountRotation {
15
15
  private readonly state;
16
16
  constructor(state: AccountState);
17
+ /**
18
+ * Whether an account can serve a request for this (family, model) right now:
19
+ * enabled, not rate-limited (real server 429s tracked in rateLimitResetTimes),
20
+ * not cooling down, AND its in-memory local token bucket has a token.
21
+ *
22
+ * The token-bucket check is what keeps a locally-depleted account out of
23
+ * selection. It is intentionally evaluated here (in-memory, per-process)
24
+ * rather than by writing a synthetic window into the persisted
25
+ * rateLimitResetTimes — that would leak a per-process proactive-limiter
26
+ * signal into the cross-process accounts file and spuriously rate-limit
27
+ * server-healthy accounts in other processes.
28
+ */
29
+ private isSelectable;
17
30
  getCurrentOrNextForFamily(family: ModelFamily, model?: string | null): ManagedAccount | null;
18
31
  getNextForFamily(family: ModelFamily, model?: string | null): ManagedAccount | null;
19
32
  getCurrentOrNextForFamilyHybrid(family: ModelFamily, model?: string | null, options?: HybridSelectionOptions): ManagedAccount | null;
33
+ /**
34
+ * Drain-first ("sticky") selection for issue #183.
35
+ *
36
+ * Stays on the current account for the family while it remains healthy
37
+ * (not disabled, not rate-limited for this family/model, not cooling down).
38
+ * When the current account is unavailable, it picks the *lowest-indexed*
39
+ * available account rather than spreading load. This concentrates traffic
40
+ * on as few accounts as possible so the remaining accounts keep their
41
+ * quota in reserve — staggering weekly-quota cooldowns instead of
42
+ * exhausting every account simultaneously (the round-robin failure mode the
43
+ * issue describes).
44
+ *
45
+ * Returns null when no account is available (every account disabled,
46
+ * rate-limited, or cooling down), matching the other selectors' contract so
47
+ * the request loop's wait/retry logic is unchanged.
48
+ */
49
+ getCurrentOrNextForFamilySticky(family: ModelFamily, model?: string | null): ManagedAccount | null;
20
50
  recordSuccess(account: ManagedAccount, family: ModelFamily, model?: string | null): void;
21
51
  recordRateLimit(account: ManagedAccount, family: ModelFamily, model?: string | null): void;
22
52
  recordFailure(account: ManagedAccount, family: ModelFamily, model?: string | null): void;
@@ -1 +1 @@
1
- {"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../../lib/accounts/rotation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAKN,KAAK,sBAAsB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAIN,KAAK,eAAe,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D,qBAAa,eAAe;IACf,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,YAAY;IAEhD,yBAAyB,CACxB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,cAAc,GAAG,IAAI;IA6BxB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,GAAG,IAAI;IA4BnF,+BAA+B,CAC9B,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC9B,cAAc,GAAG,IAAI;IA8DxB,aAAa,CACZ,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAKP,eAAe,CACd,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAMP,aAAa,CACZ,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAKP,YAAY,CACX,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO;IAKV;;;;OAIG;IACH,WAAW,CACV,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO;IAKV,eAAe,CACd,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAIP,yBAAyB,CACxB,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,eAAe,EACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAeP,sBAAsB,CACrB,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GACpB,IAAI;IAMP;;;OAGG;IACH,uCAAuC,CACtC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GACpB,MAAM;IAUT,uBAAuB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;CAuC3E"}
1
+ {"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../../lib/accounts/rotation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAKN,KAAK,sBAAsB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAIN,KAAK,eAAe,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D,qBAAa,eAAe;IACf,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,YAAY;IAEhD;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,YAAY;IAapB,yBAAyB,CACxB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,cAAc,GAAG,IAAI;IAqBxB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,GAAG,IAAI;IAoBnF,+BAA+B,CAC9B,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC9B,cAAc,GAAG,IAAI;IAoDxB;;;;;;;;;;;;;;;OAeG;IACH,+BAA+B,CAC9B,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,cAAc,GAAG,IAAI;IA8BxB,aAAa,CACZ,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAKP,eAAe,CACd,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAMP,aAAa,CACZ,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAKP,YAAY,CACX,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO;IAKV;;;;OAIG;IACH,WAAW,CACV,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO;IAKV,eAAe,CACd,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAIP,yBAAyB,CACxB,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,eAAe,EACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAeP,sBAAsB,CACrB,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GACpB,IAAI;IAMP;;;OAGG;IACH,uCAAuC,CACtC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GACpB,MAAM;IAUT,uBAAuB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;CA+C3E"}
@@ -14,6 +14,29 @@ export class AccountRotation {
14
14
  constructor(state) {
15
15
  this.state = state;
16
16
  }
17
+ /**
18
+ * Whether an account can serve a request for this (family, model) right now:
19
+ * enabled, not rate-limited (real server 429s tracked in rateLimitResetTimes),
20
+ * not cooling down, AND its in-memory local token bucket has a token.
21
+ *
22
+ * The token-bucket check is what keeps a locally-depleted account out of
23
+ * selection. It is intentionally evaluated here (in-memory, per-process)
24
+ * rather than by writing a synthetic window into the persisted
25
+ * rateLimitResetTimes — that would leak a per-process proactive-limiter
26
+ * signal into the cross-process accounts file and spuriously rate-limit
27
+ * server-healthy accounts in other processes.
28
+ */
29
+ isSelectable(account, family, model) {
30
+ if (account.enabled === false)
31
+ return false;
32
+ clearExpiredRateLimits(account);
33
+ if (isRateLimitedForFamily(account, family, model))
34
+ return false;
35
+ if (this.state.isAccountCoolingDown(account))
36
+ return false;
37
+ const quotaKey = model ? `${family}:${model}` : family;
38
+ return getTokenTracker().hasToken(account.index, quotaKey);
39
+ }
17
40
  getCurrentOrNextForFamily(family, model) {
18
41
  const count = this.state.accounts.length;
19
42
  if (count === 0)
@@ -24,13 +47,8 @@ export class AccountRotation {
24
47
  const account = this.state.accounts[idx];
25
48
  if (!account)
26
49
  continue;
27
- if (account.enabled === false)
50
+ if (!this.isSelectable(account, family, model))
28
51
  continue;
29
- clearExpiredRateLimits(account);
30
- if (isRateLimitedForFamily(account, family, model) ||
31
- this.state.isAccountCoolingDown(account)) {
32
- continue;
33
- }
34
52
  this.state.cursorByFamily[family] = (idx + 1) % count;
35
53
  this.state.currentAccountIndexByFamily[family] = idx;
36
54
  account.lastUsed = nowMs();
@@ -48,13 +66,8 @@ export class AccountRotation {
48
66
  const account = this.state.accounts[idx];
49
67
  if (!account)
50
68
  continue;
51
- if (account.enabled === false)
52
- continue;
53
- clearExpiredRateLimits(account);
54
- if (isRateLimitedForFamily(account, family, model) ||
55
- this.state.isAccountCoolingDown(account)) {
69
+ if (!this.isSelectable(account, family, model))
56
70
  continue;
57
- }
58
71
  this.state.cursorByFamily[family] = (idx + 1) % count;
59
72
  account.lastUsed = nowMs();
60
73
  return account;
@@ -72,13 +85,9 @@ export class AccountRotation {
72
85
  if (currentAccount.enabled === false) {
73
86
  // Fall through to hybrid selection.
74
87
  }
75
- else {
76
- clearExpiredRateLimits(currentAccount);
77
- if (!isRateLimitedForFamily(currentAccount, family, model) &&
78
- !this.state.isAccountCoolingDown(currentAccount)) {
79
- currentAccount.lastUsed = nowMs();
80
- return currentAccount;
81
- }
88
+ else if (this.isSelectable(currentAccount, family, model)) {
89
+ currentAccount.lastUsed = nowMs();
90
+ return currentAccount;
82
91
  }
83
92
  }
84
93
  }
@@ -91,12 +100,9 @@ export class AccountRotation {
91
100
  return null;
92
101
  if (account.enabled === false)
93
102
  return null;
94
- clearExpiredRateLimits(account);
95
- const isAvailable = !isRateLimitedForFamily(account, family, model) &&
96
- !this.state.isAccountCoolingDown(account);
97
103
  return {
98
104
  index: account.index,
99
- isAvailable,
105
+ isAvailable: this.isSelectable(account, family, model),
100
106
  lastUsed: account.lastUsed,
101
107
  };
102
108
  })
@@ -112,6 +118,50 @@ export class AccountRotation {
112
118
  account.lastUsed = nowMs();
113
119
  return account;
114
120
  }
121
+ /**
122
+ * Drain-first ("sticky") selection for issue #183.
123
+ *
124
+ * Stays on the current account for the family while it remains healthy
125
+ * (not disabled, not rate-limited for this family/model, not cooling down).
126
+ * When the current account is unavailable, it picks the *lowest-indexed*
127
+ * available account rather than spreading load. This concentrates traffic
128
+ * on as few accounts as possible so the remaining accounts keep their
129
+ * quota in reserve — staggering weekly-quota cooldowns instead of
130
+ * exhausting every account simultaneously (the round-robin failure mode the
131
+ * issue describes).
132
+ *
133
+ * Returns null when no account is available (every account disabled,
134
+ * rate-limited, or cooling down), matching the other selectors' contract so
135
+ * the request loop's wait/retry logic is unchanged.
136
+ */
137
+ getCurrentOrNextForFamilySticky(family, model) {
138
+ const count = this.state.accounts.length;
139
+ if (count === 0)
140
+ return null;
141
+ // Prefer the account we are already pinned to while it still has quota.
142
+ const currentIndex = this.state.currentAccountIndexByFamily[family];
143
+ if (currentIndex >= 0 && currentIndex < count) {
144
+ const currentAccount = this.state.accounts[currentIndex];
145
+ if (currentAccount && this.isSelectable(currentAccount, family, model)) {
146
+ currentAccount.lastUsed = nowMs();
147
+ return currentAccount;
148
+ }
149
+ }
150
+ // Current account exhausted: pick the lowest-indexed available account so
151
+ // load concentrates rather than spreads.
152
+ for (let idx = 0; idx < count; idx++) {
153
+ const account = this.state.accounts[idx];
154
+ if (!account)
155
+ continue;
156
+ if (!this.isSelectable(account, family, model))
157
+ continue;
158
+ this.state.currentAccountIndexByFamily[family] = idx;
159
+ this.state.cursorByFamily[family] = (idx + 1) % count;
160
+ account.lastUsed = nowMs();
161
+ return account;
162
+ }
163
+ return null;
164
+ }
115
165
  recordSuccess(account, family, model) {
116
166
  const quotaKey = model ? `${family}:${model}` : family;
117
167
  getHealthTracker().recordSuccess(account.index, quotaKey);
@@ -171,11 +221,7 @@ export class AccountRotation {
171
221
  getMinWaitTimeForFamily(family, model) {
172
222
  const now = nowMs();
173
223
  const enabledAccounts = this.state.accounts.filter((account) => account.enabled !== false);
174
- const available = enabledAccounts.filter((account) => {
175
- clearExpiredRateLimits(account);
176
- return (!isRateLimitedForFamily(account, family, model) &&
177
- !this.state.isAccountCoolingDown(account));
178
- });
224
+ const available = enabledAccounts.filter((account) => this.isSelectable(account, family, model));
179
225
  if (available.length > 0)
180
226
  return 0;
181
227
  if (enabledAccounts.length === 0)
@@ -183,6 +229,8 @@ export class AccountRotation {
183
229
  const waitTimes = [];
184
230
  const baseKey = getQuotaKey(family);
185
231
  const modelKey = model ? getQuotaKey(family, model) : null;
232
+ const tokenQuotaKey = model ? `${family}:${model}` : family;
233
+ const tokenTracker = getTokenTracker();
186
234
  for (const account of enabledAccounts) {
187
235
  const baseResetAt = account.rateLimitResetTimes[baseKey];
188
236
  if (typeof baseResetAt === "number") {
@@ -197,6 +245,15 @@ export class AccountRotation {
197
245
  if (typeof account.coolingDownUntil === "number") {
198
246
  waitTimes.push(Math.max(0, account.coolingDownUntil - now));
199
247
  }
248
+ // An account blocked only by a depleted local token bucket becomes
249
+ // available again after refill; include that wait so a fully
250
+ // token-depleted pool waits for refill instead of returning 0 (503).
251
+ if (account.enabled !== false) {
252
+ const tokenWait = tokenTracker.msUntilToken(account.index, tokenQuotaKey);
253
+ if (tokenWait > 0 && Number.isFinite(tokenWait)) {
254
+ waitTimes.push(tokenWait);
255
+ }
256
+ }
200
257
  }
201
258
  return waitTimes.length > 0 ? Math.min(...waitTimes) : 0;
202
259
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../../lib/accounts/rotation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../../lib/accounts/rotation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Real upstream "warm" request for issue #182.
3
+ *
4
+ * Sends a single minimal billable request to `POST /codex/responses` — the
5
+ * same endpoint and request shape the live request path uses for its quota
6
+ * probe — so the account's rolling usage window actually starts. A read-only
7
+ * `GET /wham/usage` does NOT open the window (it only reports server-side
8
+ * windows that already exist), so warming must send a genuine inference
9
+ * request. The body is deliberately tiny (reasoning effort "none", verbosity
10
+ * "low", no stored conversation) to keep the quota cost negligible, and mirrors
11
+ * the proven quota-probe request shape used by the live request path.
12
+ *
13
+ * This module owns the network side-effect; the pure iteration/summary logic
14
+ * lives in `warm.ts` and is injected this function via `codex-warm.ts`.
15
+ */
16
+ import type { RequestBody } from "../types.js";
17
+ export interface WarmRequestParams {
18
+ accountId: string;
19
+ accessToken: string;
20
+ organizationId: string | undefined;
21
+ /** Override the timeout (tests). */
22
+ timeoutMs?: number;
23
+ /** Injectable fetch for tests; defaults to global fetch. */
24
+ fetchImpl?: typeof fetch;
25
+ }
26
+ /**
27
+ * Build the minimal warm-ping request body. Exported for tests so the exact
28
+ * shape (stream/store/reasoning) stays pinned.
29
+ */
30
+ export declare function buildWarmRequestBody(model?: string): Promise<RequestBody>;
31
+ /**
32
+ * Outcome of a warm request.
33
+ * - `opened`: the request started/confirmed the usage window (2xx, or a 429
34
+ * whose reason is a transient token/concurrency limit — the window is ticking).
35
+ * - `exhausted`: a 429 whose reason is quota/usage-limit — the account's window
36
+ * is already spent, so warming it is meaningless. Reported distinctly so the
37
+ * tool does not claim a quota-dead account was "warmed".
38
+ */
39
+ export type WarmRequestStatus = "opened" | "exhausted";
40
+ export interface WarmRequestResult {
41
+ status: WarmRequestStatus;
42
+ detail?: string;
43
+ }
44
+ /**
45
+ * Send one warm request to open the account's usage window.
46
+ *
47
+ * Resolves with `{ status: "opened" }` when the upstream started/confirmed the
48
+ * window (2xx, or a non-quota 429 meaning the window is already active), or
49
+ * `{ status: "exhausted" }` for a quota/usage-limit 429 (window already spent).
50
+ * Any other non-2xx, or a network/timeout error, throws so the caller records
51
+ * the account as failed.
52
+ */
53
+ export declare function warmAccountWindow(params: WarmRequestParams): Promise<WarmRequestResult>;
54
+ //# sourceMappingURL=warm-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm-request.d.ts","sourceRoot":"","sources":["../../../lib/accounts/warm-request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAW/C,MAAM,WAAW,iBAAiB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,SAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBnF;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACtC,MAAM,EAAE,iBAAiB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CA4D5B"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Real upstream "warm" request for issue #182.
3
+ *
4
+ * Sends a single minimal billable request to `POST /codex/responses` — the
5
+ * same endpoint and request shape the live request path uses for its quota
6
+ * probe — so the account's rolling usage window actually starts. A read-only
7
+ * `GET /wham/usage` does NOT open the window (it only reports server-side
8
+ * windows that already exist), so warming must send a genuine inference
9
+ * request. The body is deliberately tiny (reasoning effort "none", verbosity
10
+ * "low", no stored conversation) to keep the quota cost negligible, and mirrors
11
+ * the proven quota-probe request shape used by the live request path.
12
+ *
13
+ * This module owns the network side-effect; the pure iteration/summary logic
14
+ * lives in `warm.ts` and is injected this function via `codex-warm.ts`.
15
+ */
16
+ import { CODEX_BASE_URL } from "../constants.js";
17
+ import { createCodexHeaders } from "../request/fetch-helpers.js";
18
+ import { getCodexInstructions } from "../prompts/codex.js";
19
+ import { parseRateLimitReason } from "./rate-limits.js";
20
+ import { createLogger } from "../logger.js";
21
+ const log = createLogger("warm-request");
22
+ /** Model used for the warm ping. Mirrors the live quota-probe default. */
23
+ const WARM_MODEL = "gpt-5.4";
24
+ /** Hard ceiling on a warm request so a hung upstream cannot wedge the batch. */
25
+ const WARM_TIMEOUT_MS = 15_000;
26
+ /**
27
+ * Build the minimal warm-ping request body. Exported for tests so the exact
28
+ * shape (stream/store/reasoning) stays pinned.
29
+ */
30
+ export async function buildWarmRequestBody(model = WARM_MODEL) {
31
+ const instructions = await getCodexInstructions(model);
32
+ return {
33
+ model,
34
+ stream: true,
35
+ store: false,
36
+ include: ["reasoning.encrypted_content"],
37
+ instructions,
38
+ input: [
39
+ {
40
+ type: "message",
41
+ role: "user",
42
+ content: [{ type: "input_text", text: "warm ping" }],
43
+ },
44
+ ],
45
+ reasoning: { effort: "none", summary: "auto" },
46
+ text: { verbosity: "low" },
47
+ };
48
+ }
49
+ /**
50
+ * Send one warm request to open the account's usage window.
51
+ *
52
+ * Resolves with `{ status: "opened" }` when the upstream started/confirmed the
53
+ * window (2xx, or a non-quota 429 meaning the window is already active), or
54
+ * `{ status: "exhausted" }` for a quota/usage-limit 429 (window already spent).
55
+ * Any other non-2xx, or a network/timeout error, throws so the caller records
56
+ * the account as failed.
57
+ */
58
+ export async function warmAccountWindow(params) {
59
+ const doFetch = params.fetchImpl ?? fetch;
60
+ const body = await buildWarmRequestBody();
61
+ const headers = createCodexHeaders(undefined, params.accountId, params.accessToken, {
62
+ model: WARM_MODEL,
63
+ organizationId: params.organizationId,
64
+ });
65
+ const controller = new AbortController();
66
+ const timeout = setTimeout(() => controller.abort(), params.timeoutMs ?? WARM_TIMEOUT_MS);
67
+ try {
68
+ const response = await doFetch(`${CODEX_BASE_URL}/codex/responses`, {
69
+ method: "POST",
70
+ headers,
71
+ body: JSON.stringify(body),
72
+ signal: controller.signal,
73
+ });
74
+ if (response.ok) {
75
+ // Drain/cancel the SSE stream — we only needed to start the window.
76
+ try {
77
+ await response.body?.cancel();
78
+ }
79
+ catch {
80
+ // Ignore cancellation failures.
81
+ }
82
+ return { status: "opened" };
83
+ }
84
+ // Read the error body (small) BEFORE classifying so a 429 quota-exhausted
85
+ // account is not mis-reported as warmed.
86
+ let bodyText = "";
87
+ try {
88
+ bodyText = (await response.text()).slice(0, 2048);
89
+ }
90
+ catch {
91
+ // Ignore body-read failures; fall back to status-only classification.
92
+ }
93
+ if (response.status === 429) {
94
+ const reason = parseRateLimitReason(extractErrorCode(bodyText));
95
+ if (reason === "quota") {
96
+ log.debug("Warm ping hit 429 quota limit — account window already spent", {
97
+ accountId: params.accountId,
98
+ });
99
+ return { status: "exhausted", detail: "quota/usage limit reached" };
100
+ }
101
+ // token/concurrent/unknown → the window is active and ticking.
102
+ log.debug("Warm ping hit 429 — window already active", {
103
+ accountId: params.accountId,
104
+ reason,
105
+ });
106
+ return { status: "opened" };
107
+ }
108
+ throw new Error(`Warm request failed: HTTP ${response.status}`);
109
+ }
110
+ finally {
111
+ clearTimeout(timeout);
112
+ }
113
+ }
114
+ /**
115
+ * Pull a rate-limit error code/message out of a JSON or plain-text error body
116
+ * so {@link parseRateLimitReason} can classify the 429. Best-effort: returns
117
+ * the raw text when JSON parsing fails so substring matching still works.
118
+ */
119
+ function extractErrorCode(bodyText) {
120
+ if (!bodyText)
121
+ return undefined;
122
+ try {
123
+ const parsed = JSON.parse(bodyText);
124
+ return (parsed.error?.code ??
125
+ parsed.error?.type ??
126
+ parsed.error?.message ??
127
+ parsed.code ??
128
+ bodyText);
129
+ }
130
+ catch {
131
+ return bodyText;
132
+ }
133
+ }
134
+ //# sourceMappingURL=warm-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm-request.js","sourceRoot":"","sources":["../../../lib/accounts/warm-request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Account "warm-up" orchestrator (issue #182).
3
+ *
4
+ * Sends one minimal request to each enabled account so its rolling usage
5
+ * window (the ~5h ChatGPT/Codex quota window) starts ticking immediately,
6
+ * rather than only when the rotation eventually lands on that account. This
7
+ * lets users prime every account at the start of a session ("send a hi to each
8
+ * account") instead of waiting for the current account to run dry.
9
+ *
10
+ * This module is intentionally pure: it contains the iteration, outcome
11
+ * classification, and summary logic, but performs no network or auth I/O
12
+ * itself. The real upstream call is injected as `warmOne`, which keeps this
13
+ * logic fully deterministic and unit-testable, and keeps the network-touching
14
+ * adapter isolated in the `codex-warm` tool. The split mirrors how
15
+ * `lib/rotation.ts` (pure selection) is separated from `lib/accounts/rotation.ts`
16
+ * (the manager-facing wrapper).
17
+ */
18
+ /**
19
+ * Per-account result of a warm attempt.
20
+ *
21
+ * - `warmed`: the upstream request succeeded; the window is now open.
22
+ * - `failed`: the upstream request was attempted but errored (auth invalid,
23
+ * network error, upstream 5xx, etc.). `detail` carries a short reason.
24
+ * - `skipped`: the account was not attempted (e.g. disabled). `detail` says why.
25
+ */
26
+ export type WarmStatus = "warmed" | "failed" | "skipped";
27
+ export interface WarmOutcome {
28
+ status: WarmStatus;
29
+ /** Short human-readable reason, primarily for `failed` / `skipped`. */
30
+ detail?: string;
31
+ }
32
+ /** A warm result paired with the account it belongs to. */
33
+ export interface WarmAccountResult<A> {
34
+ account: A;
35
+ /** Zero-based position in the input list (stable for display ordering). */
36
+ index: number;
37
+ status: WarmStatus;
38
+ detail?: string;
39
+ }
40
+ export interface WarmSummary<A> {
41
+ results: WarmAccountResult<A>[];
42
+ warmedCount: number;
43
+ failedCount: number;
44
+ skippedCount: number;
45
+ /** Total accounts considered (= results.length). */
46
+ total: number;
47
+ }
48
+ export interface WarmAccountsOptions {
49
+ /**
50
+ * Run warm attempts concurrently (default) or strictly one at a time.
51
+ * Sequential mode is useful when the caller wants to avoid bursting the
52
+ * upstream with parallel requests. Defaults to `true` (concurrent).
53
+ */
54
+ concurrent?: boolean;
55
+ }
56
+ /**
57
+ * Warm every account in `accounts` by invoking `warmOne` on each one that is
58
+ * eligible, then summarize the outcomes.
59
+ *
60
+ * `warmOne` must resolve (never reject) — but to be defensive against an
61
+ * injected function that throws or rejects, any thrown error is captured and
62
+ * recorded as a `failed` outcome so a single bad account can never abort the
63
+ * whole batch.
64
+ *
65
+ * The returned `results` array preserves the input order regardless of
66
+ * concurrency, so display output is deterministic.
67
+ */
68
+ export declare function warmAccounts<A extends {
69
+ enabled?: boolean;
70
+ }>(accounts: readonly A[], warmOne: (account: A, index: number) => Promise<WarmOutcome>, options?: WarmAccountsOptions): Promise<WarmSummary<A>>;
71
+ //# sourceMappingURL=warm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm.d.ts","sourceRoot":"","sources":["../../../lib/accounts/warm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,2DAA2D;AAC3D,MAAM,WAAW,iBAAiB,CAAC,CAAC;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC7B,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IACnC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAUD;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,EACjE,QAAQ,EAAE,SAAS,CAAC,EAAE,EACtB,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,EAC5D,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAgDzB"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Account "warm-up" orchestrator (issue #182).
3
+ *
4
+ * Sends one minimal request to each enabled account so its rolling usage
5
+ * window (the ~5h ChatGPT/Codex quota window) starts ticking immediately,
6
+ * rather than only when the rotation eventually lands on that account. This
7
+ * lets users prime every account at the start of a session ("send a hi to each
8
+ * account") instead of waiting for the current account to run dry.
9
+ *
10
+ * This module is intentionally pure: it contains the iteration, outcome
11
+ * classification, and summary logic, but performs no network or auth I/O
12
+ * itself. The real upstream call is injected as `warmOne`, which keeps this
13
+ * logic fully deterministic and unit-testable, and keeps the network-touching
14
+ * adapter isolated in the `codex-warm` tool. The split mirrors how
15
+ * `lib/rotation.ts` (pure selection) is separated from `lib/accounts/rotation.ts`
16
+ * (the manager-facing wrapper).
17
+ */
18
+ /**
19
+ * Decide whether an account should be warmed at all.
20
+ * Disabled accounts are skipped; everything else is attempted.
21
+ */
22
+ function shouldSkip(account) {
23
+ return account.enabled === false;
24
+ }
25
+ /**
26
+ * Warm every account in `accounts` by invoking `warmOne` on each one that is
27
+ * eligible, then summarize the outcomes.
28
+ *
29
+ * `warmOne` must resolve (never reject) — but to be defensive against an
30
+ * injected function that throws or rejects, any thrown error is captured and
31
+ * recorded as a `failed` outcome so a single bad account can never abort the
32
+ * whole batch.
33
+ *
34
+ * The returned `results` array preserves the input order regardless of
35
+ * concurrency, so display output is deterministic.
36
+ */
37
+ export async function warmAccounts(accounts, warmOne, options = {}) {
38
+ const concurrent = options.concurrent ?? true;
39
+ const runOne = async (account, index) => {
40
+ if (shouldSkip(account)) {
41
+ return { account, index, status: "skipped", detail: "disabled" };
42
+ }
43
+ try {
44
+ const outcome = await warmOne(account, index);
45
+ return { account, index, status: outcome.status, detail: outcome.detail };
46
+ }
47
+ catch (error) {
48
+ const detail = error instanceof Error ? error.message : String(error);
49
+ return { account, index, status: "failed", detail };
50
+ }
51
+ };
52
+ let results;
53
+ if (concurrent) {
54
+ results = await Promise.all(accounts.map((account, index) => runOne(account, index)));
55
+ }
56
+ else {
57
+ results = [];
58
+ for (let index = 0; index < accounts.length; index++) {
59
+ // Non-null: index is bounded by accounts.length.
60
+ const account = accounts[index];
61
+ results.push(await runOne(account, index));
62
+ }
63
+ }
64
+ // Preserve input order even though Promise.all already does; explicit for
65
+ // safety against future refactors to the concurrent branch.
66
+ results.sort((a, b) => a.index - b.index);
67
+ let warmedCount = 0;
68
+ let failedCount = 0;
69
+ let skippedCount = 0;
70
+ for (const result of results) {
71
+ if (result.status === "warmed")
72
+ warmedCount++;
73
+ else if (result.status === "failed")
74
+ failedCount++;
75
+ else
76
+ skippedCount++;
77
+ }
78
+ return {
79
+ results,
80
+ warmedCount,
81
+ failedCount,
82
+ skippedCount,
83
+ total: results.length,
84
+ };
85
+ }
86
+ //# sourceMappingURL=warm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm.js","sourceRoot":"","sources":["../../../lib/accounts/warm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA6CH;;;GAGG;AACH,SAAS,UAAU,CAAkC,OAAU;IAC9D,OAAO,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,QAAsB,EACtB,OAA4D,EAC5D,UAA+B,EAAE;IAEjC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;IAE9C,MAAM,MAAM,GAAG,KAAK,EAAE,OAAU,EAAE,KAAa,EAAiC,EAAE;QACjF,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAClE,CAAC;QACD,IAAI,CAAC;YACJ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QAC3E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QACrD,CAAC;IACF,CAAC,CAAC;IAEF,IAAI,OAA+B,CAAC;IACpC,IAAI,UAAU,EAAE,CAAC;QAChB,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACvF,CAAC;SAAM,CAAC;QACP,OAAO,GAAG,EAAE,CAAC;QACb,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;YACtD,iDAAiD;YACjD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAM,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;QAC5C,CAAC;IACF,CAAC;IAED,0EAA0E;IAC1E,4DAA4D;IAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAE1C,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ;YAAE,WAAW,EAAE,CAAC;aACzC,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ;YAAE,WAAW,EAAE,CAAC;;YAC9C,YAAY,EAAE,CAAC;IACrB,CAAC;IAED,OAAO;QACN,OAAO;QACP,WAAW;QACX,WAAW;QACX,YAAY;QACZ,KAAK,EAAE,OAAO,CAAC,MAAM;KACrB,CAAC;AACH,CAAC"}