codex-multi-auth 2.8.5 → 2.8.6
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/.codex-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/lib/accounts.d.ts +7 -0
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +10 -0
- package/dist/lib/codex-manager/commands/best.d.ts +3 -0
- package/dist/lib/codex-manager/commands/best.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/best.js +10 -1
- package/dist/lib/codex-manager/commands/forecast.d.ts +3 -0
- package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/forecast.js +18 -1
- package/dist/lib/codex-manager/commands/report.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/report.js +14 -0
- package/dist/lib/forecast.d.ts +13 -0
- package/dist/lib/forecast.d.ts.map +1 -1
- package/dist/lib/forecast.js +18 -3
- package/dist/lib/request/rate-limit-decision.d.ts +19 -1
- package/dist/lib/request/rate-limit-decision.d.ts.map +1 -1
- package/dist/lib/request/rate-limit-decision.js +34 -2
- package/dist/lib/runtime/account-status.d.ts +38 -0
- package/dist/lib/runtime/account-status.d.ts.map +1 -1
- package/dist/lib/runtime/account-status.js +68 -0
- package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.js +68 -2
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-multi-auth",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.6",
|
|
4
4
|
"description": "Install and operate codex-multi-auth for the official @openai/codex CLI with multi-account OAuth rotation, switching, health checks, and recovery tools.",
|
|
5
5
|
"interface": {
|
|
6
6
|
"composerIcon": "./assets/codex-multi-auth-icon.svg"
|
package/README.md
CHANGED
|
@@ -392,7 +392,7 @@ codex-multi-auth doctor --json
|
|
|
392
392
|
|
|
393
393
|
## Release Notes
|
|
394
394
|
|
|
395
|
-
- Current stable: [docs/releases/v2.8.
|
|
395
|
+
- Current stable: [docs/releases/v2.8.6.md](docs/releases/v2.8.6.md) — install via `npm i -g codex-multi-auth`
|
|
396
396
|
- Previous stable: [docs/releases/v2.8.3.md](docs/releases/v2.8.3.md)
|
|
397
397
|
- Previous stable: [docs/releases/v2.8.2.md](docs/releases/v2.8.2.md)
|
|
398
398
|
- Previous stable: [docs/releases/v2.7.1.md](docs/releases/v2.7.1.md)
|
package/dist/lib/accounts.d.ts
CHANGED
|
@@ -193,6 +193,13 @@ export declare class AccountManager {
|
|
|
193
193
|
isAccountCoolingDown(account: ManagedAccount): boolean;
|
|
194
194
|
clearAccountCooldown(account: ManagedAccount): void;
|
|
195
195
|
private isCircuitAvailable;
|
|
196
|
+
/**
|
|
197
|
+
* When the account's circuit breaker will admit an attempt again, as an
|
|
198
|
+
* epoch-ms deadline — null when it already would. Lets the pinned-503
|
|
199
|
+
* recovery metadata cover circuit-open skips, whose deadline lives in the
|
|
200
|
+
* breaker rather than the persisted account record.
|
|
201
|
+
*/
|
|
202
|
+
getCircuitRecoveryTime(account: ManagedAccount, now?: number): number | null;
|
|
196
203
|
incrementAuthFailures(account: ManagedAccount): number;
|
|
197
204
|
clearAuthFailures(account: ManagedAccount): void;
|
|
198
205
|
markAuthInvalidated(account: ManagedAccount, errorCode?: string, invalidatedAt?: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../lib/accounts.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../lib/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAI1C,OAAO,EAKN,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAGrB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,EAMN,KAAK,sBAAsB,EAC3B,MAAM,eAAe,CAAC;AACvB,OAAO,EAEN,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,MAAM,oBAAoB,CAAC;AAqB5B,OAAO,EACN,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,6BAA6B,EAC7B,8BAA8B,EAC9B,uBAAuB,EACvB,aAAa,EACb,KAAK,kBAAkB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACN,oBAAoB,EACpB,WAAW,EACX,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,cAAc,EACd,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACN,2BAA2B,EAC3B,qBAAqB,EACrB,KAAK,uBAAuB,GAC5B,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAON,KAAK,eAAe,EACpB,MAAM,2BAA2B,CAAC;AA2CnC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,MAAM,CAQ7E;AAQD,KAAK,wBAAwB,GAAG,IAAI,CACnC,cAAc,EACd,WAAW,GAAG,OAAO,GAAG,cAAc,CACtC,GAAG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AA2GF,YAAY,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAE3D,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,yCAAoC,CAAC;AAE1E,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EACd,YAAY,GACZ,SAAS,GACT,UAAU,GACV,MAAM,GACN,SAAS,GACT,QAAQ,CAAC;IACZ,mBAAmB,CAAC,EAAE,eAAe,CAAC;IACtC,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,cAAc,CAAmD;IACzE,OAAO,CAAC,2BAA2B,CACd;IACrB,OAAO,CAAC,qBAAqB,CAAM;IACnC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,iBAAiB,CAA8C;IACvE,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB,CAAqB;IAC/C;;;;OAIG;IACH,OAAO,CAAC,kBAAkB,CAAS;IACnC;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB,CAA8B;WAEzC,YAAY,CACxB,YAAY,CAAC,EAAE,gBAAgB,GAC7B,OAAO,CAAC,cAAc,CAAC;IAmB1B,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;YAMhC,mBAAmB;gBAqEhC,YAAY,CAAC,EAAE,gBAAgB,EAC/B,MAAM,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAyMjC,eAAe,IAAI,MAAM;IAIzB,cAAc,IAAI,MAAM;IAIxB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IAqBpD,mBAAmB,IAAI,cAAc,EAAE;IAavC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAOvD,2BAA2B,CAC1B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO;IAcV,2BAA2B,CAC1B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,MAAM,GAAG,IAAI;IAMhB;;;;;OAKG;IACH,kCAAkC,CACjC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,MAAM,GAAG,IAAI;IAehB,MAAM,CAAC,yBAAyB,IAAI,IAAI;IAKxC;;;;;;;;;;;;;;;;OAgBG;IACH,0BAA0B,IAAI,IAAI;IAYlC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAkB9C,mCAAmC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcvE,iBAAiB,IAAI,cAAc,GAAG,IAAI;IAI1C,0BAA0B,CAAC,MAAM,EAAE,WAAW,GAAG,cAAc,GAAG,IAAI;IAYtE,gBAAgB,IAAI,cAAc,GAAG,IAAI;IAIzC,yBAAyB,CACxB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,cAAc,GAAG,IAAI;IAgCxB,gBAAgB,CACf,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,cAAc,GAAG,IAAI;IA+BxB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,mCAAmC,CAClC,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC,cAAc,GAAG,IAAI;IAmDxB,+BAA+B,CAC9B,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,OAAO,CAAC,EAAE,sBAAsB,GAC9B,cAAc,GAAG,IAAI;IA+CxB,aAAa,CACZ,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IA2BP,eAAe,CACd,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IASP,aAAa,CACZ,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAOP,YAAY,CACX,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO;IAiBV;;;;OAIG;IACH,WAAW,CACV,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO;IAMV,YAAY,CACX,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,EACxD,MAAM,EAAE,WAAW,GACjB,IAAI;IAeP;;;;;OAKG;IACH,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAIjD,2EAA2E;IAC3E,mBAAmB,IAAI,gBAAgB;IAIvC;;;;;;;OAOG;IACG,kBAAkB,CACvB,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,EACxD,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GACpD,OAAO,CAAC,eAAe,CAAC;IA4B3B;;;OAGG;IACG,4BAA4B,CACjC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GACpB,OAAO,CAAC,IAAI,CAAC;IAQhB;;;;OAIG;IACG,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAMzE,eAAe,CACd,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,IAAI;IAUP,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;IA2BP,sBAAsB,CACrB,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,cAAc,GACpB,IAAI;IAMP,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO;IAStD,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAKnD,OAAO,CAAC,kBAAkB;IAI1B;;;;;OAKG;IACH,sBAAsB,CACrB,OAAO,EAAE,cAAc,EACvB,GAAG,SAAa,GACd,MAAM,GAAG,IAAI;IAOhB,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM;IAMtD,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIhD,mBAAmB,CAClB,OAAO,EAAE,cAAc,EACvB,SAAS,SAAsB,EAC/B,aAAa,SAAU,GACrB,IAAI;IAKP,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAKpD,wBAAwB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO;IAQ1D,oBAAoB,CACnB,SAAS,EAAE,wBAAwB,EACnC,IAAI,CAAC,EAAE,gBAAgB,GACrB,cAAc,GAAG,IAAI;IAQxB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,SAAQ,GAAG,OAAO;IAWzE,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAK1C,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAiBrE;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,uBAAuB;IAuD/B,OAAO,CAAC,oBAAoB;IAyFtB,mBAAmB,CACxB,MAAM,EAAE,IAAI,CACX,cAAc,EACd,OAAO,GAAG,WAAW,GAAG,OAAO,GAAG,cAAc,CAChD,EACD,IAAI,EAAE,gBAAgB,GACpB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAmIjC,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAS5C,cAAc,IAAI,MAAM;IAIxB,uBAAuB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;IAsD3E;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAcvB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO;IAmJ/C,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAQ5C,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI;IA6CnE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC,mBAAmB,CAAC,OAAO,SAAM,GAAG,IAAI;IAyBlC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAYvC,OAAO,CAAC,eAAe;IAiBvB,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI;IAQ9D,uBAAuB,CACtB,OAAO,EAAE,cAAc,EACvB,mBAAmB,CAAC,EAAE,MAAM,GAC1B,OAAO;IAqBV,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI;IAoBhE;;;OAGG;IACH,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO;IAOtD,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM;IAIlD,wBAAwB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM;CAIzD;AAmBD,wBAAgB,kBAAkB,CACjC,OAAO,EACJ;IACA,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC9B,GACD,SAAS,EACZ,KAAK,EAAE,MAAM,GACX,MAAM,CA4BR;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EACJ;IAAE,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D,SAAS,EACZ,MAAM,SAAQ,GACZ,MAAM,EAAE,CAgBV;AAED,wBAAgB,cAAc,CAC7B,OAAO,EAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/D,GAAG,SAAU,GACX,MAAM,GAAG,IAAI,CAMf"}
|
package/dist/lib/accounts.js
CHANGED
|
@@ -926,6 +926,16 @@ export class AccountManager {
|
|
|
926
926
|
isCircuitAvailable(account) {
|
|
927
927
|
return getCircuitBreaker(getAccountCircuitKey(account)).isAvailable();
|
|
928
928
|
}
|
|
929
|
+
/**
|
|
930
|
+
* When the account's circuit breaker will admit an attempt again, as an
|
|
931
|
+
* epoch-ms deadline — null when it already would. Lets the pinned-503
|
|
932
|
+
* recovery metadata cover circuit-open skips, whose deadline lives in the
|
|
933
|
+
* breaker rather than the persisted account record.
|
|
934
|
+
*/
|
|
935
|
+
getCircuitRecoveryTime(account, now = Date.now()) {
|
|
936
|
+
const waitMs = getCircuitBreaker(getAccountCircuitKey(account)).getTimeUntilAvailable(now);
|
|
937
|
+
return waitMs > 0 ? now + waitMs : null;
|
|
938
|
+
}
|
|
929
939
|
incrementAuthFailures(account) {
|
|
930
940
|
account.consecutiveAuthFailures =
|
|
931
941
|
(account.consecutiveAuthFailures ?? 0) + 1;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ForecastAccountResult } from "../../forecast.js";
|
|
2
2
|
import { type CodexQuotaSnapshot } from "../../quota-probe.js";
|
|
3
|
+
import { type ModelFamily } from "../../request/helpers/model-map.js";
|
|
3
4
|
import type { AccountStorageV3 } from "../../storage.js";
|
|
4
5
|
import type { TokenFailure, TokenResult } from "../../types.js";
|
|
5
6
|
export interface BestCliOptions {
|
|
@@ -56,6 +57,8 @@ export interface BestCommandDeps {
|
|
|
56
57
|
now: number;
|
|
57
58
|
refreshFailure?: TokenFailure;
|
|
58
59
|
liveQuota?: CodexQuotaSnapshot;
|
|
60
|
+
family?: ModelFamily;
|
|
61
|
+
model?: string | null;
|
|
59
62
|
}>) => ForecastAccountResult[];
|
|
60
63
|
recommendForecastAccount: (results: ForecastAccountResult[]) => {
|
|
61
64
|
recommendedIndex: number | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"best.d.ts","sourceRoot":"","sources":["../../../../lib/codex-manager/commands/best.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,KAAK,kBAAkB,EAA6B,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"best.d.ts","sourceRoot":"","sources":["../../../../lib/codex-manager/commands/best.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,KAAK,kBAAkB,EAA6B,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAEN,KAAK,WAAW,EAEhB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGhE,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;CACvB;AAED,KAAK,gBAAgB,CAAC,CAAC,IACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,CAAC,CAAA;CAAE,GACxB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAgBrC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC,cAAc,CAAC,CA0C9E;AAED,MAAM,WAAW,eAAe;IAC/B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9C,YAAY,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACrD,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,gBAAgB,CAAC,cAAc,CAAC,CAAC;IACpE,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5E,oBAAoB,EAAE,CACrB,OAAO,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,EACrD,GAAG,EAAE,MAAM,KACP,OAAO,CAAC;IACb,aAAa,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9D,sBAAsB,EAAE,CACvB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,GAAG,SAAS,KACtB,MAAM,CAAC;IACZ,gBAAgB,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC;IAC1E,mBAAmB,EAAE,CACpB,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM,GAAG,SAAS,KACvB,MAAM,GAAG,SAAS,CAAC;IACxB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC;IACjE,kBAAkB,EAAE,CACnB,OAAO,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,EACtE,KAAK,EAAE,MAAM,KACT,MAAM,CAAC;IACZ,uBAAuB,EAAE,CAAC,KAAK,EAAE;QAChC,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;KACd,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAClC,wBAAwB,EAAE,CACzB,MAAM,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;QAC9C,SAAS,EAAE,OAAO,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,cAAc,CAAC,EAAE,YAAY,CAAC;QAC9B,SAAS,CAAC,EAAE,kBAAkB,CAAC;QAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,CAAC,KACE,qBAAqB,EAAE,CAAC;IAC7B,wBAAwB,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK;QAC/D,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,MAAM,EAAE,MAAM,CAAC;KACf,CAAC;IACF,6BAA6B,EAAE,CAAC,MAAM,EAAE;QACvC,OAAO,EAAE,gBAAgB,CAAC;QAC1B,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,sBAAsB,CAAC,EAAE,OAAO,CAAC;KACjC,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzD,0BAA0B,EAAE,CAAC,MAAM,EAAE;QACpC,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,wBAAsB,cAAc,CACnC,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,EAAE,eAAe,GACnB,OAAO,CAAC,MAAM,CAAC,CAsRjB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describeCodexProbeFailure } from "../../quota-probe.js";
|
|
2
|
-
import { resolveNormalizedModel } from "../../request/helpers/model-map.js";
|
|
2
|
+
import { getModelProfile, resolveNormalizedModel, } from "../../request/helpers/model-map.js";
|
|
3
3
|
import { DEFAULT_LIVE_PROBE_MODEL } from "../quota-cache-helpers.js";
|
|
4
4
|
/**
|
|
5
5
|
* Usage text and argument parsing for `best`. Previously module-private in
|
|
@@ -173,6 +173,13 @@ export async function runBestCommand(args, deps) {
|
|
|
173
173
|
probeErrors.push(`${deps.formatAccountLabel(account, i)}: ${message}`);
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
+
// Only an explicit --model moves the recommendation off the codex family;
|
|
177
|
+
// see the note in the forecast command. `best` exists to pick the account
|
|
178
|
+
// for wrapper traffic, which is codex-family.
|
|
179
|
+
const forecastFamily = options.modelProvided
|
|
180
|
+
? getModelProfile(probeModel).promptFamily
|
|
181
|
+
: undefined;
|
|
182
|
+
const forecastModel = options.modelProvided ? probeModel : undefined;
|
|
176
183
|
const forecastInputs = storage.accounts.map((account, index) => ({
|
|
177
184
|
index,
|
|
178
185
|
account,
|
|
@@ -180,6 +187,8 @@ export async function runBestCommand(args, deps) {
|
|
|
180
187
|
now,
|
|
181
188
|
refreshFailure: refreshFailures.get(index),
|
|
182
189
|
liveQuota: liveQuotaByIndex.get(index),
|
|
190
|
+
family: forecastFamily,
|
|
191
|
+
model: forecastModel,
|
|
183
192
|
}));
|
|
184
193
|
const forecastResults = deps.evaluateForecastAccounts(forecastInputs);
|
|
185
194
|
const recommendation = deps.recommendForecastAccount(forecastResults);
|
|
@@ -2,6 +2,7 @@ import type { DashboardDisplaySettings } from "../../dashboard-settings.js";
|
|
|
2
2
|
import { type ForecastAccountResult, type RuntimeForecastOverlay } from "../../forecast.js";
|
|
3
3
|
import type { QuotaCacheData } from "../../quota-cache.js";
|
|
4
4
|
import { type CodexQuotaSnapshot } from "../../quota-probe.js";
|
|
5
|
+
import { type ModelFamily } from "../../request/helpers/model-map.js";
|
|
5
6
|
import { type AccountMetadataV3, type AccountStorageV3 } from "../../storage.js";
|
|
6
7
|
import type { TokenFailure, TokenResult } from "../../types.js";
|
|
7
8
|
type PromptTone = "accent" | "success" | "warning" | "danger" | "muted";
|
|
@@ -40,6 +41,8 @@ export interface ForecastCommandDeps {
|
|
|
40
41
|
quotaCache?: QuotaCacheData | null;
|
|
41
42
|
allAccounts?: readonly AccountMetadataV3[];
|
|
42
43
|
runtimeOverlay?: RuntimeForecastOverlay | null;
|
|
44
|
+
family?: ModelFamily;
|
|
45
|
+
model?: string | null;
|
|
43
46
|
}>) => ForecastAccountResult[];
|
|
44
47
|
summarizeForecast: (results: ForecastAccountResult[]) => {
|
|
45
48
|
total: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../../../lib/codex-manager/commands/forecast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAE5E,OAAO,EAEN,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,KAAK,kBAAkB,EAA6B,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../../../lib/codex-manager/commands/forecast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAE5E,OAAO,EAEN,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,KAAK,kBAAkB,EAA6B,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAGN,KAAK,WAAW,EAEhB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAmBhE,KAAK,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AACxE,KAAK,uBAAuB,GAAG,WAAW,CACzC,MAAM,EACN;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,CAC1D,CAAC;AAEF,MAAM,WAAW,mBAAmB;IACnC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9C,YAAY,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACrD,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,4BAA4B,CAAC,EAAE,MAAM,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5E,cAAc,EAAE,MAAM,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACrD,cAAc,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,mBAAmB,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,cAAc,CAAC;IAC/D,4BAA4B,EAAE,CAC7B,QAAQ,EAAE,SAAS,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,OAAO,CAAC,EAAE,KAC/D,uBAAuB,CAAC;IAC7B,0BAA0B,EAAE,CAC3B,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,OAAO,CAAC,EACvD,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,SAAS,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,OAAO,CAAC,EAAE,EACnE,kBAAkB,CAAC,EAAE,uBAAuB,KACxC,OAAO,CAAC;IACb,oBAAoB,EAAE,CACrB,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,WAAW,CAAC,EAC7D,GAAG,EAAE,MAAM,KACP,OAAO,CAAC;IACb,aAAa,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9D,uBAAuB,EAAE,CAAC,KAAK,EAAE;QAChC,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;KACd,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAClC,sBAAsB,EAAE,CACvB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,GAAG,SAAS,KACtB,MAAM,CAAC;IACZ,kBAAkB,EAAE,CACnB,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,cAAc,GAAG,WAAW,CAAC,EACxE,KAAK,EAAE,MAAM,KACT,MAAM,CAAC;IACZ,gBAAgB,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC;IAC1E,wBAAwB,EAAE,CACzB,MAAM,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,iBAAiB,CAAC;QAC3B,SAAS,EAAE,OAAO,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,cAAc,CAAC,EAAE,YAAY,CAAC;QAC9B,SAAS,CAAC,EAAE,kBAAkB,CAAC;QAC/B,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;QACnC,WAAW,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;QAC3C,cAAc,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;QAC/C,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,CAAC,KACE,qBAAqB,EAAE,CAAC;IAC7B,iBAAiB,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK;QACxD,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,wBAAwB,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK;QAC/D,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,MAAM,EAAE,MAAM,CAAC;KACf,CAAC;IACF,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,MAAM,CAAC;IAC5D,mBAAmB,EAAE,CACpB,QAAQ,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,KACvD,MAAM,CAAC;IACZ,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/C,0BAA0B,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,MAAM,CAAC;IACrE,gBAAgB,EAAE,CACjB,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC,KAC/C,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtC,QAAQ,EAAE,CACT,KAAK,EAAE,qBAAqB,CAAC,WAAW,CAAC,KACrC,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtC,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,cAAc,EAAE,wBAAwB,CAAC;IACzC,gCAAgC,CAAC,EAAE,MAAM,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IAChF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAkFD,wBAAsB,kBAAkB,CACvC,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,EAAE,mBAAmB,GAAG;IAC3B,uBAAuB,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,MAAM,CAAC;CAClE,GACC,OAAO,CAAC,MAAM,CAAC,CAyXjB"}
|
|
@@ -2,7 +2,7 @@ import { extractAccountEmail, sanitizeEmail } from "../../accounts.js";
|
|
|
2
2
|
import { buildForecastExplanation, } from "../../forecast.js";
|
|
3
3
|
import { applyRefreshedAccountPatch, persistRefreshedAccountPatch, serializeForecastResults, } from "../forecast-report-shared.js";
|
|
4
4
|
import { describeCodexProbeFailure } from "../../quota-probe.js";
|
|
5
|
-
import { DEFAULT_PROBE_MODEL, resolveNormalizedModel } from "../../request/helpers/model-map.js";
|
|
5
|
+
import { DEFAULT_PROBE_MODEL, getModelProfile, resolveNormalizedModel, } from "../../request/helpers/model-map.js";
|
|
6
6
|
function joinStyledSegments(parts, styleText) {
|
|
7
7
|
if (parts.length === 0)
|
|
8
8
|
return "";
|
|
@@ -27,6 +27,7 @@ function parseForecastArgs(args) {
|
|
|
27
27
|
json: false,
|
|
28
28
|
explain: false,
|
|
29
29
|
model: DEFAULT_PROBE_MODEL,
|
|
30
|
+
modelProvided: false,
|
|
30
31
|
runtimeOverlay: true,
|
|
31
32
|
};
|
|
32
33
|
for (let i = 0; i < args.length; i += 1) {
|
|
@@ -55,6 +56,7 @@ function parseForecastArgs(args) {
|
|
|
55
56
|
return { ok: false, message: "Missing value for --model" };
|
|
56
57
|
}
|
|
57
58
|
options.model = value;
|
|
59
|
+
options.modelProvided = true;
|
|
58
60
|
i += 1;
|
|
59
61
|
continue;
|
|
60
62
|
}
|
|
@@ -64,6 +66,7 @@ function parseForecastArgs(args) {
|
|
|
64
66
|
return { ok: false, message: "Missing value for --model" };
|
|
65
67
|
}
|
|
66
68
|
options.model = value;
|
|
69
|
+
options.modelProvided = true;
|
|
67
70
|
continue;
|
|
68
71
|
}
|
|
69
72
|
return { ok: false, message: `Unknown option: ${arg}` };
|
|
@@ -195,6 +198,18 @@ export async function runForecastCommand(args, deps) {
|
|
|
195
198
|
probeErrors.push(`${deps.formatAccountLabel(account, i)}: ${message}`);
|
|
196
199
|
}
|
|
197
200
|
}
|
|
201
|
+
// Only an explicit --model moves the forecast off the codex family. The
|
|
202
|
+
// default probe model is gpt-5.6-sol, whose family is gpt-5.2, so keying a
|
|
203
|
+
// bare `forecast` on it would evaluate every account against a family no
|
|
204
|
+
// wrapper request uses - /codex/responses buckets into codex.
|
|
205
|
+
//
|
|
206
|
+
// probeModel, not requestedModel: rate-limit records are keyed by the
|
|
207
|
+
// normalized model the proxy routes on. Resolved once rather than per
|
|
208
|
+
// account: getModelProfile re-parses the model string on every call.
|
|
209
|
+
const forecastFamily = options.modelProvided
|
|
210
|
+
? getModelProfile(requestedModel).promptFamily
|
|
211
|
+
: undefined;
|
|
212
|
+
const forecastModel = options.modelProvided ? probeModel : undefined;
|
|
198
213
|
const forecastInputs = storage.accounts.map((account, index) => ({
|
|
199
214
|
index,
|
|
200
215
|
account,
|
|
@@ -205,6 +220,8 @@ export async function runForecastCommand(args, deps) {
|
|
|
205
220
|
quotaCache,
|
|
206
221
|
allAccounts: storage.accounts,
|
|
207
222
|
runtimeOverlay,
|
|
223
|
+
family: forecastFamily,
|
|
224
|
+
model: forecastModel,
|
|
208
225
|
}));
|
|
209
226
|
const forecastResults = deps.evaluateForecastAccounts(forecastInputs);
|
|
210
227
|
const summary = deps.summarizeForecast(forecastResults);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../../lib/codex-manager/commands/report.ts"],"names":[],"mappings":"AAoBA,OAAO,EACN,KAAK,kBAAkB,EAGvB,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAC;AAC3F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../../lib/codex-manager/commands/report.ts"],"names":[],"mappings":"AAoBA,OAAO,EACN,KAAK,kBAAkB,EAGvB,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAC;AAC3F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA6ChE,MAAM,WAAW,iBAAiB;IACjC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9C,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,YAAY,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACrD,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5E,oBAAoB,EAAE,CACrB,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,WAAW,CAAC,EAC7D,GAAG,EAAE,MAAM,KACP,OAAO,CAAC;IACb,aAAa,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9D,uBAAuB,EAAE,CAAC,KAAK,EAAE;QAChC,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;KACd,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAClC,oBAAoB,EAAE,CACrB,OAAO,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,EAC7C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,KACX,MAAM,GAAG,IAAI,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC3D,sBAAsB,EAAE,CACvB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,GAAG,SAAS,KACtB,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,gCAAgC,CAAC,EAAE,MAAM,OAAO,CAAC,4BAA4B,GAAG,IAAI,CAAC,CAAC;IACtF,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CACtD;AAuLD,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,EAAE,iBAAiB,GACrB,OAAO,CAAC,MAAM,CAAC,CA8VjB"}
|
|
@@ -44,6 +44,7 @@ function parseReportArgs(args) {
|
|
|
44
44
|
json: false,
|
|
45
45
|
explain: false,
|
|
46
46
|
model: DEFAULT_PROBE_MODEL,
|
|
47
|
+
modelProvided: false,
|
|
47
48
|
cachedOnly: false,
|
|
48
49
|
};
|
|
49
50
|
for (let i = 0; i < args.length; i += 1) {
|
|
@@ -72,6 +73,7 @@ function parseReportArgs(args) {
|
|
|
72
73
|
return { ok: false, message: "Missing value for --model" };
|
|
73
74
|
}
|
|
74
75
|
options.model = value;
|
|
76
|
+
options.modelProvided = true;
|
|
75
77
|
i += 1;
|
|
76
78
|
continue;
|
|
77
79
|
}
|
|
@@ -81,6 +83,7 @@ function parseReportArgs(args) {
|
|
|
81
83
|
return { ok: false, message: "Missing value for --model" };
|
|
82
84
|
}
|
|
83
85
|
options.model = value;
|
|
86
|
+
options.modelProvided = true;
|
|
84
87
|
continue;
|
|
85
88
|
}
|
|
86
89
|
if (arg === "--max-accounts") {
|
|
@@ -328,6 +331,15 @@ export async function runReportCommand(args, deps) {
|
|
|
328
331
|
}
|
|
329
332
|
}
|
|
330
333
|
}
|
|
334
|
+
// Only an explicit --model moves the report off the codex family; see the
|
|
335
|
+
// note in the forecast command. promptFamily is reused from the inspection
|
|
336
|
+
// rather than re-resolved per account.
|
|
337
|
+
const forecastFamily = options.modelProvided
|
|
338
|
+
? modelInspection.promptFamily
|
|
339
|
+
: undefined;
|
|
340
|
+
const forecastModel = options.modelProvided
|
|
341
|
+
? modelInspection.normalized
|
|
342
|
+
: undefined;
|
|
331
343
|
const forecastResults = storage
|
|
332
344
|
? evaluateForecastAccounts(storage.accounts.map((account, index) => ({
|
|
333
345
|
index,
|
|
@@ -339,6 +351,8 @@ export async function runReportCommand(args, deps) {
|
|
|
339
351
|
quotaCache,
|
|
340
352
|
allAccounts: storage.accounts,
|
|
341
353
|
runtimeOverlay: runtimeSnapshot,
|
|
354
|
+
family: forecastFamily,
|
|
355
|
+
model: forecastModel,
|
|
342
356
|
})))
|
|
343
357
|
: [];
|
|
344
358
|
const forecastSummary = summarizeForecast(forecastResults);
|
package/dist/lib/forecast.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CodexQuotaSnapshot } from "./quota-probe.js";
|
|
2
2
|
import type { QuotaCacheData } from "./quota-cache.js";
|
|
3
|
+
import type { ModelFamily } from "./request/helpers/model-map.js";
|
|
3
4
|
import type { AccountMetadataV3 } from "./storage.js";
|
|
4
5
|
import type { TokenFailure } from "./types.js";
|
|
5
6
|
type ForecastAvailability = "ready" | "delayed" | "unavailable";
|
|
@@ -14,6 +15,18 @@ export interface ForecastAccountInput {
|
|
|
14
15
|
quotaCache?: QuotaCacheData | null;
|
|
15
16
|
allAccounts?: readonly AccountMetadataV3[];
|
|
16
17
|
runtimeOverlay?: RuntimeForecastOverlay | null;
|
|
18
|
+
/**
|
|
19
|
+
* Prompt family whose per-family rate-limit records gate this forecast.
|
|
20
|
+
* Callers with a model in hand resolve it via getModelProfile; the codex
|
|
21
|
+
* default preserves the historical behavior for model-less surfaces.
|
|
22
|
+
*/
|
|
23
|
+
family?: ModelFamily;
|
|
24
|
+
/**
|
|
25
|
+
* Normalized model the forecast is about, when the caller has one. Selection
|
|
26
|
+
* keys token/concurrency limits under `family:<model>`, so without it a
|
|
27
|
+
* sibling model's record would be read as gating this one.
|
|
28
|
+
*/
|
|
29
|
+
model?: string | null;
|
|
17
30
|
}
|
|
18
31
|
export interface RuntimeForecastOverlay {
|
|
19
32
|
accountSkipReasons?: Record<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../lib/forecast.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../lib/forecast.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/forecast.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AUTH_INVALIDATION_MARKER, formatAccountLabel, formatWaitTime, } from "./accounts.js";
|
|
2
2
|
import { findQuotaCacheEntryForAccount, isQuotaCacheEntryExhausted, quotaUsedPercentIsExhausted, } from "./quota-readiness.js";
|
|
3
|
-
import { getRateLimitResetTimeForFamily } from "./runtime/account-status.js";
|
|
3
|
+
import { getRateLimitResetTimeForFamily, getRateLimitResetTimeForModel, } from "./runtime/account-status.js";
|
|
4
4
|
function clampRisk(score) {
|
|
5
5
|
if (!Number.isFinite(score))
|
|
6
6
|
return 100;
|
|
@@ -132,7 +132,18 @@ export function evaluateForecastAccount(input) {
|
|
|
132
132
|
riskScore += 45;
|
|
133
133
|
appendWaitReason(reasons, "cooldown remaining", remaining);
|
|
134
134
|
}
|
|
135
|
-
|
|
135
|
+
// With a model in hand, gate on exactly the keys selection consults for that
|
|
136
|
+
// family/model pair, and on the LATEST of them: a sibling model's record does
|
|
137
|
+
// not gate this request, and while both the family-wide and model-scoped keys
|
|
138
|
+
// are active the account stays skipped until the later one expires.
|
|
139
|
+
//
|
|
140
|
+
// Without one (status, fix) no model key can be singled out, so keep the
|
|
141
|
+
// family-wide union - the conservative answer, and the behavior those
|
|
142
|
+
// surfaces have always had.
|
|
143
|
+
const forecastFamily = input.family ?? "codex";
|
|
144
|
+
const rateLimitResetAt = input.model
|
|
145
|
+
? getRateLimitResetTimeForModel(account, now, forecastFamily, input.model)
|
|
146
|
+
: getRateLimitResetTimeForFamily(account, now, forecastFamily);
|
|
136
147
|
if (typeof rateLimitResetAt === "number") {
|
|
137
148
|
const remaining = Math.max(0, rateLimitResetAt - now);
|
|
138
149
|
waitMs = Math.max(waitMs, remaining);
|
|
@@ -176,7 +187,11 @@ export function evaluateForecastAccount(input) {
|
|
|
176
187
|
// drop the overlay reason when the condition it describes is no longer
|
|
177
188
|
// active. Each reason validates only against its own backing disk state
|
|
178
189
|
// ("rate-limited" -> rateLimitResetTimes, "cooling-down" -> coolingDownUntil)
|
|
179
|
-
// so we never substitute a misleading reason string.
|
|
190
|
+
// so we never substitute a misleading reason string. The rate-limited
|
|
191
|
+
// cross-check inherits rateLimitResetAt's scope above: a record under one of
|
|
192
|
+
// the keys that actually gates this family/model request keeps the reason,
|
|
193
|
+
// while a record for another family - or another model in the same family -
|
|
194
|
+
// neither sustains it nor gates this request. Non-time-bounded
|
|
180
195
|
// reasons ("circuit-open", "token-exhausted", "policy-blocked") have no disk
|
|
181
196
|
// expiry to check and are always applied.
|
|
182
197
|
const coolingDownActive = typeof account.coolingDownUntil === "number" &&
|
|
@@ -22,7 +22,25 @@ export interface PinnedUnavailableErrorBody {
|
|
|
22
22
|
code: "codex_pinned_account_unavailable";
|
|
23
23
|
pinnedAccountIndex: number | null;
|
|
24
24
|
reason: string | null;
|
|
25
|
+
/** How the pin was set; forced pins are not cleared by `unpin`. */
|
|
26
|
+
pin_source: "forced" | "manual" | null;
|
|
27
|
+
/** When the blocking record ends, when the skip reason is time-bounded. */
|
|
28
|
+
reset_at: string | null;
|
|
29
|
+
retry_after_ms: number | null;
|
|
25
30
|
account_skip_reasons: Record<string, string>;
|
|
26
31
|
}
|
|
27
|
-
export
|
|
32
|
+
export interface PinnedUnavailableContext {
|
|
33
|
+
/**
|
|
34
|
+
* "forced" when the pin came from the wrapper's forced-account mode
|
|
35
|
+
* (`--account` / CODEX_MULTI_AUTH_FORCE_ACCOUNT, which the wrapper resolves
|
|
36
|
+
* into the internal CODEX_MULTI_AUTH_FORCE_ACCOUNT_INDEX), "manual" when it
|
|
37
|
+
* came from `switch`. `unpin` clears only the manual kind, so the remedy
|
|
38
|
+
* line must not suggest it for a forced pin.
|
|
39
|
+
*/
|
|
40
|
+
pinSource?: "forced" | "manual" | null;
|
|
41
|
+
/** Epoch ms when the blocking record ends (rate limit or cooldown). */
|
|
42
|
+
resetAtMs?: number | null;
|
|
43
|
+
now?: number;
|
|
44
|
+
}
|
|
45
|
+
export declare function buildPinnedUnavailableErrorBody(pinnedIndex: number | null | undefined, accountSkipReasons: ReadonlyMap<number, string>, context?: PinnedUnavailableContext): PinnedUnavailableErrorBody;
|
|
28
46
|
//# sourceMappingURL=rate-limit-decision.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit-decision.d.ts","sourceRoot":"","sources":["../../../lib/request/rate-limit-decision.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAe/C,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAAG,OAAO,CAWjG;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAapF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoBlF;AAYD,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAuB3E;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBxE;AA0BD,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,GAAG,EAAE,MAAM,GACT,MAAM,CAcR;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAE1E;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,kCAAkC,CAAC;IACzC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAED,wBAAgB,+BAA+B,CAC9C,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACtC,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"rate-limit-decision.d.ts","sourceRoot":"","sources":["../../../lib/request/rate-limit-decision.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAe/C,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAAG,OAAO,CAWjG;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAapF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoBlF;AAYD,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAuB3E;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBxE;AA0BD,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,GAAG,EAAE,MAAM,GACT,MAAM,CAcR;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAE1E;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,kCAAkC,CAAC;IACzC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mEAAmE;IACnE,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;IACvC,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAQD,MAAM,WAAW,wBAAwB;IACxC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;IACvC,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,+BAA+B,CAC9C,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACtC,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/C,OAAO,CAAC,EAAE,wBAAwB,GAChC,0BAA0B,CAwD5B"}
|
|
@@ -172,7 +172,12 @@ export function getQuotaNearExhaustionWaitMs(headers, remainingThreshold, now) {
|
|
|
172
172
|
export function normalizeExhaustionStatus(reason) {
|
|
173
173
|
return reason === "rate-limit" ? HTTP_STATUS.TOO_MANY_REQUESTS : 503;
|
|
174
174
|
}
|
|
175
|
-
|
|
175
|
+
/**
|
|
176
|
+
* Largest epoch-ms value `new Date(...).toISOString()` accepts; anything beyond
|
|
177
|
+
* throws RangeError (ECMAScript time-value limit, ±100,000,000 days).
|
|
178
|
+
*/
|
|
179
|
+
const MAX_ECMASCRIPT_TIME_VALUE = 8_640_000_000_000_000;
|
|
180
|
+
export function buildPinnedUnavailableErrorBody(pinnedIndex, accountSkipReasons, context) {
|
|
176
181
|
const normalizedPinnedIndex = typeof pinnedIndex === "number" ? pinnedIndex : null;
|
|
177
182
|
const skipReason = normalizedPinnedIndex !== null
|
|
178
183
|
? accountSkipReasons.get(normalizedPinnedIndex) ?? null
|
|
@@ -183,11 +188,38 @@ export function buildPinnedUnavailableErrorBody(pinnedIndex, accountSkipReasons)
|
|
|
183
188
|
const accountPhrase = normalizedPinnedIndex === null
|
|
184
189
|
? "The pinned account"
|
|
185
190
|
: `Pinned account ${normalizedPinnedIndex + 1}`;
|
|
191
|
+
const pinSource = context?.pinSource ?? null;
|
|
192
|
+
// Upper bound as well as lower: resetAtMs comes from persisted account state
|
|
193
|
+
// (rateLimitResetTimes, coolingDownUntil), and markAccountCoolingDown clamps
|
|
194
|
+
// only the low side while nothing re-validates either on load. A finite but
|
|
195
|
+
// absurd deadline past the ECMAScript time limit would make toISOString below
|
|
196
|
+
// throw a RangeError inside handleRequestInner, collapsing this diagnostic 503
|
|
197
|
+
// into a generic 500 that carries no pinnedAccountIndex, reason, or skip map —
|
|
198
|
+
// the exact payload this branch exists to deliver. Such a value bounds nothing
|
|
199
|
+
// usable anyway, so treat it as "no known recovery" instead.
|
|
200
|
+
const resetAtMs = typeof context?.resetAtMs === "number" &&
|
|
201
|
+
Number.isFinite(context.resetAtMs) &&
|
|
202
|
+
context.resetAtMs > 0 &&
|
|
203
|
+
context.resetAtMs <= MAX_ECMASCRIPT_TIME_VALUE
|
|
204
|
+
? context.resetAtMs
|
|
205
|
+
: null;
|
|
206
|
+
const now = context?.now ?? Date.now();
|
|
207
|
+
const retryAfterMs = resetAtMs !== null ? Math.max(0, resetAtMs - now) : null;
|
|
208
|
+
const resetAt = resetAtMs !== null ? new Date(resetAtMs).toISOString() : null;
|
|
209
|
+
const waitSuffix = resetAt !== null ? `; the recorded limit resets at ${resetAt}` : "";
|
|
210
|
+
// A forced pin belongs to the launching process, not to the persisted pin
|
|
211
|
+
// state, so `unpin` would clear nothing — say what actually helps.
|
|
212
|
+
const remedy = pinSource === "forced"
|
|
213
|
+
? "the pin was set by this session's launcher, so relaunch to select a different account"
|
|
214
|
+
: "run `codex-multi-auth status` for details, or `codex-multi-auth unpin` to allow rotation";
|
|
186
215
|
return {
|
|
187
|
-
message: `${accountPhrase} is currently unavailable${reasonSuffix};
|
|
216
|
+
message: `${accountPhrase} is currently unavailable${reasonSuffix}${waitSuffix}; ${remedy}.`,
|
|
188
217
|
code: "codex_pinned_account_unavailable",
|
|
189
218
|
pinnedAccountIndex: normalizedPinnedIndex,
|
|
190
219
|
reason: skipReason,
|
|
220
|
+
pin_source: pinSource,
|
|
221
|
+
reset_at: resetAt,
|
|
222
|
+
retry_after_ms: retryAfterMs,
|
|
191
223
|
account_skip_reasons: Object.fromEntries([...accountSkipReasons.entries()].map(([index, reason]) => [
|
|
192
224
|
String(index),
|
|
193
225
|
reason,
|
|
@@ -7,7 +7,45 @@ export declare function resolveActiveIndex(storage: {
|
|
|
7
7
|
export declare function getRateLimitResetTimeForFamily(account: {
|
|
8
8
|
rateLimitResetTimes?: Record<string, number | undefined>;
|
|
9
9
|
}, now: number, family: ModelFamily): number | null;
|
|
10
|
+
/**
|
|
11
|
+
* The moment the account becomes usable again for a `family`/`model`
|
|
12
|
+
* request: the LATEST bound among the records that actually gate that
|
|
13
|
+
* request plus any active cooldown. Two deliberate differences from
|
|
14
|
+
* getRateLimitResetTimeForFamily, whose earliest-reset answer feeds wait
|
|
15
|
+
* displays: the account stays skipped while ANY gating record is active,
|
|
16
|
+
* so the earliest reset would send clients back into a 503 — and only the
|
|
17
|
+
* keys selection consults (`family`, plus `family:<model>` when a model is
|
|
18
|
+
* known; see isRateLimitedForFamily) may contribute, because another
|
|
19
|
+
* model's record does not block this request and would overstate its
|
|
20
|
+
* recovery. Null when nothing bounds recovery.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getAccountRecoveryTimeForFamily(account: {
|
|
23
|
+
rateLimitResetTimes?: Record<string, number | undefined>;
|
|
24
|
+
coolingDownUntil?: number;
|
|
25
|
+
}, now: number, family: ModelFamily, model?: string | null): number | null;
|
|
10
26
|
export declare function formatRateLimitEntry(account: {
|
|
11
27
|
rateLimitResetTimes?: Record<string, number | undefined>;
|
|
12
28
|
}, now: number, formatWaitTime: (ms: number) => string, family?: ModelFamily): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* When a request for `family`/`model` stops being rate limited: the LATEST
|
|
31
|
+
* active bound among exactly the two keys selection consults — the family-wide
|
|
32
|
+
* key and `family:<model>` (see `isRateLimitedForFamily`). Null when neither is
|
|
33
|
+
* active.
|
|
34
|
+
*
|
|
35
|
+
* Deliberately narrower and later than `getRateLimitResetTimeForFamily`, whose
|
|
36
|
+
* earliest-reset-across-every-`family:*`-key answer feeds wait displays and
|
|
37
|
+
* model-less callers:
|
|
38
|
+
*
|
|
39
|
+
* - narrower, because `markRateLimitedWithReason` keys token/concurrency limits
|
|
40
|
+
* under `family:<model>`, and a sibling model's record does not gate this
|
|
41
|
+
* request — folding it in reports a delay the runtime proxy would not impose;
|
|
42
|
+
* - later, because the account stays skipped while EITHER key is active, so the
|
|
43
|
+
* earliest reset understates the wait when both are set.
|
|
44
|
+
*
|
|
45
|
+
* Requires a model by construction: a caller without one cannot know which
|
|
46
|
+
* model key applies and should keep the family-wide union above.
|
|
47
|
+
*/
|
|
48
|
+
export declare function getRateLimitResetTimeForModel(account: {
|
|
49
|
+
rateLimitResetTimes?: Record<string, number | undefined>;
|
|
50
|
+
}, now: number, family: ModelFamily, model: string): number | null;
|
|
13
51
|
//# sourceMappingURL=account-status.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-status.d.ts","sourceRoot":"","sources":["../../../lib/runtime/account-status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"account-status.d.ts","sourceRoot":"","sources":["../../../lib/runtime/account-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,wBAAgB,kBAAkB,CACjC,OAAO,EAAE;IACR,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3D,QAAQ,EAAE,OAAO,EAAE,CAAC;CACpB,EACD,MAAM,GAAE,WAAqB,GAC3B,MAAM,CAOR;AAED,wBAAgB,8BAA8B,CAC7C,OAAO,EAAE;IAAE,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CAAE,EACrE,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,WAAW,GACjB,MAAM,GAAG,IAAI,CAgBf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAC9C,OAAO,EAAE;IACR,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B,EACD,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,MAAM,GAAG,IAAI,CAcf;AAED,wBAAgB,oBAAoB,CACnC,OAAO,EAAE;IAAE,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CAAE,EACrE,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,EACtC,MAAM,GAAE,WAAqB,GAC3B,MAAM,GAAG,IAAI,CAMf;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,6BAA6B,CAC5C,OAAO,EAAE;IAAE,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CAAE,EACrE,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAcf"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getQuotaKey } from "../accounts/rate-limits.js";
|
|
1
2
|
export function resolveActiveIndex(storage, family = "codex") {
|
|
2
3
|
const total = storage.accounts.length;
|
|
3
4
|
if (total === 0)
|
|
@@ -25,6 +26,37 @@ export function getRateLimitResetTimeForFamily(account, now, family) {
|
|
|
25
26
|
}
|
|
26
27
|
return minReset;
|
|
27
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* The moment the account becomes usable again for a `family`/`model`
|
|
31
|
+
* request: the LATEST bound among the records that actually gate that
|
|
32
|
+
* request plus any active cooldown. Two deliberate differences from
|
|
33
|
+
* getRateLimitResetTimeForFamily, whose earliest-reset answer feeds wait
|
|
34
|
+
* displays: the account stays skipped while ANY gating record is active,
|
|
35
|
+
* so the earliest reset would send clients back into a 503 — and only the
|
|
36
|
+
* keys selection consults (`family`, plus `family:<model>` when a model is
|
|
37
|
+
* known; see isRateLimitedForFamily) may contribute, because another
|
|
38
|
+
* model's record does not block this request and would overstate its
|
|
39
|
+
* recovery. Null when nothing bounds recovery.
|
|
40
|
+
*/
|
|
41
|
+
export function getAccountRecoveryTimeForFamily(account, now, family, model) {
|
|
42
|
+
let latest = null;
|
|
43
|
+
const consider = (value) => {
|
|
44
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
45
|
+
return;
|
|
46
|
+
if (value <= now)
|
|
47
|
+
return;
|
|
48
|
+
if (latest === null || value > latest)
|
|
49
|
+
latest = value;
|
|
50
|
+
};
|
|
51
|
+
const times = account.rateLimitResetTimes;
|
|
52
|
+
if (times) {
|
|
53
|
+
consider(times[getQuotaKey(family)]);
|
|
54
|
+
if (model)
|
|
55
|
+
consider(times[getQuotaKey(family, model)]);
|
|
56
|
+
}
|
|
57
|
+
consider(account.coolingDownUntil);
|
|
58
|
+
return latest;
|
|
59
|
+
}
|
|
28
60
|
export function formatRateLimitEntry(account, now, formatWaitTime, family = "codex") {
|
|
29
61
|
const resetAt = getRateLimitResetTimeForFamily(account, now, family);
|
|
30
62
|
if (typeof resetAt !== "number")
|
|
@@ -34,3 +66,39 @@ export function formatRateLimitEntry(account, now, formatWaitTime, family = "cod
|
|
|
34
66
|
return null;
|
|
35
67
|
return `resets in ${formatWaitTime(remaining)}`;
|
|
36
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* When a request for `family`/`model` stops being rate limited: the LATEST
|
|
71
|
+
* active bound among exactly the two keys selection consults — the family-wide
|
|
72
|
+
* key and `family:<model>` (see `isRateLimitedForFamily`). Null when neither is
|
|
73
|
+
* active.
|
|
74
|
+
*
|
|
75
|
+
* Deliberately narrower and later than `getRateLimitResetTimeForFamily`, whose
|
|
76
|
+
* earliest-reset-across-every-`family:*`-key answer feeds wait displays and
|
|
77
|
+
* model-less callers:
|
|
78
|
+
*
|
|
79
|
+
* - narrower, because `markRateLimitedWithReason` keys token/concurrency limits
|
|
80
|
+
* under `family:<model>`, and a sibling model's record does not gate this
|
|
81
|
+
* request — folding it in reports a delay the runtime proxy would not impose;
|
|
82
|
+
* - later, because the account stays skipped while EITHER key is active, so the
|
|
83
|
+
* earliest reset understates the wait when both are set.
|
|
84
|
+
*
|
|
85
|
+
* Requires a model by construction: a caller without one cannot know which
|
|
86
|
+
* model key applies and should keep the family-wide union above.
|
|
87
|
+
*/
|
|
88
|
+
export function getRateLimitResetTimeForModel(account, now, family, model) {
|
|
89
|
+
const times = account.rateLimitResetTimes;
|
|
90
|
+
if (!times)
|
|
91
|
+
return null;
|
|
92
|
+
let latest = null;
|
|
93
|
+
const consider = (value) => {
|
|
94
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
95
|
+
return;
|
|
96
|
+
if (value <= now)
|
|
97
|
+
return;
|
|
98
|
+
if (latest === null || value > latest)
|
|
99
|
+
latest = value;
|
|
100
|
+
};
|
|
101
|
+
consider(times[getQuotaKey(family)]);
|
|
102
|
+
consider(times[getQuotaKey(family, model)]);
|
|
103
|
+
return latest;
|
|
104
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-rotation-proxy.d.ts","sourceRoot":"","sources":["../../lib/runtime-rotation-proxy.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"runtime-rotation-proxy.d.ts","sourceRoot":"","sources":["../../lib/runtime-rotation-proxy.ts"],"names":[],"mappings":"AAGA,OAAO,EAIN,KAAK,cAAc,EACnB,MAAM,eAAe,CAAC;AA8BvB,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA4CtE,OAAO,KAAK,EAKX,2BAA2B,EAC3B,0BAA0B,EAE1B,MAAM,oCAAoC,CAAC;AAe5C,YAAY,EACX,2BAA2B,EAC3B,0BAA0B,EAC1B,0BAA0B,GAC1B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACN,+BAA+B,EAC/B,0BAA0B,GAC1B,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AACxE,OAAO,EACN,+BAA+B,EAC/B,8BAA8B,EAC9B,uBAAuB,EACvB,uBAAuB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,YAAY,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AA8DtE,kFAAkF;AAClF,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,OAAO,GAAG,cAAc,CAAC,GAAG;IACvE,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,EACD,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,MAAM,CAmBR;AA8bD;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAC1C,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,MAAM,GAAG,IAAI,CAUf;AAED,wBAAsB,yBAAyB,CAC9C,OAAO,EAAE,2BAA2B,GAClC,OAAO,CAAC,0BAA0B,CAAC,CA4KrC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { createServer } from "node:http";
|
|
3
|
-
import { AccountManager, extractAccountId, } from "./accounts.js";
|
|
3
|
+
import { AccountManager, AUTH_INVALIDATION_MARKER, extractAccountId, } from "./accounts.js";
|
|
4
4
|
import { withRoutingMutex } from "./routing-mutex.js";
|
|
5
5
|
import { getFetchTimeoutMs, getNetworkErrorCooldownMs, getRetryAllAccountsMaxRetries, getServerErrorCooldownMs, getSessionAffinity, getSessionAffinityMaxEntries, getSessionAffinityTtlMs, getStreamStallTimeoutMs, getMinRotationIntervalMs, getTokenInvalidationCooldownMs, getTokenRefreshSkewMs, getPidOffsetEnabled, getPreemptiveQuotaEnabled, getPreemptiveQuotaMaxDeferralMs, getPreemptiveQuotaRemainingPercent5h, getPreemptiveQuotaRemainingPercent7d, getRoutingMutexMode, getSchedulingStrategy, loadPluginConfig, } from "./config.js";
|
|
6
6
|
import { CODEX_BASE_URL, HTTP_STATUS, OPENAI_HEADERS, OPENAI_HEADER_VALUES, URL_PATHS, } from "./constants.js";
|
|
@@ -15,6 +15,7 @@ import { CodexValidationError } from "./errors.js";
|
|
|
15
15
|
import { normalizeEmailKey } from "./storage/identity.js";
|
|
16
16
|
import { buildPinnedUnavailableErrorBody, buildTokenInvalidationBody, extractErrorCodeFromBody, isTokenInvalidationError, normalizeExhaustionStatus, parseRetryAfterBodyMs, parseRetryAfterHeaderMs, } from "./request/rate-limit-decision.js";
|
|
17
17
|
import { forwardStreamingResponse, HOP_BY_HOP_HEADERS, readErrorBody, responseHeadersForClient, withTimeout, } from "./request/stream-failover-runtime.js";
|
|
18
|
+
import { getAccountRecoveryTimeForFamily } from "./runtime/account-status.js";
|
|
18
19
|
import { chooseAccount } from "./runtime/rotation-account-selection.js";
|
|
19
20
|
import { createRotationProxyState, recoverStaleRuntimeState, } from "./runtime/rotation-proxy-state.js";
|
|
20
21
|
import { readStorageMetaFromDisk } from "./runtime/rotation-storage-meta.js";
|
|
@@ -62,6 +63,18 @@ function toUrlHost(host) {
|
|
|
62
63
|
// failures surfaced only as a last-write-wins status.lastError string. Logs are
|
|
63
64
|
// level-gated and carry the per-request correlation id set in handleRequest.
|
|
64
65
|
const proxyLog = createLogger("runtime-proxy");
|
|
66
|
+
/**
|
|
67
|
+
* Pinned skip reasons that no timer clears: the account stays unselectable
|
|
68
|
+
* after any concurrent rate-limit record or cooldown expires, so the pinned
|
|
69
|
+
* 503 must not advertise that record's expiry as a recovery time.
|
|
70
|
+
*/
|
|
71
|
+
const PINNED_PERMANENT_SKIP_REASONS = new Set([
|
|
72
|
+
"missing",
|
|
73
|
+
"disabled",
|
|
74
|
+
"workspace-disabled",
|
|
75
|
+
"policy-blocked",
|
|
76
|
+
AUTH_INVALIDATION_MARKER,
|
|
77
|
+
]);
|
|
65
78
|
const DEFAULT_QUOTA_REMAINING_THRESHOLD = 10;
|
|
66
79
|
/** @internal Stable identity key for in-memory quota snapshots across reloads. */
|
|
67
80
|
export function buildQuotaScheduleKey(account, family, model) {
|
|
@@ -1170,7 +1183,60 @@ async function handleRequestInner(state, req, res, traceId) {
|
|
|
1170
1183
|
// null reason indicates a forecast/runtime state desync (the pinned
|
|
1171
1184
|
// account was selected but no skip reason was recorded) — see #486.
|
|
1172
1185
|
if (isPinned) {
|
|
1173
|
-
const
|
|
1186
|
+
const pinnedAccount = typeof pinnedIndex === "number"
|
|
1187
|
+
? accountManager.getAccountByIndex(pinnedIndex)
|
|
1188
|
+
: null;
|
|
1189
|
+
const pinnedSkipReason = typeof pinnedIndex === "number"
|
|
1190
|
+
? accountSkipReasons.get(pinnedIndex) ?? null
|
|
1191
|
+
: null;
|
|
1192
|
+
// A permanent blocker (disabled, no enabled workspace, invalidated
|
|
1193
|
+
// auth, policy block, out-of-range pin) outlives every timed record,
|
|
1194
|
+
// so advertising a record's expiry would invite a retry into another
|
|
1195
|
+
// 503.
|
|
1196
|
+
//
|
|
1197
|
+
// The recorded reason alone is not enough to detect one. It is the
|
|
1198
|
+
// SELECTION verdict, and this request can make the pin permanently
|
|
1199
|
+
// unselectable after selection already ran: a workspace-disabled
|
|
1200
|
+
// 402/403 calls setAccountEnabled(index, false) above and then
|
|
1201
|
+
// continues, so the next pass records "already-attempted" and the
|
|
1202
|
+
// disable never surfaces. With a breaker tripped by the same failure
|
|
1203
|
+
// the 503 would then advertise the circuit's ~30s reset for an
|
|
1204
|
+
// account no timer will ever re-admit. Re-read the pin's CURRENT
|
|
1205
|
+
// runtime state so a permanent blocker cannot hide behind the
|
|
1206
|
+
// verdict; the recorded reason still covers the selection-only
|
|
1207
|
+
// verdicts ("missing", "policy-blocked") that state cannot express.
|
|
1208
|
+
const pinnedCurrentSkipReason = pinnedAccount === null
|
|
1209
|
+
? null
|
|
1210
|
+
: accountManager.getManagedAccountRuntimeSkipReason(pinnedAccount, context.family, context.model);
|
|
1211
|
+
const pinnedBlockedPermanently = (pinnedSkipReason !== null &&
|
|
1212
|
+
PINNED_PERMANENT_SKIP_REASONS.has(pinnedSkipReason)) ||
|
|
1213
|
+
(pinnedCurrentSkipReason !== null &&
|
|
1214
|
+
PINNED_PERMANENT_SKIP_REASONS.has(pinnedCurrentSkipReason));
|
|
1215
|
+
// Otherwise recovery comes from the pinned account's persisted state, not the
|
|
1216
|
+
// recorded skip reason: a direct 429/cooldown on the pinned account
|
|
1217
|
+
// reaches this 503 as "already-attempted" (the retry loop's selection
|
|
1218
|
+
// verdict) while the record it just wrote is what actually bounds
|
|
1219
|
+
// recovery — and with several overlapping records the account stays
|
|
1220
|
+
// skipped until the LAST one expires, so the latest bound is the one
|
|
1221
|
+
// worth advertising.
|
|
1222
|
+
const pinnedStateRecoveryAtMs = pinnedAccount === null
|
|
1223
|
+
? null
|
|
1224
|
+
: getAccountRecoveryTimeForFamily(pinnedAccount, state.now(), context.family, context.model);
|
|
1225
|
+
// An open circuit outlives the short failure cooldowns that tripped
|
|
1226
|
+
// it; its deadline lives in the breaker, not the account record.
|
|
1227
|
+
const pinnedCircuitRecoveryAtMs = pinnedAccount === null
|
|
1228
|
+
? null
|
|
1229
|
+
: accountManager.getCircuitRecoveryTime(pinnedAccount, state.now());
|
|
1230
|
+
const pinnedResetAtMs = pinnedBlockedPermanently ||
|
|
1231
|
+
(pinnedStateRecoveryAtMs === null && pinnedCircuitRecoveryAtMs === null)
|
|
1232
|
+
? null
|
|
1233
|
+
: Math.max(pinnedStateRecoveryAtMs ?? 0, pinnedCircuitRecoveryAtMs ?? 0);
|
|
1234
|
+
const errorBody = buildPinnedUnavailableErrorBody(pinnedIndex, accountSkipReasons, {
|
|
1235
|
+
// typeof check so a forced index of 0 still reads as forced.
|
|
1236
|
+
pinSource: typeof state.forcedAccountIndex === "number" ? "forced" : "manual",
|
|
1237
|
+
resetAtMs: pinnedResetAtMs,
|
|
1238
|
+
now: state.now(),
|
|
1239
|
+
});
|
|
1174
1240
|
if (errorBody.reason === null) {
|
|
1175
1241
|
state.status.lastError = `pinned-503 missing skip reason (pinnedIndex=${pinnedIndex})`;
|
|
1176
1242
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-multi-auth",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.6",
|
|
4
4
|
"description": "Codex CLI multi-account OAuth manager with account switching, health checks, runtime rotation, diagnostics, and recovery tools for @openai/codex",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|