codex-multi-auth 2.7.0 → 2.7.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.
- package/.codex-plugin/plugin.json +9 -9
- package/README.md +434 -433
- package/dist/lib/cli.d.ts +2 -0
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-menu-actions.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-menu-actions.js +12 -1
- package/dist/lib/codex-manager/login-menu-data.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-menu-data.js +19 -8
- package/dist/lib/forecast.d.ts.map +1 -1
- package/dist/lib/forecast.js +30 -4
- package/dist/lib/policy/runtime-policy.d.ts.map +1 -1
- package/dist/lib/policy/runtime-policy.js +12 -3
- package/dist/lib/quota-readiness.d.ts +1 -0
- package/dist/lib/quota-readiness.d.ts.map +1 -1
- package/dist/lib/quota-readiness.js +12 -2
- package/dist/lib/refresh-lease.d.ts +12 -0
- package/dist/lib/refresh-lease.d.ts.map +1 -1
- package/dist/lib/refresh-lease.js +24 -2
- package/dist/lib/refresh-queue.d.ts.map +1 -1
- package/dist/lib/refresh-queue.js +29 -3
- package/dist/lib/request/request-transformer.d.ts.map +1 -1
- package/dist/lib/request/request-transformer.js +13 -2
- package/dist/lib/request/response-handler.d.ts.map +1 -1
- package/dist/lib/request/response-handler.js +10 -1
- package/dist/lib/rotation.d.ts.map +1 -1
- package/dist/lib/rotation.js +8 -1
- package/dist/lib/runtime/account-check.d.ts +1 -1
- package/dist/lib/runtime/account-check.d.ts.map +1 -1
- package/dist/lib/runtime/account-check.js +8 -0
- package/dist/lib/runtime/rotation-storage-meta.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-storage-meta.js +8 -2
- package/dist/lib/storage/account-port.d.ts +2 -0
- package/dist/lib/storage/account-port.d.ts.map +1 -1
- package/dist/lib/storage/account-port.js +1 -0
- package/dist/lib/storage/import-export.d.ts +1 -0
- package/dist/lib/storage/import-export.d.ts.map +1 -1
- package/dist/lib/storage/import-export.js +25 -0
- package/dist/lib/storage/project-migration.d.ts +1 -1
- package/dist/lib/storage/project-migration.d.ts.map +1 -1
- package/dist/lib/storage/project-migration.js +28 -2
- package/dist/lib/storage.d.ts +10 -0
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +16 -1
- package/dist/lib/ui/auth-menu-builder.d.ts +10 -0
- package/dist/lib/ui/auth-menu-builder.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu-builder.js +29 -4
- package/package.json +1 -1
package/dist/lib/cli.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface ExistingAccountInfo {
|
|
|
24
24
|
quota5hResetAtMs?: number;
|
|
25
25
|
quota7dLeftPercent?: number;
|
|
26
26
|
quota7dResetAtMs?: number;
|
|
27
|
+
quotaPrimaryWindowMinutes?: number;
|
|
28
|
+
quotaSecondaryWindowMinutes?: number;
|
|
27
29
|
quotaRateLimited?: boolean;
|
|
28
30
|
quotaExhausted?: boolean;
|
|
29
31
|
isCurrentAccount?: boolean;
|
package/dist/lib/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../lib/cli.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAGN,KAAK,EACL,KAAK,aAAa,EAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAEjF;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAQ9C;AAED,wBAAsB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAcpF;AAED,MAAM,MAAM,SAAS,GAClB,KAAK,GACL,UAAU,GACV,KAAK,GACL,UAAU,GACV,OAAO,GACP,QAAQ,GACR,OAAO,GACP,YAAY,GACZ,gBAAgB,GAChB,QAAQ,CAAC;AAEZ,MAAM,WAAW,mBAAmB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AA0FD,wBAAsB,eAAe,CACpC,gBAAgB,EAAE,mBAAmB,EAAE,EACvC,OAAO,GAAE,gBAAqB,GAC5B,OAAO,CAAC,eAAe,CAAC,CAqG1B;AAED,MAAM,WAAW,yBAAyB;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,sBAAsB,CAC3C,UAAU,EAAE,yBAAyB,EAAE,EACvC,OAAO,GAAE,uBAA4B,GACnC,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAyC3C;AAED,OAAO,EAAE,KAAK,EAAE,CAAC;AACjB,YAAY,EAAE,aAAa,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../lib/cli.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAGN,KAAK,EACL,KAAK,aAAa,EAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAEjF;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAQ9C;AAED,wBAAsB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAcpF;AAED,MAAM,MAAM,SAAS,GAClB,KAAK,GACL,UAAU,GACV,KAAK,GACL,UAAU,GACV,OAAO,GACP,QAAQ,GACR,OAAO,GACP,YAAY,GACZ,gBAAgB,GAChB,QAAQ,CAAC;AAEZ,MAAM,WAAW,mBAAmB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,cAAc,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AA0FD,wBAAsB,eAAe,CACpC,gBAAgB,EAAE,mBAAmB,EAAE,EACvC,OAAO,GAAE,gBAAqB,GAC5B,OAAO,CAAC,eAAe,CAAC,CAqG1B;AAED,MAAM,WAAW,yBAAyB;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,sBAAsB,CAC3C,UAAU,EAAE,yBAAyB,EAAE,EACvC,OAAO,GAAE,uBAA4B,GACnC,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAyC3C;AAED,OAAO,EAAE,KAAK,EAAE,CAAC;AACjB,YAAY,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-menu-actions.d.ts","sourceRoot":"","sources":["../../../lib/codex-manager/login-menu-actions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,EAEN,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"login-menu-actions.d.ts","sourceRoot":"","sources":["../../../lib/codex-manager/login-menu-actions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,EAEN,KAAK,gBAAgB,EAIrB,KAAK,kBAAkB,EAGvB,MAAM,eAAe,CAAC;AASvB,OAAO,EACN,KAAK,eAAe,EAKpB,MAAM,kBAAkB,CAAC;AAG1B;;;;;GAKG;AAEH,gBAAgB;AAChB,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE7D,gBAAgB;AAChB,wBAAsB,qBAAqB,CAC1C,YAAY,EAAE,kBAAkB,GAAG,IAAI,EACvC,sBAAsB,GAAE,MAAM,GAAG,IAAW,GAC1C,OAAO,CAAC,eAAe,CAAC,CA6D1B;AAED,gBAAgB;AAChB,wBAAsB,uBAAuB,CAC5C,YAAY,EAAE,kBAAkB,GAC9B,OAAO,CAAC,iBAAiB,CAAC,CA0C5B;AAED,gBAAgB;AAChB,wBAAsB,2BAA2B,CAChD,OAAO,EAAE,kBAAkB,EAAE,GAC3B,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAkCpC;AA8GD,gBAAgB;AAChB,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,gBAAgB,EACzB,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,GACrD,OAAO,CAAC,IAAI,CAAC,CA0Hf"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { stdin as input, stdout as output } from "node:process";
|
|
2
2
|
import { sanitizeEmail } from "../accounts.js";
|
|
3
3
|
import { MODEL_FAMILIES } from "../prompts/codex.js";
|
|
4
|
-
import { findMatchingAccountIndex, loadAccounts, setStoragePath, withAccountStorageTransaction, } from "../storage.js";
|
|
4
|
+
import { findMatchingAccountIndex, loadAccounts, reconcilePinnedAccountIndex, setStoragePath, withAccountStorageTransaction, } from "../storage.js";
|
|
5
5
|
import { UI_COPY } from "../ui/ui-copy.js";
|
|
6
6
|
import { getUiRuntimeOptions } from "../ui/runtime.js";
|
|
7
7
|
import { select } from "../ui/select.js";
|
|
@@ -179,6 +179,9 @@ function replaceManageActionStorage(target, source) {
|
|
|
179
179
|
target.activeIndexByFamily = {
|
|
180
180
|
...source.activeIndexByFamily,
|
|
181
181
|
};
|
|
182
|
+
// Keep the in-memory view's manual pin in sync with what was just persisted;
|
|
183
|
+
// the pin was re-resolved (or cleared) against the post-deletion account list.
|
|
184
|
+
target.pinnedAccountIndex = source.pinnedAccountIndex;
|
|
182
185
|
}
|
|
183
186
|
function resolveManageActionAccountIndex(storage, fallbackIndex, account) {
|
|
184
187
|
if (account) {
|
|
@@ -236,8 +239,16 @@ export async function handleManageAction(storage, menuResult) {
|
|
|
236
239
|
if (!matchesManageActionAccount(selectedAccount, nextAccount)) {
|
|
237
240
|
return;
|
|
238
241
|
}
|
|
242
|
+
// Capture the pinned account BEFORE the splice so the manual pin can be
|
|
243
|
+
// followed by identity afterwards. resetManageActionSelection only remaps
|
|
244
|
+
// activeIndex; without this the pin keeps its raw slot and silently points
|
|
245
|
+
// at a different account (or wedges the pool). See #474.
|
|
246
|
+
const pinnedAccount = typeof nextStorage.pinnedAccountIndex === "number"
|
|
247
|
+
? nextStorage.accounts[nextStorage.pinnedAccountIndex]
|
|
248
|
+
: undefined;
|
|
239
249
|
nextStorage.accounts.splice(nextIndex, 1);
|
|
240
250
|
resetManageActionSelection(nextStorage, nextIndex);
|
|
251
|
+
nextStorage.pinnedAccountIndex = reconcilePinnedAccountIndex(pinnedAccount, nextStorage.accounts);
|
|
241
252
|
await persist(nextStorage);
|
|
242
253
|
replaceManageActionStorage(storage, nextStorage);
|
|
243
254
|
deleted = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-menu-data.d.ts","sourceRoot":"","sources":["../../../lib/codex-manager/login-menu-data.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EAEN,KAAK,wBAAwB,EAE7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEN,KAAK,cAAc,EAGnB,MAAM,mBAAmB,CAAC;AAe3B,OAAO,EAKN,KAAK,8BAA8B,EACnC,MAAM,uCAAuC,CAAC;AAE/C,OAAO,KAAK,EAAqB,gBAAgB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"login-menu-data.d.ts","sourceRoot":"","sources":["../../../lib/codex-manager/login-menu-data.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EAEN,KAAK,wBAAwB,EAE7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEN,KAAK,cAAc,EAGnB,MAAM,mBAAmB,CAAC;AAe3B,OAAO,EAKN,KAAK,8BAA8B,EACnC,MAAM,uCAAuC,CAAC;AAE/C,OAAO,KAAK,EAAqB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAezE;;;;;;GAMG;AAEH,eAAO,MAAM,iCAAiC,QAAa,CAAC;AA+E5D,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,EAChB,GAAG,SAAa,GACd,MAAM,CAkBR;AAED,wBAAsB,wBAAwB,CAC7C,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACnD,OAAO,CAAC,cAAc,CAAC,CAiGzB;AAoKD,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,gBAAgB,EACzB,UAAU,EAAE,cAAc,GAAG,IAAI,EACjC,eAAe,EAAE,wBAAwB,EACzC,cAAc,GAAE,8BAA8B,GAAG,IAAW,GAC1D,mBAAmB,EAAE,CA+EvB;AAED,wBAAsB,qCAAqC,CAC1D,OAAO,EAAE,gBAAgB,EACzB,GAAG,SAAa,GACd,OAAO,CAAC,8BAA8B,GAAG,IAAI,CAAC,CAgBhD;AAsBD,wBAAsB,oCAAoC,CACzD,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,OAAO,CAAC,CAyBlB"}
|
|
@@ -9,6 +9,7 @@ import { resolveActiveIndex } from "../runtime/account-status.js";
|
|
|
9
9
|
import { getAppBindStatus } from "../runtime/app-bind.js";
|
|
10
10
|
import { isDisplayCurrentAccount, readAppRuntimeHelperAccountSignal, resolveAccountCurrentMarkers, resolveRuntimeCurrentAccount, } from "../runtime/runtime-current-account.js";
|
|
11
11
|
import { loadPersistedRuntimeObservabilitySnapshot } from "../runtime/runtime-observability.js";
|
|
12
|
+
import { resolveQuotaWindowLabel } from "../ui/auth-menu-builder.js";
|
|
12
13
|
import { hasUsableAccessToken } from "./account-credentials.js";
|
|
13
14
|
import { formatAccountQuotaSummary, formatRateLimitEntry, } from "./formatters/index.js";
|
|
14
15
|
import { cloneQuotaCacheData, DEFAULT_LIVE_PROBE_MODEL, getPersistedQuotaViewForAccount, updateQuotaCacheForAccount, } from "./quota-cache-helpers.js";
|
|
@@ -175,17 +176,25 @@ function parseLeftPercentFromQuotaSummary(summary, windowLabel) {
|
|
|
175
176
|
return -1;
|
|
176
177
|
return Math.max(0, Math.min(100, value));
|
|
177
178
|
}
|
|
178
|
-
function readQuotaLeftPercent(account,
|
|
179
|
-
const
|
|
179
|
+
function readQuotaLeftPercent(account, window) {
|
|
180
|
+
const isPrimary = window === "primary";
|
|
181
|
+
const direct = isPrimary
|
|
180
182
|
? account.quota5hLeftPercent
|
|
181
183
|
: account.quota7dLeftPercent;
|
|
182
184
|
if (typeof direct === "number" && Number.isFinite(direct)) {
|
|
183
185
|
return Math.max(0, Math.min(100, Math.round(direct)));
|
|
184
186
|
}
|
|
185
|
-
|
|
187
|
+
// The summary string is labelled by DURATION (formatAccountQuotaSummary), so a
|
|
188
|
+
// Codex Business row reads "30d 18%, ...". Searching it for the positional
|
|
189
|
+
// "5h"/"7d" finds nothing, scores the account -1, and sinks it to the bottom of
|
|
190
|
+
// a ready-first sort. Resolve the label from the window's real duration.
|
|
191
|
+
const label = resolveQuotaWindowLabel(isPrimary
|
|
192
|
+
? account.quotaPrimaryWindowMinutes
|
|
193
|
+
: account.quotaSecondaryWindowMinutes, isPrimary ? "5h" : "7d");
|
|
194
|
+
return parseLeftPercentFromQuotaSummary(account.quotaSummary, label);
|
|
186
195
|
}
|
|
187
196
|
function readQuotaFloorPercent(account) {
|
|
188
|
-
return Math.min(readQuotaLeftPercent(account, "
|
|
197
|
+
return Math.min(readQuotaLeftPercent(account, "primary"), readQuotaLeftPercent(account, "secondary"));
|
|
189
198
|
}
|
|
190
199
|
function accountStatusSortBucket(status) {
|
|
191
200
|
switch (status) {
|
|
@@ -220,12 +229,12 @@ function compareReadyFirstAccounts(left, right) {
|
|
|
220
229
|
const rightFloor = readQuotaFloorPercent(right);
|
|
221
230
|
if (leftFloor !== rightFloor)
|
|
222
231
|
return rightFloor - leftFloor;
|
|
223
|
-
const left5h = readQuotaLeftPercent(left, "
|
|
224
|
-
const right5h = readQuotaLeftPercent(right, "
|
|
232
|
+
const left5h = readQuotaLeftPercent(left, "primary");
|
|
233
|
+
const right5h = readQuotaLeftPercent(right, "primary");
|
|
225
234
|
if (left5h !== right5h)
|
|
226
235
|
return right5h - left5h;
|
|
227
|
-
const left7d = readQuotaLeftPercent(left, "
|
|
228
|
-
const right7d = readQuotaLeftPercent(right, "
|
|
236
|
+
const left7d = readQuotaLeftPercent(left, "secondary");
|
|
237
|
+
const right7d = readQuotaLeftPercent(right, "secondary");
|
|
229
238
|
if (left7d !== right7d)
|
|
230
239
|
return right7d - left7d;
|
|
231
240
|
const leftLastUsed = left.lastUsed ?? 0;
|
|
@@ -291,6 +300,8 @@ export function toExistingAccountInfo(storage, quotaCache, displaySettings, runt
|
|
|
291
300
|
quota5hResetAtMs: entry?.primary.resetAtMs,
|
|
292
301
|
quota7dLeftPercent: quotaLeftPercentFromUsed(entry?.secondary.usedPercent),
|
|
293
302
|
quota7dResetAtMs: entry?.secondary.resetAtMs,
|
|
303
|
+
quotaPrimaryWindowMinutes: entry?.primary.windowMinutes,
|
|
304
|
+
quotaSecondaryWindowMinutes: entry?.secondary.windowMinutes,
|
|
294
305
|
quotaRateLimited: entry?.status === 429,
|
|
295
306
|
quotaExhausted,
|
|
296
307
|
isCurrentAccount,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../lib/forecast.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,KAAK,oBAAoB,GAAG,OAAO,GAAG,SAAS,GAAG,aAAa,CAAC;AAChE,KAAK,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,iBAAiB,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC3C,cAAc,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CAC/C;AAED,MAAM,WAAW,sBAAsB;IACtC,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,6BAA6B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,oBAAoB,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAKlB,SAAS,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACtC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CACf;AAED,UAAU,0BAA0B;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,oBAAoB,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,0BAA0B,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../lib/forecast.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,KAAK,oBAAoB,GAAG,OAAO,GAAG,SAAS,GAAG,aAAa,CAAC;AAChE,KAAK,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,iBAAiB,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,WAAW,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC3C,cAAc,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CAC/C;AAED,MAAM,WAAW,sBAAsB;IACtC,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,6BAA6B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,oBAAoB,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAKlB,SAAS,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACtC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CACf;AAED,UAAU,0BAA0B;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,oBAAoB,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,0BAA0B,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAuFD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAUnE;AAWD,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,oBAAoB,GACzB,qBAAqB,CA0NvB;AAED,wBAAgB,wBAAwB,CACvC,MAAM,EAAE,oBAAoB,EAAE,GAC5B,qBAAqB,EAAE,CAEzB;AAkCD,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,qBAAqB,EAAE,GAC9B,sBAAsB,CAuDxB;AAED,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,qBAAqB,EAAE,GAC9B,eAAe,CAWjB;AAED,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,qBAAqB,EAAE,EAChC,cAAc,EAAE,sBAAsB,GACpC,mBAAmB,CAgBrB"}
|
package/dist/lib/forecast.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formatAccountLabel, formatWaitTime } from "./accounts.js";
|
|
2
|
-
import { findQuotaCacheEntryForAccount, isQuotaCacheEntryExhausted,
|
|
2
|
+
import { findQuotaCacheEntryForAccount, isQuotaCacheEntryExhausted, quotaUsedPercentIsExhausted, } from "./quota-readiness.js";
|
|
3
3
|
import { getRateLimitResetTimeForFamily } from "./runtime/account-status.js";
|
|
4
4
|
function clampRisk(score) {
|
|
5
5
|
if (!Number.isFinite(score))
|
|
@@ -49,8 +49,10 @@ function getLiveQuotaWaitMs(snapshot, now, onlyExhausted) {
|
|
|
49
49
|
// resets ~7d out; folding that in would overstate the wait by orders of
|
|
50
50
|
// magnitude and invert the account recommendation (stress audit H5). On a
|
|
51
51
|
// 429 we honor every future window, since the upstream said "slow down now"
|
|
52
|
-
// regardless of the usage gauge.
|
|
53
|
-
|
|
52
|
+
// regardless of the usage gauge. The test is the RAW usedPercent, never the
|
|
53
|
+
// rounded left-percent: 100 - 99.6 rounds to 0 left, which would bench a
|
|
54
|
+
// window that still has quota and falsely mark the account "delayed".
|
|
55
|
+
if (onlyExhausted && !quotaUsedPercentIsExhausted(window?.usedPercent)) {
|
|
54
56
|
continue;
|
|
55
57
|
}
|
|
56
58
|
const resetAt = window?.resetAtMs;
|
|
@@ -135,8 +137,13 @@ export function evaluateForecastAccount(input) {
|
|
|
135
137
|
}
|
|
136
138
|
const quotaEntry = findQuotaCacheEntryForAccount(input.quotaCache, account, input.allAccounts ?? [account]);
|
|
137
139
|
if (isQuotaCacheEntryExhausted(quotaEntry, now)) {
|
|
140
|
+
// Only a window that is genuinely at/over 100% used should contribute its
|
|
141
|
+
// reset time. Testing the ROUNDED left-percent instead would treat a
|
|
142
|
+
// 99.6%-used sibling as at-limit and fold its (possibly far-future) reset
|
|
143
|
+
// into the Math.max below, overstating the wait for an account whose
|
|
144
|
+
// actually-exhausted window recovers much sooner.
|
|
138
145
|
const resetAts = [quotaEntry?.primary, quotaEntry?.secondary]
|
|
139
|
-
.filter((window) =>
|
|
146
|
+
.filter((window) => quotaUsedPercentIsExhausted(window?.usedPercent) &&
|
|
140
147
|
typeof window?.resetAtMs === "number" &&
|
|
141
148
|
Number.isFinite(window.resetAtMs) &&
|
|
142
149
|
window.resetAtMs > now)
|
|
@@ -207,6 +214,25 @@ export function evaluateForecastAccount(input) {
|
|
|
207
214
|
if (liveWait > 0 && availability === "ready") {
|
|
208
215
|
availability = "delayed";
|
|
209
216
|
}
|
|
217
|
+
// A live window at 100% used with NO resetAtMs has no known recovery time —
|
|
218
|
+
// the probe reports it fully consumed and cannot say when it refills. On a
|
|
219
|
+
// 200 probe getLiveQuotaWaitMs then yields 0 (no reset to wait on) and the
|
|
220
|
+
// 429 branch never fires, so without this the account would stay "ready" and
|
|
221
|
+
// be recommended as a healthy pick. Treat that case as exhausted and downgrade
|
|
222
|
+
// a "ready" account to "delayed". A window WITH a resetAtMs is only *delayed*,
|
|
223
|
+
// not exhausted: getLiveQuotaWaitMs already contributes its wait above, so a
|
|
224
|
+
// 429 with known reset times stays a recoverable "delayed" account rather than
|
|
225
|
+
// a blocked one. The raw-usedPercent test (not rounded left-percent) keeps
|
|
226
|
+
// 99.6% from being falsely benched.
|
|
227
|
+
const liveExhausted = (quotaUsedPercentIsExhausted(quota.primary.usedPercent) &&
|
|
228
|
+
typeof quota.primary.resetAtMs !== "number") ||
|
|
229
|
+
(quotaUsedPercentIsExhausted(quota.secondary.usedPercent) &&
|
|
230
|
+
typeof quota.secondary.resetAtMs !== "number");
|
|
231
|
+
if (liveExhausted) {
|
|
232
|
+
exhausted = true;
|
|
233
|
+
if (availability === "ready")
|
|
234
|
+
availability = "delayed";
|
|
235
|
+
}
|
|
210
236
|
const primaryUsage = describeQuotaUsage("primary", quota.primary.usedPercent);
|
|
211
237
|
if (primaryUsage)
|
|
212
238
|
reasons.push(primaryUsage);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-policy.d.ts","sourceRoot":"","sources":["../../../lib/policy/runtime-policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAErE,OAAO,EAGN,KAAK,kBAAkB,EACvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,
|
|
1
|
+
{"version":3,"file":"runtime-policy.d.ts","sourceRoot":"","sources":["../../../lib/policy/runtime-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveEntitlementAccountKey } from "../entitlement-cache.js";
|
|
2
2
|
import { getAccountPolicyKey, loadAccountPolicyStore, } from "../account-policy.js";
|
|
3
|
-
import { evaluateBudgetGuard, getBudgetWindowStart, loadBudgetGuardStore, } from "../budget-guard.js";
|
|
3
|
+
import { evaluateBudgetGuard, getBudgetWindowStart, loadBudgetGuardStore, normalizeBudgetKey, } from "../budget-guard.js";
|
|
4
4
|
import { resolveProjectRoutingProfile, } from "../routing-profiles.js";
|
|
5
5
|
import { appendUsageLedgerRow, summarizeUsageLedger, } from "../usage/index.js";
|
|
6
6
|
export async function loadRuntimePolicyState(startDir = process.cwd()) {
|
|
@@ -33,12 +33,21 @@ function intersects(left, right) {
|
|
|
33
33
|
}
|
|
34
34
|
async function evaluateBudgets(input) {
|
|
35
35
|
const keys = new Set();
|
|
36
|
+
// `global` is already normalize-clean. Project/profile keys can carry uppercase
|
|
37
|
+
// or spaces, but budget-guard STORES limits only under normalizeBudgetKey (see
|
|
38
|
+
// upsertBudgetLimit and load-time normalizeStore). Look them up the same way, or
|
|
39
|
+
// a key like `project:MyApp` never matches its stored `project:myapp` and the
|
|
40
|
+
// budget is silently unenforced.
|
|
36
41
|
keys.add("global");
|
|
37
42
|
if (input.state.project.projectKey) {
|
|
38
|
-
|
|
43
|
+
const projectKey = normalizeBudgetKey(`project:${input.state.project.projectKey}`);
|
|
44
|
+
if (projectKey)
|
|
45
|
+
keys.add(projectKey);
|
|
39
46
|
}
|
|
40
47
|
if (input.state.project.profile?.budgetKey) {
|
|
41
|
-
|
|
48
|
+
const budgetKey = normalizeBudgetKey(input.state.project.profile.budgetKey);
|
|
49
|
+
if (budgetKey)
|
|
50
|
+
keys.add(budgetKey);
|
|
42
51
|
}
|
|
43
52
|
const evaluations = [];
|
|
44
53
|
for (const key of keys) {
|
|
@@ -11,6 +11,7 @@ export type QuotaEmailFallbackState = {
|
|
|
11
11
|
export declare function buildQuotaEmailFallbackState(accounts: readonly QuotaCacheAccountRef[]): ReadonlyMap<string, QuotaEmailFallbackState>;
|
|
12
12
|
export declare function hasSafeQuotaEmailFallback(emailFallbackState: ReadonlyMap<string, QuotaEmailFallbackState>, account: QuotaCacheAccountRef): boolean;
|
|
13
13
|
export declare function quotaLeftPercentFromUsed(usedPercent: number | undefined): number | undefined;
|
|
14
|
+
export declare function quotaUsedPercentIsExhausted(usedPercent: number | undefined): boolean;
|
|
14
15
|
export declare function isQuotaCacheEntryExhausted(entry: Pick<QuotaCacheEntry, "primary" | "secondary"> & {
|
|
15
16
|
updatedAt?: number;
|
|
16
17
|
} | null | undefined, now?: number): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quota-readiness.d.ts","sourceRoot":"","sources":["../../lib/quota-readiness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAoB,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC;AAIlF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGhF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAG5E;AAED,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,EACzC,OAAO,EAAE,oBAAoB,GAC3B,OAAO,CAQT;AAED,MAAM,MAAM,uBAAuB,GAAG;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,wBAAgB,4BAA4B,CAC3C,QAAQ,EAAE,SAAS,oBAAoB,EAAE,GACvC,WAAW,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAiB9C;AAED,wBAAgB,yBAAyB,CACxC,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAChE,OAAO,EAAE,oBAAoB,GAC3B,OAAO,CAMT;AAED,wBAAgB,wBAAwB,CACvC,WAAW,EAAE,MAAM,GAAG,SAAS,GAC7B,MAAM,GAAG,SAAS,CAKpB;
|
|
1
|
+
{"version":3,"file":"quota-readiness.d.ts","sourceRoot":"","sources":["../../lib/quota-readiness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAoB,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC;AAIlF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGhF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAG5E;AAED,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,EACzC,OAAO,EAAE,oBAAoB,GAC3B,OAAO,CAQT;AAED,MAAM,MAAM,uBAAuB,GAAG;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,wBAAgB,4BAA4B,CAC3C,QAAQ,EAAE,SAAS,oBAAoB,EAAE,GACvC,WAAW,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAiB9C;AAED,wBAAgB,yBAAyB,CACxC,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAChE,OAAO,EAAE,oBAAoB,GAC3B,OAAO,CAMT;AAED,wBAAgB,wBAAwB,CACvC,WAAW,EAAE,MAAM,GAAG,SAAS,GAC7B,MAAM,GAAG,SAAS,CAKpB;AAQD,wBAAgB,2BAA2B,CAC1C,WAAW,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAMT;AA2BD,wBAAgB,0BAA0B,CACzC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,WAAW,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,EACjG,GAAG,SAAa,GACd,OAAO,CAQT;AAED,wBAAgB,6BAA6B,CAC5C,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EACxC,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,SAAS,oBAAoB,EAAE,EACzC,kBAAkB,+CAAyC,GACzD,eAAe,GAAG,IAAI,CAWxB"}
|
|
@@ -53,6 +53,17 @@ export function quotaLeftPercentFromUsed(usedPercent) {
|
|
|
53
53
|
}
|
|
54
54
|
return Math.max(0, Math.min(100, Math.round(100 - usedPercent)));
|
|
55
55
|
}
|
|
56
|
+
// A window is exhausted only when it is genuinely at/over 100% used. Base this on
|
|
57
|
+
// the RAW usedPercent, never the rounded quotaLeftPercentFromUsed: rounding
|
|
58
|
+
// 100 - 99.6 = 0.4 down to 0 left-percent would falsely bench a window that still
|
|
59
|
+
// has ~0.4% quota (any usedPercent in (99.5, 100) rounds to 0 left). The header
|
|
60
|
+
// parser preserves fractional used-percent, so this input is expected;
|
|
61
|
+
// quotaLeftPercentFromUsed stays for DISPLAY only.
|
|
62
|
+
export function quotaUsedPercentIsExhausted(usedPercent) {
|
|
63
|
+
return (typeof usedPercent === "number" &&
|
|
64
|
+
Number.isFinite(usedPercent) &&
|
|
65
|
+
usedPercent >= 100);
|
|
66
|
+
}
|
|
56
67
|
function quotaWindowIsExhausted(window, now = Date.now(), updatedAt) {
|
|
57
68
|
if (typeof window?.resetAtMs === "number" && now >= window.resetAtMs) {
|
|
58
69
|
return false;
|
|
@@ -69,8 +80,7 @@ function quotaWindowIsExhausted(window, now = Date.now(), updatedAt) {
|
|
|
69
80
|
now >= updatedAt + window.windowMinutes * 60_000) {
|
|
70
81
|
return false;
|
|
71
82
|
}
|
|
72
|
-
|
|
73
|
-
return typeof leftPercent === "number" && leftPercent <= 0;
|
|
83
|
+
return quotaUsedPercentIsExhausted(window?.usedPercent);
|
|
74
84
|
}
|
|
75
85
|
export function isQuotaCacheEntryExhausted(entry, now = Date.now()) {
|
|
76
86
|
// Codex quota windows are cumulative gates: a 0% remaining active window blocks use
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
2
|
import type { TokenResult } from "./types.js";
|
|
3
|
+
export declare const DEFAULT_WAIT_TIMEOUT_MS = 35000;
|
|
3
4
|
type LeaseFsOps = Pick<typeof fs, "mkdir" | "open" | "writeFile" | "rename" | "unlink" | "readFile" | "stat" | "readdir"> & Partial<Pick<typeof fs, "chmod">>;
|
|
4
5
|
export interface RefreshLeaseCoordinatorOptions {
|
|
5
6
|
enabled?: boolean;
|
|
@@ -24,6 +25,17 @@ export declare class RefreshLeaseCoordinator {
|
|
|
24
25
|
private readonly resultTtlMs;
|
|
25
26
|
private readonly fsOps;
|
|
26
27
|
constructor(options?: RefreshLeaseCoordinatorOptions);
|
|
28
|
+
/**
|
|
29
|
+
* Resolved maximum time `acquire()` may block waiting for a lease.
|
|
30
|
+
*
|
|
31
|
+
* Exposed so the refresh queue can size its acquire-stage eviction threshold
|
|
32
|
+
* against the budget this coordinator ACTUALLY uses. The budget is
|
|
33
|
+
* configurable (constructor option / `CODEX_AUTH_REFRESH_LEASE_WAIT_MS`), so
|
|
34
|
+
* sizing eviction off the static `DEFAULT_WAIT_TIMEOUT_MS` would evict an
|
|
35
|
+
* acquire that is still legitimately waiting under a larger budget, spawning
|
|
36
|
+
* the duplicate refresh (→ `invalid_grant`) the lease exists to prevent.
|
|
37
|
+
*/
|
|
38
|
+
get configuredWaitTimeoutMs(): number;
|
|
27
39
|
static fromEnvironment(): RefreshLeaseCoordinator;
|
|
28
40
|
acquire(refreshToken: string): Promise<RefreshLeaseHandle>;
|
|
29
41
|
private createBypassHandle;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh-lease.d.ts","sourceRoot":"","sources":["../../lib/refresh-lease.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAMrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"refresh-lease.d.ts","sourceRoot":"","sources":["../../lib/refresh-lease.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAMrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAQ9C,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAsB9C,KAAK,UAAU,GAAG,IAAI,CACrB,OAAO,EAAE,EACT,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CACtF,GACA,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;AAEnC,MAAM,WAAW,8BAA8B;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;IACtC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAyGD,qBAAa,uBAAuB;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;gBAEvB,OAAO,GAAE,8BAAmC;IAUxD;;;;;;;;;OASG;IACH,IAAI,uBAAuB,IAAI,MAAM,CAEpC;IAED,MAAM,CAAC,eAAe,IAAI,uBAAuB;IAgB3C,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA+FhE,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,iBAAiB;YA0CX,QAAQ;YAkBR,WAAW;YAwBX,eAAe;YAiBf,mBAAmB;YAuCnB,qBAAqB;CAsBnC"}
|
|
@@ -8,7 +8,9 @@ import { safeParseTokenResult } from "./schemas.js";
|
|
|
8
8
|
import { isRecord } from "./utils.js";
|
|
9
9
|
const log = createLogger("refresh-lease");
|
|
10
10
|
const DEFAULT_LEASE_TTL_MS = 30_000;
|
|
11
|
-
|
|
11
|
+
// Exported so the refresh queue can size its acquire-stage eviction threshold
|
|
12
|
+
// above the maximum time a lease acquire() may legitimately block waiting.
|
|
13
|
+
export const DEFAULT_WAIT_TIMEOUT_MS = 35_000;
|
|
12
14
|
const DEFAULT_POLL_INTERVAL_MS = 150;
|
|
13
15
|
const DEFAULT_RESULT_TTL_MS = 20_000;
|
|
14
16
|
const RETRYABLE_IO_ERRORS = new Set(["EBUSY", "EPERM", "EMFILE", "ENFILE"]);
|
|
@@ -120,6 +122,19 @@ export class RefreshLeaseCoordinator {
|
|
|
120
122
|
this.resultTtlMs = Math.max(1_000, Math.floor(options.resultTtlMs ?? DEFAULT_RESULT_TTL_MS));
|
|
121
123
|
this.fsOps = options.fsOps ?? fs;
|
|
122
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Resolved maximum time `acquire()` may block waiting for a lease.
|
|
127
|
+
*
|
|
128
|
+
* Exposed so the refresh queue can size its acquire-stage eviction threshold
|
|
129
|
+
* against the budget this coordinator ACTUALLY uses. The budget is
|
|
130
|
+
* configurable (constructor option / `CODEX_AUTH_REFRESH_LEASE_WAIT_MS`), so
|
|
131
|
+
* sizing eviction off the static `DEFAULT_WAIT_TIMEOUT_MS` would evict an
|
|
132
|
+
* acquire that is still legitimately waiting under a larger budget, spawning
|
|
133
|
+
* the duplicate refresh (→ `invalid_grant`) the lease exists to prevent.
|
|
134
|
+
*/
|
|
135
|
+
get configuredWaitTimeoutMs() {
|
|
136
|
+
return this.waitTimeoutMs;
|
|
137
|
+
}
|
|
123
138
|
static fromEnvironment() {
|
|
124
139
|
const testMode = process.env.VITEST === "true" || process.env.NODE_ENV === "test";
|
|
125
140
|
const enabled = parseBooleanEnv(process.env.CODEX_AUTH_REFRESH_LEASE) ??
|
|
@@ -243,7 +258,14 @@ export class RefreshLeaseCoordinator {
|
|
|
243
258
|
return;
|
|
244
259
|
released = true;
|
|
245
260
|
try {
|
|
246
|
-
|
|
261
|
+
// Only ever cache a SUCCESSFUL refresh in the cross-process lease.
|
|
262
|
+
// A `failed` result carries no token material to share; caching it
|
|
263
|
+
// would make readFreshResult serve the failure verbatim to every
|
|
264
|
+
// follower for the whole result TTL (DEFAULT_RESULT_TTL_MS), blocking
|
|
265
|
+
// a real refresh and even escalating to cooldowns. On failure we skip
|
|
266
|
+
// the cache and still unlink the lock in `finally`, so the next caller
|
|
267
|
+
// becomes owner and retries immediately.
|
|
268
|
+
if (result?.type === "success") {
|
|
247
269
|
await this.writeResult(resultPath, tokenHash, result);
|
|
248
270
|
}
|
|
249
271
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh-queue.d.ts","sourceRoot":"","sources":["../../lib/refresh-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"refresh-queue.d.ts","sourceRoot":"","sources":["../../lib/refresh-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,uBAAuB,EAA2B,MAAM,oBAAoB,CAAC;AAqCtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IAC3D,OAAO,CAAC,cAAc,CAAK;IAE3B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAAkC;IAE1D;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IAEvC;;;OAGG;gBAED,aAAa,GAAE,MAAe,EAC9B,gBAAgB,GAAE,uBAAmE;IAMvF;;;;;;;;OAQG;IACG,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAuHzD,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,sBAAsB;YAShB,kCAAkC;IAchD;;OAEG;YACW,cAAc;IAsE5B;;;OAGG;IACH,OAAO,CAAC,OAAO;IA8Cf;;;;OAIG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI3C;;;OAGG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;CAId;AAQD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,CAKpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAE9E"}
|
|
@@ -10,9 +10,16 @@
|
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
11
|
import { refreshAccessToken } from "./auth/auth.js";
|
|
12
12
|
import { createLogger } from "./logger.js";
|
|
13
|
-
import { RefreshLeaseCoordinator } from "./refresh-lease.js";
|
|
13
|
+
import { RefreshLeaseCoordinator, DEFAULT_WAIT_TIMEOUT_MS } from "./refresh-lease.js";
|
|
14
14
|
import { isAbortError } from "./utils.js";
|
|
15
15
|
const log = createLogger("refresh-queue");
|
|
16
|
+
/**
|
|
17
|
+
* Extra headroom beyond the lease wait budget before an acquire-stage entry is
|
|
18
|
+
* treated as genuinely stuck. A lease acquire() polls on an interval and does
|
|
19
|
+
* filesystem work, so it can overshoot its wait deadline slightly; this slack
|
|
20
|
+
* keeps cleanup from evicting an acquire that is still legitimately waiting.
|
|
21
|
+
*/
|
|
22
|
+
const ACQUIRE_EVICTION_SLACK_MS = 5_000;
|
|
16
23
|
/**
|
|
17
24
|
* Non-reversible correlation fingerprint for a token, for logs.
|
|
18
25
|
*
|
|
@@ -311,11 +318,28 @@ export class RefreshQueue {
|
|
|
311
318
|
*/
|
|
312
319
|
cleanup() {
|
|
313
320
|
const now = Date.now();
|
|
321
|
+
// A lease acquire() can legitimately block up to the coordinator's wait
|
|
322
|
+
// budget. Evicting an acquire-stage entry before that budget elapses would
|
|
323
|
+
// spawn a duplicate refresh whose refresh token OpenAI has already rotated on
|
|
324
|
+
// first use (invalid_grant). So an acquire-stage entry is only evicted once it
|
|
325
|
+
// exceeds BOTH the configured max age AND the lease wait budget plus slack —
|
|
326
|
+
// never merely maxEntryAgeMs, which can be shorter than the wait budget.
|
|
327
|
+
//
|
|
328
|
+
// Read the budget the coordinator was actually CONFIGURED with (constructor
|
|
329
|
+
// option / CODEX_AUTH_REFRESH_LEASE_WAIT_MS) rather than the static default:
|
|
330
|
+
// under a larger configured budget the default would evict too early. An
|
|
331
|
+
// injected test double may not expose the getter, so fall back to the default.
|
|
332
|
+
const configuredWaitTimeoutMs = this.leaseCoordinator.configuredWaitTimeoutMs;
|
|
333
|
+
const leaseWaitTimeoutMs = typeof configuredWaitTimeoutMs === "number" &&
|
|
334
|
+
Number.isFinite(configuredWaitTimeoutMs)
|
|
335
|
+
? configuredWaitTimeoutMs
|
|
336
|
+
: DEFAULT_WAIT_TIMEOUT_MS;
|
|
337
|
+
const acquireEvictionAgeMs = Math.max(this.maxEntryAgeMs, leaseWaitTimeoutMs + ACQUIRE_EVICTION_SLACK_MS);
|
|
314
338
|
for (const [token, entry] of this.pending.entries()) {
|
|
315
339
|
const ageMs = now - entry.startedAt;
|
|
316
|
-
if (ageMs <= this.maxEntryAgeMs)
|
|
317
|
-
continue;
|
|
318
340
|
if (entry.stage === "acquire") {
|
|
341
|
+
if (ageMs <= acquireEvictionAgeMs)
|
|
342
|
+
continue;
|
|
319
343
|
log.warn("Evicting stale refresh entry during lease acquire stage", {
|
|
320
344
|
tokenSuffix: tokenFingerprint(token),
|
|
321
345
|
ageMs,
|
|
@@ -324,6 +348,8 @@ export class RefreshQueue {
|
|
|
324
348
|
this.cleanupRotationMapping(token);
|
|
325
349
|
continue;
|
|
326
350
|
}
|
|
351
|
+
if (ageMs <= this.maxEntryAgeMs)
|
|
352
|
+
continue;
|
|
327
353
|
if (!entry.staleWarningLogged) {
|
|
328
354
|
log.warn("Refresh entry exceeded stale warning threshold", {
|
|
329
355
|
tokenSuffix: tokenFingerprint(token),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-transformer.d.ts","sourceRoot":"","sources":["../../../lib/request/request-transformer.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACX,aAAa,EACb,SAAS,EACT,eAAe,EACf,WAAW,EAEX,UAAU,EACV,MAAM,aAAa,CAAC;AAGrB,KAAK,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAO/C,MAAM,WAAW,0BAA0B;IAC1C,IAAI,EAAE,WAAW,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,6BAA6B,CAAC,EAAE,OAAO,CAAC;IACxC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACnC;AAID,OAAO,EACN,kBAAkB,EAClB,uCAAuC,GACvC,MAAM,0BAA0B,CAAC;AAElC;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEhE;AAkBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,GAAE,UAAuC,GACjD,aAAa,CAqEf;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACvC,UAAU,GAAE,UAAuC,GACjD,UAAU,CAUZ;AA4QD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,GAAE,aAAkB,GAC5B,eAAe,CAuBjB;AA2DD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CAC1B,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAC9B,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9B,SAAS,EAAE,GAAG,SAAS,CAsBzB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1C,SAAS,EAAE,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"request-transformer.d.ts","sourceRoot":"","sources":["../../../lib/request/request-transformer.ts"],"names":[],"mappings":"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"}
|
|
@@ -487,7 +487,8 @@ export function trimInputForFastSession(input, maxItems, options) {
|
|
|
487
487
|
}
|
|
488
488
|
break;
|
|
489
489
|
}
|
|
490
|
-
|
|
490
|
+
const tailStart = Math.max(0, input.length - safeMax);
|
|
491
|
+
for (let i = tailStart; i < input.length; i++) {
|
|
491
492
|
if (excludedHeadIndexes.has(i))
|
|
492
493
|
continue;
|
|
493
494
|
keepIndexes.add(i);
|
|
@@ -499,7 +500,17 @@ export function trimInputForFastSession(input, maxItems, options) {
|
|
|
499
500
|
return input;
|
|
500
501
|
if (trimmed.length <= safeMax)
|
|
501
502
|
return trimmed;
|
|
502
|
-
|
|
503
|
+
// Kept head items are always the LOWEST kept indexes, so they occupy the first
|
|
504
|
+
// `keptHead` entries of `trimmed`. Reserve budget for exactly that many.
|
|
505
|
+
// Recounting the kept indexes below `tailStart` instead would miss a head
|
|
506
|
+
// instruction that ALSO falls inside the tail window (input.length only just
|
|
507
|
+
// over safeMax), and the tail slice would then drop it. The two slices cannot
|
|
508
|
+
// overlap here: keptHead + tailBudget === safeMax < trimmed.length.
|
|
509
|
+
const tailBudget = Math.max(1, safeMax - keptHead);
|
|
510
|
+
return [
|
|
511
|
+
...trimmed.slice(0, keptHead),
|
|
512
|
+
...trimmed.slice(trimmed.length - tailBudget),
|
|
513
|
+
];
|
|
503
514
|
}
|
|
504
515
|
function isTrivialLatestPrompt(text) {
|
|
505
516
|
const normalized = text.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-handler.d.ts","sourceRoot":"","sources":["../../../lib/request/response-handler.ts"],"names":[],"mappings":"AAwwBA;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;IACT,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B,GACC,OAAO,CAAC,QAAQ,CAAC,CA2HnB;AA6DD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAQ3D;AA2BD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"response-handler.d.ts","sourceRoot":"","sources":["../../../lib/request/response-handler.ts"],"names":[],"mappings":"AAwwBA;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;IACT,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B,GACC,OAAO,CAAC,QAAQ,CAAC,CA2HnB;AA6DD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAQ3D;AA2BD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CA4CtD;AAED,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GACzC,QAAQ,CAiBV"}
|
|
@@ -787,7 +787,16 @@ export function isEmptyResponse(body) {
|
|
|
787
787
|
const obj = body;
|
|
788
788
|
if (Object.keys(obj).length === 0)
|
|
789
789
|
return true;
|
|
790
|
-
const hasOutput = "output" in obj &&
|
|
790
|
+
const hasOutput = "output" in obj &&
|
|
791
|
+
obj.output !== null &&
|
|
792
|
+
obj.output !== undefined &&
|
|
793
|
+
(Array.isArray(obj.output)
|
|
794
|
+
? obj.output.some((o) => o !== null &&
|
|
795
|
+
o !== undefined &&
|
|
796
|
+
(typeof o !== "object" || Object.keys(o).length > 0))
|
|
797
|
+
: typeof obj.output === "string"
|
|
798
|
+
? obj.output.trim() !== ""
|
|
799
|
+
: true);
|
|
791
800
|
const hasChoices = "choices" in obj &&
|
|
792
801
|
Array.isArray(obj.choices) &&
|
|
793
802
|
obj.choices.some((c) => c !== null &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../lib/rotation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,MAAM,WAAW,iBAAiB;IACjC,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,sBAAsB,EAAE,MAAM,CAAC;CAC/B;AAED,eAAO,MAAM,2BAA2B,EAAE,iBAOzC,CAAC;AAQF,KAAK,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAWlC;;;GAGG;AACH,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,MAAM,CAAoB;gBAEtB,MAAM,GAAE,OAAO,CAAC,iBAAiB,CAAM;IAInD,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,oBAAoB;IAO5B,QAAQ,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IAO3D,sBAAsB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IAMzE,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAiB9D,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAiBhE,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAiB9D,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAKtD,KAAK,IAAI,IAAI;IAIb,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAanD;;;;OAIG;IACH,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;CAW7C;AAMD,MAAM,WAAW,iBAAiB;IACjC,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,eAAe,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,2BAA2B,EAAE,iBAGzC,CAAC;
|
|
1
|
+
{"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../lib/rotation.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/rotation.js
CHANGED
|
@@ -132,7 +132,14 @@ export const DEFAULT_TOKEN_BUCKET_CONFIG = {
|
|
|
132
132
|
maxTokens: 50,
|
|
133
133
|
tokensPerMinute: 6,
|
|
134
134
|
};
|
|
135
|
-
|
|
135
|
+
// Must cover the full request lifetime so a token consumed at request start can
|
|
136
|
+
// still be refunded when the request fails at the very end. The runtime proxy
|
|
137
|
+
// refunds on network error / upstream timeout, and the default fetch timeout is
|
|
138
|
+
// 60_000ms (config.ts fetchTimeoutMs) — measured AFTER token consumption and a
|
|
139
|
+
// token refresh. 90_000ms = that 60s timeout plus slack for the refresh and
|
|
140
|
+
// processing, so a genuinely timed-out request's token is reversed instead of
|
|
141
|
+
// leaking (gradual token-bucket starvation -> spurious token-exhausted skips).
|
|
142
|
+
const TOKEN_REFUND_WINDOW_MS = 90_000;
|
|
136
143
|
/**
|
|
137
144
|
* Client-side token bucket for rate limiting requests per account.
|
|
138
145
|
* Prevents sending requests to accounts that are likely to be rate-limited.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ModelFamily } from "../prompts/codex.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type AccountStorageV3, type FlaggedAccountMetadataV1 } from "../storage.js";
|
|
3
3
|
import type { AccountIdSource, TokenResult } from "../types.js";
|
|
4
4
|
import type { AccountCheckWorkingState } from "./account-check-types.js";
|
|
5
5
|
import type { CodexQuotaSnapshot } from "./quota-headers.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-check.d.ts","sourceRoot":"","sources":["../../../lib/runtime/account-check.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"account-check.d.ts","sourceRoot":"","sources":["../../../lib/runtime/account-check.ts"],"names":[],"mappings":"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"}
|