codex-multi-auth 2.16.0 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/README.md +22 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +8 -3
  5. package/dist/lib/account-policy.d.ts +4 -0
  6. package/dist/lib/account-policy.d.ts.map +1 -1
  7. package/dist/lib/account-policy.js +8 -0
  8. package/dist/lib/accounts/rate-limits.d.ts.map +1 -1
  9. package/dist/lib/accounts/rate-limits.js +2 -0
  10. package/dist/lib/accounts.d.ts +21 -3
  11. package/dist/lib/accounts.d.ts.map +1 -1
  12. package/dist/lib/accounts.js +229 -17
  13. package/dist/lib/api-route-store.d.ts +24 -0
  14. package/dist/lib/api-route-store.d.ts.map +1 -0
  15. package/dist/lib/api-route-store.js +145 -0
  16. package/dist/lib/auth/account-access.d.ts +115 -0
  17. package/dist/lib/auth/account-access.d.ts.map +1 -0
  18. package/dist/lib/auth/account-access.js +214 -0
  19. package/dist/lib/auth/token-utils.d.ts +54 -1
  20. package/dist/lib/auth/token-utils.d.ts.map +1 -1
  21. package/dist/lib/auth/token-utils.js +92 -7
  22. package/dist/lib/cli.d.ts +1 -1
  23. package/dist/lib/cli.d.ts.map +1 -1
  24. package/dist/lib/cli.js +4 -0
  25. package/dist/lib/codex-cli/state.d.ts +7 -0
  26. package/dist/lib/codex-cli/state.d.ts.map +1 -1
  27. package/dist/lib/codex-cli/state.js +18 -0
  28. package/dist/lib/codex-cli/writer.d.ts.map +1 -1
  29. package/dist/lib/codex-cli/writer.js +60 -8
  30. package/dist/lib/codex-manager/account-manager-commands.d.ts.map +1 -1
  31. package/dist/lib/codex-manager/account-manager-commands.js +1 -0
  32. package/dist/lib/codex-manager/account-pool-write.d.ts +3 -1
  33. package/dist/lib/codex-manager/account-pool-write.d.ts.map +1 -1
  34. package/dist/lib/codex-manager/account-pool-write.js +4 -0
  35. package/dist/lib/codex-manager/api-login-menu.d.ts +14 -0
  36. package/dist/lib/codex-manager/api-login-menu.d.ts.map +1 -0
  37. package/dist/lib/codex-manager/api-login-menu.js +224 -0
  38. package/dist/lib/codex-manager/commands/account.d.ts.map +1 -1
  39. package/dist/lib/codex-manager/commands/account.js +27 -0
  40. package/dist/lib/codex-manager/commands/best.d.ts.map +1 -1
  41. package/dist/lib/codex-manager/commands/best.js +6 -2
  42. package/dist/lib/codex-manager/commands/check.d.ts +7 -1
  43. package/dist/lib/codex-manager/commands/check.d.ts.map +1 -1
  44. package/dist/lib/codex-manager/commands/check.js +24 -3
  45. package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -1
  46. package/dist/lib/codex-manager/commands/forecast.js +5 -1
  47. package/dist/lib/codex-manager/commands/report.d.ts.map +1 -1
  48. package/dist/lib/codex-manager/commands/report.js +5 -1
  49. package/dist/lib/codex-manager/commands/resets.d.ts +2 -0
  50. package/dist/lib/codex-manager/commands/resets.d.ts.map +1 -0
  51. package/dist/lib/codex-manager/commands/resets.js +67 -0
  52. package/dist/lib/codex-manager/commands/rotation.d.ts +2 -2
  53. package/dist/lib/codex-manager/commands/rotation.d.ts.map +1 -1
  54. package/dist/lib/codex-manager/commands/rotation.js +63 -12
  55. package/dist/lib/codex-manager/commands/status.d.ts +12 -1
  56. package/dist/lib/codex-manager/commands/status.d.ts.map +1 -1
  57. package/dist/lib/codex-manager/commands/status.js +166 -22
  58. package/dist/lib/codex-manager/commands/uninstall.js +1 -1
  59. package/dist/lib/codex-manager/formatters/quota-formatters.d.ts.map +1 -1
  60. package/dist/lib/codex-manager/formatters/quota-formatters.js +3 -2
  61. package/dist/lib/codex-manager/health-check.d.ts +3 -0
  62. package/dist/lib/codex-manager/health-check.d.ts.map +1 -1
  63. package/dist/lib/codex-manager/health-check.js +56 -6
  64. package/dist/lib/codex-manager/help.d.ts.map +1 -1
  65. package/dist/lib/codex-manager/help.js +4 -2
  66. package/dist/lib/codex-manager/login-flow.d.ts.map +1 -1
  67. package/dist/lib/codex-manager/login-flow.js +69 -7
  68. package/dist/lib/codex-manager/login-menu-data.d.ts.map +1 -1
  69. package/dist/lib/codex-manager/login-menu-data.js +14 -5
  70. package/dist/lib/codex-manager/login-oauth.d.ts +3 -0
  71. package/dist/lib/codex-manager/login-oauth.d.ts.map +1 -1
  72. package/dist/lib/codex-manager/login-oauth.js +6 -1
  73. package/dist/lib/codex-manager/login-workspace-choice.d.ts +11 -0
  74. package/dist/lib/codex-manager/login-workspace-choice.d.ts.map +1 -0
  75. package/dist/lib/codex-manager/login-workspace-choice.js +37 -0
  76. package/dist/lib/codex-manager/persist-selected-account.d.ts.map +1 -1
  77. package/dist/lib/codex-manager/persist-selected-account.js +2 -1
  78. package/dist/lib/codex-manager/repair-commands.d.ts +13 -0
  79. package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -1
  80. package/dist/lib/codex-manager/repair-commands.js +143 -8
  81. package/dist/lib/codex-manager.d.ts.map +1 -1
  82. package/dist/lib/codex-manager.js +25 -6
  83. package/dist/lib/concurrency.d.ts +3 -0
  84. package/dist/lib/concurrency.d.ts.map +1 -0
  85. package/dist/lib/concurrency.js +31 -0
  86. package/dist/lib/model-route-policy.d.ts +52 -0
  87. package/dist/lib/model-route-policy.d.ts.map +1 -0
  88. package/dist/lib/model-route-policy.js +159 -0
  89. package/dist/lib/policy/runtime-policy.d.ts +1 -0
  90. package/dist/lib/policy/runtime-policy.d.ts.map +1 -1
  91. package/dist/lib/policy/runtime-policy.js +3 -0
  92. package/dist/lib/preemptive-quota-scheduler.d.ts +2 -0
  93. package/dist/lib/preemptive-quota-scheduler.d.ts.map +1 -1
  94. package/dist/lib/preemptive-quota-scheduler.js +4 -0
  95. package/dist/lib/quota-probe.d.ts +5 -0
  96. package/dist/lib/quota-probe.d.ts.map +1 -1
  97. package/dist/lib/quota-probe.js +26 -2
  98. package/dist/lib/request/client-cancellation.d.ts +5 -0
  99. package/dist/lib/request/client-cancellation.d.ts.map +1 -0
  100. package/dist/lib/request/client-cancellation.js +7 -0
  101. package/dist/lib/request/response-outcome.d.ts +25 -0
  102. package/dist/lib/request/response-outcome.d.ts.map +1 -0
  103. package/dist/lib/request/response-outcome.js +49 -0
  104. package/dist/lib/request/stream-failover-runtime.d.ts +2 -1
  105. package/dist/lib/request/stream-failover-runtime.d.ts.map +1 -1
  106. package/dist/lib/request/stream-failover-runtime.js +29 -10
  107. package/dist/lib/runtime/account-check.d.ts.map +1 -1
  108. package/dist/lib/runtime/account-check.js +2 -8
  109. package/dist/lib/runtime/account-model-catalog.d.ts +64 -0
  110. package/dist/lib/runtime/account-model-catalog.d.ts.map +1 -0
  111. package/dist/lib/runtime/account-model-catalog.js +154 -0
  112. package/dist/lib/runtime/account-pool.d.ts +3 -1
  113. package/dist/lib/runtime/account-pool.d.ts.map +1 -1
  114. package/dist/lib/runtime/account-pool.js +4 -0
  115. package/dist/lib/runtime/account-reset-credits.d.ts +42 -0
  116. package/dist/lib/runtime/account-reset-credits.d.ts.map +1 -0
  117. package/dist/lib/runtime/account-reset-credits.js +82 -0
  118. package/dist/lib/runtime/api-model-capabilities.d.ts +30 -0
  119. package/dist/lib/runtime/api-model-capabilities.d.ts.map +1 -0
  120. package/dist/lib/runtime/api-model-capabilities.js +434 -0
  121. package/dist/lib/runtime/api-model-runtime.d.ts +42 -0
  122. package/dist/lib/runtime/api-model-runtime.d.ts.map +1 -0
  123. package/dist/lib/runtime/api-model-runtime.js +358 -0
  124. package/dist/lib/runtime/app-bind.d.ts +19 -1
  125. package/dist/lib/runtime/app-bind.d.ts.map +1 -1
  126. package/dist/lib/runtime/app-bind.js +79 -9
  127. package/dist/lib/runtime/automatic-account-checks.d.ts +31 -0
  128. package/dist/lib/runtime/automatic-account-checks.d.ts.map +1 -0
  129. package/dist/lib/runtime/automatic-account-checks.js +113 -0
  130. package/dist/lib/runtime/automatic-subscription-checks.d.ts +7 -0
  131. package/dist/lib/runtime/automatic-subscription-checks.d.ts.map +1 -0
  132. package/dist/lib/runtime/automatic-subscription-checks.js +57 -0
  133. package/dist/lib/runtime/catalog-capabilities.d.ts +8 -0
  134. package/dist/lib/runtime/catalog-capabilities.d.ts.map +1 -0
  135. package/dist/lib/runtime/catalog-capabilities.js +61 -0
  136. package/dist/lib/runtime/inference-activity.d.ts +15 -0
  137. package/dist/lib/runtime/inference-activity.d.ts.map +1 -0
  138. package/dist/lib/runtime/inference-activity.js +95 -0
  139. package/dist/lib/runtime/model-discovery-status.d.ts +100 -0
  140. package/dist/lib/runtime/model-discovery-status.d.ts.map +1 -0
  141. package/dist/lib/runtime/model-discovery-status.js +387 -0
  142. package/dist/lib/runtime/native-account-storage.d.ts +11 -0
  143. package/dist/lib/runtime/native-account-storage.d.ts.map +1 -0
  144. package/dist/lib/runtime/native-account-storage.js +50 -0
  145. package/dist/lib/runtime/native-account-sync.d.ts +19 -0
  146. package/dist/lib/runtime/native-account-sync.d.ts.map +1 -0
  147. package/dist/lib/runtime/native-account-sync.js +62 -0
  148. package/dist/lib/runtime/native-binding-lock.d.ts +3 -0
  149. package/dist/lib/runtime/native-binding-lock.d.ts.map +1 -0
  150. package/dist/lib/runtime/native-binding-lock.js +5 -0
  151. package/dist/lib/runtime/native-client-auth.d.ts +3 -0
  152. package/dist/lib/runtime/native-client-auth.d.ts.map +1 -0
  153. package/dist/lib/runtime/native-client-auth.js +42 -0
  154. package/dist/lib/runtime/native-provider-config.d.ts +4 -0
  155. package/dist/lib/runtime/native-provider-config.d.ts.map +1 -0
  156. package/dist/lib/runtime/native-provider-config.js +52 -0
  157. package/dist/lib/runtime/native-rate-limits.d.ts +18 -0
  158. package/dist/lib/runtime/native-rate-limits.d.ts.map +1 -0
  159. package/dist/lib/runtime/native-rate-limits.js +135 -0
  160. package/dist/lib/runtime/reset-credit-routing.d.ts +41 -0
  161. package/dist/lib/runtime/reset-credit-routing.d.ts.map +1 -0
  162. package/dist/lib/runtime/reset-credit-routing.js +66 -0
  163. package/dist/lib/runtime/reset-credits.d.ts +101 -0
  164. package/dist/lib/runtime/reset-credits.d.ts.map +1 -0
  165. package/dist/lib/runtime/reset-credits.js +162 -0
  166. package/dist/lib/runtime/response-output-history.d.ts +17 -0
  167. package/dist/lib/runtime/response-output-history.d.ts.map +1 -0
  168. package/dist/lib/runtime/response-output-history.js +85 -0
  169. package/dist/lib/runtime/responses-websocket.d.ts +31 -0
  170. package/dist/lib/runtime/responses-websocket.d.ts.map +1 -0
  171. package/dist/lib/runtime/responses-websocket.js +636 -0
  172. package/dist/lib/runtime/resume-picker.d.ts +41 -0
  173. package/dist/lib/runtime/resume-picker.d.ts.map +1 -0
  174. package/dist/lib/runtime/resume-picker.js +169 -0
  175. package/dist/lib/runtime/rotation-account-selection.d.ts +6 -0
  176. package/dist/lib/runtime/rotation-account-selection.d.ts.map +1 -1
  177. package/dist/lib/runtime/rotation-account-selection.js +63 -0
  178. package/dist/lib/runtime/rotation-proxy-state.d.ts +33 -0
  179. package/dist/lib/runtime/rotation-proxy-state.d.ts.map +1 -1
  180. package/dist/lib/runtime/rotation-server-types.d.ts +18 -0
  181. package/dist/lib/runtime/rotation-server-types.d.ts.map +1 -1
  182. package/dist/lib/runtime/runtime-capability-failures.d.ts +14 -0
  183. package/dist/lib/runtime/runtime-capability-failures.d.ts.map +1 -0
  184. package/dist/lib/runtime/runtime-capability-failures.js +76 -0
  185. package/dist/lib/runtime/runtime-observability.d.ts +7 -0
  186. package/dist/lib/runtime/runtime-observability.d.ts.map +1 -1
  187. package/dist/lib/runtime/runtime-observability.js +42 -2
  188. package/dist/lib/runtime/subscription-first-use.d.ts +10 -0
  189. package/dist/lib/runtime/subscription-first-use.d.ts.map +1 -0
  190. package/dist/lib/runtime/subscription-first-use.js +64 -0
  191. package/dist/lib/runtime/subscription-quota-event.d.ts +6 -0
  192. package/dist/lib/runtime/subscription-quota-event.d.ts.map +1 -0
  193. package/dist/lib/runtime/subscription-quota-event.js +31 -0
  194. package/dist/lib/runtime/subscription-quota-order.d.ts +17 -0
  195. package/dist/lib/runtime/subscription-quota-order.d.ts.map +1 -0
  196. package/dist/lib/runtime/subscription-quota-order.js +31 -0
  197. package/dist/lib/runtime/workspace-model-scopes.d.ts +15 -0
  198. package/dist/lib/runtime/workspace-model-scopes.d.ts.map +1 -0
  199. package/dist/lib/runtime/workspace-model-scopes.js +34 -0
  200. package/dist/lib/runtime-constants.d.ts +3 -0
  201. package/dist/lib/runtime-constants.d.ts.map +1 -1
  202. package/dist/lib/runtime-constants.js +5 -0
  203. package/dist/lib/runtime-paths.d.ts.map +1 -1
  204. package/dist/lib/runtime-paths.js +4 -1
  205. package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
  206. package/dist/lib/runtime-rotation-proxy.js +852 -42
  207. package/dist/lib/schemas.d.ts +20 -0
  208. package/dist/lib/schemas.d.ts.map +1 -1
  209. package/dist/lib/schemas.js +3 -0
  210. package/dist/lib/storage/credential-sidecars.d.ts +13 -0
  211. package/dist/lib/storage/credential-sidecars.d.ts.map +1 -0
  212. package/dist/lib/storage/credential-sidecars.js +52 -0
  213. package/dist/lib/storage/file-lock.d.ts +9 -0
  214. package/dist/lib/storage/file-lock.d.ts.map +1 -0
  215. package/dist/lib/storage/file-lock.js +186 -0
  216. package/dist/lib/storage/flagged-storage.d.ts.map +1 -1
  217. package/dist/lib/storage/flagged-storage.js +12 -0
  218. package/dist/lib/storage/path-state.d.ts +2 -0
  219. package/dist/lib/storage/path-state.d.ts.map +1 -1
  220. package/dist/lib/storage/path-state.js +9 -0
  221. package/dist/lib/storage/paths.js +4 -4
  222. package/dist/lib/storage/pending-auth.d.ts +17 -0
  223. package/dist/lib/storage/pending-auth.d.ts.map +1 -0
  224. package/dist/lib/storage/pending-auth.js +153 -0
  225. package/dist/lib/storage/public-types.d.ts +13 -0
  226. package/dist/lib/storage/public-types.d.ts.map +1 -1
  227. package/dist/lib/storage/snapshot-merge.d.ts +16 -0
  228. package/dist/lib/storage/snapshot-merge.d.ts.map +1 -0
  229. package/dist/lib/storage/snapshot-merge.js +206 -0
  230. package/dist/lib/storage/transactions.d.ts.map +1 -1
  231. package/dist/lib/storage/transactions.js +5 -4
  232. package/dist/lib/storage.d.ts +6 -0
  233. package/dist/lib/storage.d.ts.map +1 -1
  234. package/dist/lib/storage.js +77 -7
  235. package/dist/lib/ui/auth-menu-builder.d.ts +2 -0
  236. package/dist/lib/ui/auth-menu-builder.d.ts.map +1 -1
  237. package/dist/lib/ui/auth-menu-builder.js +1 -0
  238. package/dist/lib/ui/auth-menu.d.ts.map +1 -1
  239. package/dist/lib/ui/auth-menu.js +1 -0
  240. package/dist/lib/ui/check-progress.d.ts +8 -0
  241. package/dist/lib/ui/check-progress.d.ts.map +1 -0
  242. package/dist/lib/ui/check-progress.js +30 -0
  243. package/dist/lib/ui/format.d.ts +3 -1
  244. package/dist/lib/ui/format.d.ts.map +1 -1
  245. package/dist/lib/ui/format.js +8 -0
  246. package/dist/lib/ui/ui-copy.d.ts +2 -2
  247. package/dist/lib/ui/ui-copy.js +2 -2
  248. package/dist/lib/usage/pricing.js +2 -2
  249. package/dist/lib/usage/usage-extraction.d.ts +3 -1
  250. package/dist/lib/usage/usage-extraction.d.ts.map +1 -1
  251. package/dist/lib/usage/usage-extraction.js +46 -9
  252. package/package.json +7 -4
  253. package/scripts/codex-app-router.js +7 -0
  254. package/scripts/codex-bin-resolver.js +40 -8
  255. package/scripts/codex-routing.js +1 -0
  256. package/scripts/codex.js +100 -22
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-policy.d.ts","sourceRoot":"","sources":["../../../lib/policy/runtime-policy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime-policy.d.ts","sourceRoot":"","sources":["../../../lib/policy/runtime-policy.ts"],"names":[],"mappings":"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"}
@@ -72,6 +72,7 @@ export async function evaluateRuntimePolicy(input) {
72
72
  const blockedAccountIndexes = new Set();
73
73
  const blockedAccountReasons = {};
74
74
  const scoreBoostByAccount = {};
75
+ const priorityByAccount = {};
75
76
  const profile = input.state.project.profile;
76
77
  if (profile?.modelDenylist.length && matchesModel(profile.modelDenylist, input.model)) {
77
78
  reasons.push("routing profile denies requested model");
@@ -101,6 +102,7 @@ export async function evaluateRuntimePolicy(input) {
101
102
  refreshToken: account.refreshToken ?? undefined,
102
103
  }, account.index);
103
104
  const accountPolicy = input.state.accountPolicies.accounts[accountKey];
105
+ priorityByAccount[account.index] = accountPolicy?.priority ?? 1;
104
106
  let boost = 0;
105
107
  if (accountPolicy?.paused) {
106
108
  blockedAccountIndexes.add(account.index);
@@ -155,6 +157,7 @@ export async function evaluateRuntimePolicy(input) {
155
157
  blockedAccountIndexes,
156
158
  blockedAccountReasons,
157
159
  scoreBoostByAccount,
160
+ priorityByAccount,
158
161
  budgetEvaluations,
159
162
  };
160
163
  }
@@ -58,6 +58,8 @@ export declare class PreemptiveQuotaScheduler {
58
58
  * silent clear-all; use `clearAll()` when that is the intent.
59
59
  */
60
60
  clearByPrefix(prefix: string): void;
61
+ /** Forget one verified recovered model; preserve sibling quota buckets. */
62
+ clear(key: string): void;
61
63
  /** Forget every cached quota observation. */
62
64
  clearAll(): void;
63
65
  prune(now?: number): number;
@@ -1 +1 @@
1
- {"version":3,"file":"preemptive-quota-scheduler.d.ts","sourceRoot":"","sources":["../../lib/preemptive-quota-scheduler.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,oBAAoB,CAAC;IAC9B,SAAS,EAAE,oBAAoB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,YAAY,GAAG,uBAAuB,CAAC;CAChD;AAED,MAAM,WAAW,qBAAqB;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,kCAAkC,CAAC,EAAE,MAAM,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AA6GD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,sBAAsB,GAAG,IAAI,CAqB5H;AAED,qBAAa,wBAAwB;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6C;IACvE,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,gCAAgC,CAAS;IACjD,OAAO,CAAC,kCAAkC,CAAS;IACnD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAK;gBAEZ,OAAO,GAAE,qBAA0B;IAQ/C,SAAS,CAAC,OAAO,GAAE,qBAA0B,GAAG,IAAI;IA2CpD,OAAO,CAAC,UAAU;IAMlB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,IAAI;IAM3D,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,IAAI;IA8B1E,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,qBAAqB;IAkEjE;;;;;;;;OAQG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAOnC,6CAA6C;IAC7C,QAAQ,IAAI,IAAI;IAIhB,KAAK,CAAC,GAAG,SAAa,GAAG,MAAM;CAW/B"}
1
+ {"version":3,"file":"preemptive-quota-scheduler.d.ts","sourceRoot":"","sources":["../../lib/preemptive-quota-scheduler.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,oBAAoB,CAAC;IAC9B,SAAS,EAAE,oBAAoB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,YAAY,GAAG,uBAAuB,CAAC;CAChD;AAED,MAAM,WAAW,qBAAqB;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,kCAAkC,CAAC,EAAE,MAAM,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AA6GD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,sBAAsB,GAAG,IAAI,CAqB5H;AAED,qBAAa,wBAAwB;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6C;IACvE,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,gCAAgC,CAAS;IACjD,OAAO,CAAC,kCAAkC,CAAS;IACnD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAK;gBAEZ,OAAO,GAAE,qBAA0B;IAQ/C,SAAS,CAAC,OAAO,GAAE,qBAA0B,GAAG,IAAI;IA2CpD,OAAO,CAAC,UAAU;IAMlB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,IAAI;IAM3D,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,IAAI;IA8B1E,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,qBAAqB;IAkEjE;;;;;;;;OAQG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAOnC,2EAA2E;IAC3E,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB,6CAA6C;IAC7C,QAAQ,IAAI,IAAI;IAIhB,KAAK,CAAC,GAAG,SAAa,GAAG,MAAM;CAW/B"}
@@ -281,6 +281,10 @@ export class PreemptiveQuotaScheduler {
281
281
  this.snapshots.delete(key);
282
282
  }
283
283
  }
284
+ /** Forget one verified recovered model; preserve sibling quota buckets. */
285
+ clear(key) {
286
+ this.snapshots.delete(key);
287
+ }
284
288
  /** Forget every cached quota observation. */
285
289
  clearAll() {
286
290
  this.snapshots.clear();
@@ -1,3 +1,4 @@
1
+ import { FirstUseProbeError } from "./runtime/subscription-first-use.js";
1
2
  /**
2
3
  * Human-readable note shown when a live probe fails solely because the account
3
4
  * lacks Codex entitlement (see {@link CodexUnavailableError}). Centralized so
@@ -25,6 +26,8 @@ export interface CodexQuotaWindow {
25
26
  resetAtMs?: number;
26
27
  }
27
28
  export interface CodexQuotaSnapshot {
29
+ primingCompleted?: boolean;
30
+ primingFailure?: FirstUseProbeError["reason"];
28
31
  status: number;
29
32
  planType?: string;
30
33
  activeLimit?: number;
@@ -57,6 +60,8 @@ export declare function formatQuotaResetAt(resetAtMs: number | undefined, nowMs?
57
60
  */
58
61
  export declare function formatQuotaSnapshotLine(snapshot: CodexQuotaSnapshot): string;
59
62
  export interface ProbeCodexQuotaOptions {
63
+ signal?: AbortSignal;
64
+ primeUnusedSubscription?: boolean;
60
65
  accountId: string;
61
66
  accessToken: string;
62
67
  model?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"quota-probe.d.ts","sourceRoot":"","sources":["../../lib/quota-probe.ts"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,yCAAyC,CAAC;AAEnF;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,OAAO,EACd,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GACrC,MAAM,CAMR;AAED,MAAM,WAAW,gBAAgB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACd;AA0MD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,KAAK,SAAa,GAChB,MAAM,GAAG,SAAS,CAqBpB;AAwBD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAa5E;AAED,MAAM,WAAW,sBAAsB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC5C,OAAO,EAAE,sBAAsB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CA4G7B"}
1
+ {"version":3,"file":"quota-probe.d.ts","sourceRoot":"","sources":["../../lib/quota-probe.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,kBAAkB,EAAyD,MAAM,qCAAqC,CAAC;AAEhI;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,yCAAyC,CAAC;AAEnF;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,OAAO,EACd,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GACrC,MAAM,CAMR;AAED,MAAM,WAAW,gBAAgB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACd;AAiND;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,KAAK,SAAa,GAChB,MAAM,GAAG,SAAS,CAqBpB;AAwBD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,CAa5E;AAED,MAAM,WAAW,sBAAsB;IACtC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC5C,OAAO,EAAE,sBAAsB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CA0H7B"}
@@ -1,10 +1,11 @@
1
- import { CODEX_BASE_URL } from "./constants.js";
1
+ import { CODEX_BASE_URL, MAX_RATE_LIMIT_DELAY_MS } from "./constants.js";
2
2
  import { createCodexHeaders, getUnsupportedCodexModelInfo } from "./request/fetch-helpers.js";
3
3
  import { QUOTA_PROBE_MODEL_CHAIN, resolveProbeReasoningEffort, } from "./request/helpers/model-map.js";
4
4
  import { CodexUnavailableError, isCodexUnavailableError } from "./errors.js";
5
5
  import { getCodexInstructions } from "./prompts/codex.js";
6
6
  import { mutateRuntimeObservabilitySnapshot } from "./runtime/runtime-observability.js";
7
7
  import { isRecord } from "./utils.js";
8
+ import { FirstUseProbeError, finishSubscriptionFirstUse, needsSubscriptionFirstUse } from "./runtime/subscription-first-use.js";
8
9
  /**
9
10
  * Human-readable note shown when a live probe fails solely because the account
10
11
  * lacks Codex entitlement (see {@link CodexUnavailableError}). Centralized so
@@ -79,6 +80,12 @@ function parseFiniteIntHeader(headers, name) {
79
80
  * Security: does not emit or persist header values; callers must redact any sensitive tokens before storing or logging headers.
80
81
  */
81
82
  function parseResetAtMs(headers, prefix) {
83
+ const raw = parseUnboundedResetAtMs(headers, prefix);
84
+ // A bogus header (finite, but overflowing once scaled to ms) must not read as
85
+ // a window that never resets.
86
+ return raw === undefined || Number.isNaN(raw) ? undefined : Math.min(raw, Date.now() + MAX_RATE_LIMIT_DELAY_MS);
87
+ }
88
+ function parseUnboundedResetAtMs(headers, prefix) {
82
89
  const resetAfterSeconds = parseFiniteIntHeader(headers, `${prefix}-reset-after-seconds`);
83
90
  if (typeof resetAfterSeconds === "number" && resetAfterSeconds > 0) {
84
91
  return Date.now() + resetAfterSeconds * 1000;
@@ -324,9 +331,11 @@ export async function fetchCodexQuotaSnapshot(options) {
324
331
  let sawUnsupportedModel = false;
325
332
  let sawOtherFailure = false;
326
333
  for (const model of models) {
334
+ options.signal?.throwIfAborted();
327
335
  attemptedAnyModel = true;
328
336
  try {
329
337
  const instructions = await getCodexInstructions(model);
338
+ options.signal?.throwIfAborted();
330
339
  const probeBody = {
331
340
  model,
332
341
  stream: true,
@@ -362,7 +371,7 @@ export async function fetchCodexQuotaSnapshot(options) {
362
371
  method: "POST",
363
372
  headers,
364
373
  body: JSON.stringify(probeBody),
365
- signal: controller.signal,
374
+ signal: options.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal,
366
375
  });
367
376
  }
368
377
  finally {
@@ -370,6 +379,18 @@ export async function fetchCodexQuotaSnapshot(options) {
370
379
  }
371
380
  const snapshotBase = parseQuotaSnapshotBase(response.headers, response.status);
372
381
  if (snapshotBase) {
382
+ if (options.primeUnusedSubscription && needsSubscriptionFirstUse(snapshotBase, Date.now())) {
383
+ try {
384
+ await finishSubscriptionFirstUse(response, timeoutMs);
385
+ return { ...snapshotBase, model, primingCompleted: true };
386
+ }
387
+ catch (error) {
388
+ // Keep valid quota data without retrying an accepted inference.
389
+ if (error instanceof FirstUseProbeError)
390
+ return { ...snapshotBase, model, primingFailure: error.reason };
391
+ throw error;
392
+ }
393
+ }
373
394
  try {
374
395
  await response.body?.cancel();
375
396
  }
@@ -406,6 +427,9 @@ export async function fetchCodexQuotaSnapshot(options) {
406
427
  lastError = new Error("Codex response did not include quota headers");
407
428
  }
408
429
  catch (error) {
430
+ options.signal?.throwIfAborted();
431
+ if (error instanceof FirstUseProbeError)
432
+ throw error;
409
433
  sawOtherFailure = true;
410
434
  lastError = error instanceof Error ? error : new Error(String(error));
411
435
  }
@@ -0,0 +1,5 @@
1
+ /** Internal transport marker: upstream timeouts may also use AbortError. */
2
+ export declare class ClientCancellationError extends Error {
3
+ constructor();
4
+ }
5
+ //# sourceMappingURL=client-cancellation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-cancellation.d.ts","sourceRoot":"","sources":["../../../lib/request/client-cancellation.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,qBAAa,uBAAwB,SAAQ,KAAK;;CAKjD"}
@@ -0,0 +1,7 @@
1
+ /** Internal transport marker: upstream timeouts may also use AbortError. */
2
+ export class ClientCancellationError extends Error {
3
+ constructor() {
4
+ super("Client cancelled request");
5
+ this.name = "AbortError";
6
+ }
7
+ }
@@ -0,0 +1,25 @@
1
+ export interface StreamCompletion {
2
+ success: boolean;
3
+ errorCode: string | null;
4
+ missingTerminal: boolean;
5
+ }
6
+ /** Protocol completion, separate from socket delivery. Never retain output or error messages. */
7
+ export declare class ResponseOutcome {
8
+ private readonly requireTerminal;
9
+ private terminal;
10
+ rejection: {
11
+ error: {
12
+ code?: string;
13
+ param?: string;
14
+ };
15
+ } | undefined;
16
+ constructor(requireTerminal: boolean);
17
+ observe(value: unknown): void;
18
+ /**
19
+ * `response.incomplete` (e.g. max_output_tokens) is a delivered response, not an
20
+ * account failure: it counts as success for health and affinity, and its terminal
21
+ * type survives only as the usage annotation in `errorCode`.
22
+ */
23
+ finish(): StreamCompletion;
24
+ }
25
+ //# sourceMappingURL=response-outcome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-outcome.d.ts","sourceRoot":"","sources":["../../../lib/request/response-outcome.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CACzB;AAED,iGAAiG;AACjG,qBAAa,eAAe;IAIf,OAAO,CAAC,QAAQ,CAAC,eAAe;IAH5C,OAAO,CAAC,QAAQ,CAAkE;IAClF,SAAS,EAAE;QAAE,KAAK,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAAG,SAAS,CAAC;gBAEvC,eAAe,EAAE,OAAO;IAErD,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAuB7B;;;;OAIG;IACH,MAAM,IAAI,gBAAgB;CAS1B"}
@@ -0,0 +1,49 @@
1
+ import { isRecord } from "../utils.js";
2
+ /** Protocol completion, separate from socket delivery. Never retain output or error messages. */
3
+ export class ResponseOutcome {
4
+ requireTerminal;
5
+ terminal;
6
+ rejection;
7
+ constructor(requireTerminal) {
8
+ this.requireTerminal = requireTerminal;
9
+ }
10
+ observe(value) {
11
+ if (!isRecord(value))
12
+ return;
13
+ let type = value.type ?? (value.object === "response" && typeof value.status === "string" ? `response.${value.status}` : undefined);
14
+ // SSE `response.done` carries its outcome in the nested status.
15
+ if (type === "response.done") {
16
+ const status = isRecord(value.response) ? value.response.status : undefined;
17
+ type = typeof status === "string" ? `response.${status}` : "response.completed";
18
+ }
19
+ if (type === "response.completed") {
20
+ if (!this.terminal)
21
+ this.terminal = "completed";
22
+ return;
23
+ }
24
+ const failure = type === "response.failed" || type === "error";
25
+ if (!failure && type !== "response.incomplete" && type !== "response.cancelled")
26
+ return;
27
+ this.terminal = failure ? "failed" : type === "response.incomplete" ? "incomplete" : "cancelled";
28
+ const response = isRecord(value.response) ? value.response : value;
29
+ const error = isRecord(response.error) ? response.error : type === "error" ? value : undefined;
30
+ if (error) {
31
+ const safe = (v) => typeof v === "string" && /^[A-Za-z0-9._-]{1,100}$/.test(v) ? v : undefined;
32
+ this.rejection = { error: { code: safe(error.code), param: safe(error.param) } };
33
+ }
34
+ }
35
+ /**
36
+ * `response.incomplete` (e.g. max_output_tokens) is a delivered response, not an
37
+ * account failure: it counts as success for health and affinity, and its terminal
38
+ * type survives only as the usage annotation in `errorCode`.
39
+ */
40
+ finish() {
41
+ const missingTerminal = this.requireTerminal && !this.terminal;
42
+ const success = !missingTerminal && (!this.terminal || this.terminal === "completed" || this.terminal === "incomplete");
43
+ return {
44
+ success,
45
+ missingTerminal,
46
+ errorCode: missingTerminal ? "upstream_missing_terminal" : this.terminal && this.terminal !== "completed" ? `upstream_response_${this.terminal}` : null,
47
+ };
48
+ }
49
+ }
@@ -1,5 +1,6 @@
1
1
  import type { ServerResponse } from "node:http";
2
2
  import type { RuntimeRotationProxyStatus } from "../runtime/rotation-server-types.js";
3
+ import type { StreamCompletion } from "./response-outcome.js";
3
4
  export declare const HOP_BY_HOP_HEADERS: Set<string>;
4
5
  export declare function responseHeadersForClient(upstreamHeaders: Headers): Record<string, string>;
5
6
  export declare function withTimeout<T>(promise: Promise<T>, timeoutMs: number, onTimeout: () => void, message: string): Promise<T>;
@@ -13,5 +14,5 @@ export declare function forwardStreamingResponse(upstream: Response, res: Server
13
14
  */
14
15
  onChunk?: (chunk: Uint8Array) => void,
15
16
  /** Additional response headers, applied after (so they can override) the forwarded upstream ones. */
16
- extraHeaders?: Record<string, string>): Promise<boolean>;
17
+ extraHeaders?: Record<string, string>, completion?: () => StreamCompletion): Promise<boolean>;
17
18
  //# sourceMappingURL=stream-failover-runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-failover-runtime.d.ts","sourceRoot":"","sources":["../../../lib/request/stream-failover-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAEtF,eAAO,MAAM,kBAAkB,aAW7B,CAAC;AAWH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUzF;AAED,wBAAsB,WAAW,CAAC,CAAC,EAClC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,IAAI,EACrB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,CAAC,CAmBZ;AAED,wBAAsB,aAAa,CAClC,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,SAAc,GACpB,OAAO,CAAC,MAAM,CAAC,CAuDjB;AAoBD,wBAAsB,wBAAwB,CAC7C,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,0BAA0B,EAClC,aAAa,EAAE,MAAM,IAAI,EACzB,oBAAoB,EAAE,MAAM;AAC5B;;;;;GAKG;AACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;AACrC,qGAAqG;AACrG,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,OAAO,CAAC,CAsDlB"}
1
+ {"version":3,"file":"stream-failover-runtime.d.ts","sourceRoot":"","sources":["../../../lib/request/stream-failover-runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,eAAO,MAAM,kBAAkB,aAW7B,CAAC;AAWH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUzF;AAED,wBAAsB,WAAW,CAAC,CAAC,EAClC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,IAAI,EACrB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,CAAC,CAmBZ;AAED,wBAAsB,aAAa,CAClC,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,SAAc,GACpB,OAAO,CAAC,MAAM,CAAC,CAuDjB;AAoBD,wBAAsB,wBAAwB,CAC7C,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,0BAA0B,EAClC,aAAa,EAAE,MAAM,IAAI,EACzB,oBAAoB,EAAE,MAAM;AAC5B;;;;;GAKG;AACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;AACrC,qGAAqG;AACrG,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,UAAU,CAAC,EAAE,MAAM,gBAAgB,GACjC,OAAO,CAAC,OAAO,CAAC,CAmElB"}
@@ -1,3 +1,4 @@
1
+ import { ClientCancellationError } from "./client-cancellation.js";
1
2
  export const HOP_BY_HOP_HEADERS = new Set([
2
3
  "connection",
3
4
  "content-length",
@@ -137,19 +138,34 @@ export async function forwardStreamingResponse(upstream, res, status, onStreamEr
137
138
  */
138
139
  onChunk,
139
140
  /** Additional response headers, applied after (so they can override) the forwarded upstream ones. */
140
- extraHeaders) {
141
+ extraHeaders, completion) {
141
142
  status.streamsStarted += 1;
142
143
  res.writeHead(upstream.status, {
143
144
  ...responseHeadersForClient(upstream.headers),
144
145
  ...extraHeaders,
145
146
  });
146
- if (!upstream.body) {
147
+ let clientDisconnected = false;
148
+ const finish = () => {
149
+ if (clientDisconnected || res.destroyed)
150
+ return false;
151
+ const result = completion?.();
152
+ // Already ended by a concurrent close path: never write after end.
153
+ if (res.writableEnded)
154
+ return false;
155
+ if (result && !result.success) {
156
+ status.lastError = result.errorCode;
157
+ if (result.missingTerminal)
158
+ res.write(Buffer.from(`data: ${JSON.stringify({ type: "error", error: { code: result.errorCode, message: "Upstream ended before completing the response." } })}\n\n`));
159
+ }
147
160
  res.end();
148
- return true;
149
- }
161
+ return result?.success ?? true;
162
+ };
163
+ if (!upstream.body)
164
+ return finish();
150
165
  const reader = upstream.body.getReader();
151
166
  res.on("close", () => {
152
167
  if (!res.writableEnded) {
168
+ clientDisconnected = true;
153
169
  void reader.cancel().catch(() => undefined);
154
170
  }
155
171
  });
@@ -163,10 +179,9 @@ extraHeaders) {
163
179
  if (value && value.byteLength > 0) {
164
180
  onChunk?.(value);
165
181
  // If the response is already finished (clean end by a concurrent
166
- // close-then-reader-cancel path), stop writing. Do NOT guard on
167
- // res.destroyed here: a socket-error-during-backpressure scenario sets
168
- // destroyed=true and then lets the next res.write() throw so the catch
169
- // block can record the error and fire onStreamError correctly.
182
+ // close-then-reader-cancel path), stop writing. A destroyed response
183
+ // is left to the next res.write(), which throws into the catch below;
184
+ // that path returns false without penalizing the upstream account.
170
185
  if (res.writableEnded)
171
186
  break;
172
187
  // Respect backpressure: when the client's socket buffer is full,
@@ -177,10 +192,14 @@ extraHeaders) {
177
192
  }
178
193
  }
179
194
  }
180
- res.end();
181
- return true;
195
+ return finish();
182
196
  }
183
197
  catch (error) {
198
+ if (clientDisconnected || res.destroyed || (error instanceof ClientCancellationError)) {
199
+ if (!res.destroyed)
200
+ res.destroy();
201
+ return false;
202
+ }
184
203
  status.lastError = error instanceof Error ? error.message : String(error);
185
204
  onStreamError();
186
205
  if (!res.destroyed) {
@@ -1 +1 @@
1
- {"version":3,"file":"account-check.d.ts","sourceRoot":"","sources":["../../../lib/runtime/account-check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"account-check.d.ts","sourceRoot":"","sources":["../../../lib/runtime/account-check.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,11 @@
1
1
  import { maskEmail } from "../logger.js";
2
2
  import { CODEX_UNAVAILABLE_PROBE_NOTE } from "../quota-probe.js";
3
3
  import { isCodexUnavailableError } from "../errors.js";
4
- import { bumpStorageAffinityGeneration, reconcilePinnedAccountIndex, } from "../storage.js";
4
+ import { cloneTrackedAccountStorage, bumpStorageAffinityGeneration, reconcilePinnedAccountIndex, } from "../storage.js";
5
5
  export async function runRuntimeAccountCheck(deepProbe, deps) {
6
6
  const loadedStorage = await deps.hydrateEmails(await deps.loadAccounts());
7
7
  const workingStorage = loadedStorage
8
- ? {
9
- ...loadedStorage,
10
- accounts: loadedStorage.accounts.map((account) => ({ ...account })),
11
- activeIndexByFamily: loadedStorage.activeIndexByFamily
12
- ? { ...loadedStorage.activeIndexByFamily }
13
- : {},
14
- }
8
+ ? cloneTrackedAccountStorage(loadedStorage)
15
9
  : deps.createEmptyStorage();
16
10
  if (workingStorage.accounts.length === 0) {
17
11
  deps.showLine("\nNo accounts to check.\n");
@@ -0,0 +1,64 @@
1
+ export declare class CatalogRetryError extends Error {
2
+ readonly retryAfterMs: number;
3
+ constructor(retryAfterMs: number);
4
+ }
5
+ export type CatalogModel = Record<string, unknown> & {
6
+ slug: string;
7
+ };
8
+ /** Upper bound for a catalog 429 backoff, whatever Retry-After the upstream sends. */
9
+ export declare const MAX_CATALOG_RETRY_MS: number;
10
+ export declare function clampCatalogRetryMs(retryAfterMs: number | null | undefined): number;
11
+ /**
12
+ * Per-proxy discovery cache. Failed refreshes never advertise stale access, but
13
+ * they are "unknown", not "empty": only a successful fetch can exclude a model.
14
+ * Routing fails open: an outage or throttle lets inference through, and the last
15
+ * successfully fetched catalog (whatever its age) is the only thing that excludes.
16
+ */
17
+ export declare class AccountModelCatalog {
18
+ private readonly fetchCatalog;
19
+ private readonly now;
20
+ private readonly ttlMs;
21
+ private readonly cache;
22
+ private readonly updated;
23
+ private readonly pending;
24
+ constructor(fetchCatalog: (accountKey: string) => Promise<unknown>, now?: () => number, ttlMs?: number);
25
+ private read;
26
+ /** Picker-only stale-while-refresh view; routing still awaits fresh discovery. */
27
+ cachedList(accountKeys: string[]): CatalogModel[];
28
+ invalidate(): void;
29
+ /** Retry discovery while retaining known routing exclusions if it fails. */
30
+ refresh(): void;
31
+ supportsCached(key: string, model: string, effort?: string, tier?: string): boolean;
32
+ /**
33
+ * Routing view: the last successful catalog decides, whatever its age. A workspace
34
+ * that has never been fetched successfully (outage, throttle, slow discovery) is
35
+ * unknown and stays routable; only a fetched catalog can exclude a model.
36
+ */
37
+ supportsForRouting(key: string, model: string, effort?: string, tier?: string): boolean;
38
+ /** Refresh in the background; one fresh eligible route is enough to dispatch early.
39
+ * After the wait, routing falls back to {@link supportsForRouting}. The caller still ranks eligible accounts.
40
+ */
41
+ prepareRouting(keys: string[], model: string, effort?: string, tier?: string, eligible?: (key: string) => boolean, waitMs?: number): Promise<"ready" | "unavailable">;
42
+ list(accountKeys: string[], referenceKey?: string): Promise<CatalogModel[]>;
43
+ /** True unless a successfully fetched catalog omits the model. */
44
+ supports(accountKey: string, model: string, effort?: string, tier?: string): Promise<boolean>;
45
+ snapshot(key: string): {
46
+ checkedAt: number;
47
+ models: string[];
48
+ entitlements: {
49
+ serviceTiers: {
50
+ id: string;
51
+ name: string;
52
+ }[];
53
+ reasoningLevels: string[];
54
+ accessPrograms: string[];
55
+ probes?: {
56
+ [k: string]: "unsupported" | "verified" | "unverified" | "downgraded";
57
+ } | undefined;
58
+ checkedAt?: number | undefined;
59
+ model: string;
60
+ }[];
61
+ error: boolean;
62
+ };
63
+ }
64
+ //# sourceMappingURL=account-model-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-model-catalog.d.ts","sourceRoot":"","sources":["../../../lib/runtime/account-model-catalog.ts"],"names":[],"mappings":"AAKA,qBAAa,iBAAkB,SAAQ,KAAK;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM;gBAApB,YAAY,EAAE,MAAM;CACzC;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtE,sFAAsF;AACtF,eAAO,MAAM,oBAAoB,QAAc,CAAC;AAChD,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGnF;AAED;;;;;GAKG;AACH,qBAAa,mBAAmB;IAQ9B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IATvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAGlB;IACJ,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqD;gBAE3D,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EACtD,GAAG,GAAE,MAAM,MAAiB,EAC5B,KAAK,SAAa;YAEtB,IAAI;IAkDlB,kFAAkF;IAClF,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE;IAOjD,UAAU,IAAI,IAAI;IAClB,4EAA4E;IAC5E,OAAO,IAAI,IAAI;IACf,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO;IAInF;;;;OAIG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO;IAIvF;;OAEG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EACjF,QAAQ,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAoB,EAAE,MAAM,SAAO,GAC5D,OAAO,CAAC,OAAO,GAAG,aAAa,CAAC;IAe7B,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAYjF,kEAAkE;IAC5D,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAInG,QAAQ,CAAC,GAAG,EAAE,MAAM;;;;;;;;;;;;;;;;;;CAIpB"}
@@ -0,0 +1,154 @@
1
+ import { buildVisibleModelUnion, supportsModelSettings, modelEntitlements } from "../model-route-policy.js";
2
+ import { mapWithConcurrency } from "../concurrency.js";
3
+ import { clampCatalogContext, supportsCatalogSettings } from "./catalog-capabilities.js";
4
+ import { isRecord } from "../utils.js";
5
+ export class CatalogRetryError extends Error {
6
+ retryAfterMs;
7
+ constructor(retryAfterMs) {
8
+ super("Catalog temporarily rate limited");
9
+ this.retryAfterMs = retryAfterMs;
10
+ }
11
+ }
12
+ /** Upper bound for a catalog 429 backoff, whatever Retry-After the upstream sends. */
13
+ export const MAX_CATALOG_RETRY_MS = 15 * 60_000;
14
+ export function clampCatalogRetryMs(retryAfterMs) {
15
+ const value = typeof retryAfterMs === "number" && Number.isFinite(retryAfterMs) ? retryAfterMs : 60_000;
16
+ return Math.min(MAX_CATALOG_RETRY_MS, Math.max(60_000, value));
17
+ }
18
+ /**
19
+ * Per-proxy discovery cache. Failed refreshes never advertise stale access, but
20
+ * they are "unknown", not "empty": only a successful fetch can exclude a model.
21
+ * Routing fails open: an outage or throttle lets inference through, and the last
22
+ * successfully fetched catalog (whatever its age) is the only thing that excludes.
23
+ */
24
+ export class AccountModelCatalog {
25
+ fetchCatalog;
26
+ now;
27
+ ttlMs;
28
+ cache = new Map();
29
+ updated = new Set();
30
+ pending = new Map();
31
+ constructor(fetchCatalog, now = Date.now, ttlMs = 5 * 60_000) {
32
+ this.fetchCatalog = fetchCatalog;
33
+ this.now = now;
34
+ this.ttlMs = ttlMs;
35
+ }
36
+ async read(key) {
37
+ const cached = this.cache.get(key);
38
+ if (cached && cached.expires > this.now())
39
+ return cached.models;
40
+ const existing = this.pending.get(key);
41
+ if (existing)
42
+ return existing;
43
+ const task = (async () => {
44
+ let models = null;
45
+ let retryMs = Math.min(this.ttlMs, 5000);
46
+ try {
47
+ const value = await this.fetchCatalog(key);
48
+ if (!isRecord(value) ||
49
+ !Array.isArray(value.models) ||
50
+ value.models.length > 1000 ||
51
+ !value.models.every((m) => isRecord(m) &&
52
+ typeof m.slug === "string" &&
53
+ m.slug.length > 0 &&
54
+ m.slug.length < 256)) {
55
+ throw new Error("Invalid account model catalog");
56
+ }
57
+ models = value.models;
58
+ }
59
+ catch (error) {
60
+ if (error instanceof CatalogRetryError)
61
+ retryMs = clampCatalogRetryMs(error.retryAfterMs);
62
+ /* Unknown; list() advertises nothing from it and supports() fails open. */
63
+ }
64
+ const previous = this.cache.get(key);
65
+ if (!previous && this.cache.size >= 3000)
66
+ this.cache.delete(this.cache.keys().next().value ?? "");
67
+ this.cache.set(key, {
68
+ lastGood: models ?? previous?.lastGood ?? null,
69
+ checkedAt: this.now(), error: models === null,
70
+ expires: this.now() +
71
+ (models !== null ? this.ttlMs : retryMs),
72
+ models,
73
+ });
74
+ for (const notify of this.updated)
75
+ notify();
76
+ return models;
77
+ })();
78
+ this.pending.set(key, task);
79
+ try {
80
+ return await task;
81
+ }
82
+ finally {
83
+ this.pending.delete(key);
84
+ }
85
+ }
86
+ /** Picker-only stale-while-refresh view; routing still awaits fresh discovery. */
87
+ cachedList(accountKeys) {
88
+ return buildVisibleModelUnion(accountKeys.map((key, index) => {
89
+ const entry = this.cache.get(key);
90
+ const usable = entry && !entry.error && entry.checkedAt <= this.now() && this.now() - entry.checkedAt < 15 * 60_000;
91
+ return { id: key, kind: "oauth", priority: index, enabled: true, models: usable ? entry.models ?? [] : [], visibleModels: null };
92
+ }));
93
+ }
94
+ invalidate() { this.cache.clear(); }
95
+ /** Retry discovery while retaining known routing exclusions if it fails. */
96
+ refresh() { for (const entry of this.cache.values())
97
+ entry.expires = Number.NEGATIVE_INFINITY; }
98
+ supportsCached(key, model, effort, tier) {
99
+ const cached = this.cache.get(key);
100
+ return Boolean(cached && !cached.error && cached.expires > this.now() && cached.models?.some(entry => entry.slug === model && supportsModelSettings(entry, effort, tier)));
101
+ }
102
+ /**
103
+ * Routing view: the last successful catalog decides, whatever its age. A workspace
104
+ * that has never been fetched successfully (outage, throttle, slow discovery) is
105
+ * unknown and stays routable; only a fetched catalog can exclude a model.
106
+ */
107
+ supportsForRouting(key, model, effort, tier) {
108
+ const known = this.cache.get(key)?.lastGood;
109
+ return !known || known.some(entry => entry.slug === model && supportsModelSettings(entry, effort, tier));
110
+ }
111
+ /** Refresh in the background; one fresh eligible route is enough to dispatch early.
112
+ * After the wait, routing falls back to {@link supportsForRouting}. The caller still ranks eligible accounts.
113
+ */
114
+ async prepareRouting(keys, model, effort, tier, eligible = () => true, waitMs = 2000) {
115
+ const ready = () => keys.some(key => eligible(key) && this.supportsCached(key, model, effort, tier));
116
+ let notify;
117
+ const available = new Promise(resolve => { notify = () => { if (ready())
118
+ resolve(); }; });
119
+ this.updated.add(notify);
120
+ let timer;
121
+ try {
122
+ const refresh = this.list(keys).then(() => undefined, () => undefined);
123
+ if (!ready())
124
+ await Promise.race([refresh, available, new Promise(resolve => { timer = setTimeout(resolve, waitMs); })]);
125
+ return ready() || keys.some(key => eligible(key) && this.supportsForRouting(key, model, effort, tier)) ? "ready" : "unavailable";
126
+ }
127
+ finally {
128
+ if (timer)
129
+ clearTimeout(timer);
130
+ this.updated.delete(notify);
131
+ }
132
+ }
133
+ async list(accountKeys, referenceKey) {
134
+ const models = new Map();
135
+ const catalogs = await mapWithConcurrency([...new Set([...accountKeys, ...(referenceKey ? [referenceKey] : [])])], 3, key => this.read(key));
136
+ const combined = buildVisibleModelUnion(catalogs.map((models, index) => ({ id: String(index), kind: "oauth", enabled: true, priority: index, models: models ?? [], visibleModels: null })));
137
+ for (const model of combined)
138
+ models.set(model.slug, model);
139
+ if (referenceKey) {
140
+ const reference = await this.read(referenceKey);
141
+ return (reference ?? []).map(model => clampCatalogContext(model, models.get(model.slug) ?? model));
142
+ }
143
+ return [...models.values()];
144
+ }
145
+ /** True unless a successfully fetched catalog omits the model. */
146
+ async supports(accountKey, model, effort, tier) {
147
+ const models = await this.read(accountKey);
148
+ return models === null ? true : models.some((entry) => entry.slug === model && supportsCatalogSettings(entry, effort, tier));
149
+ }
150
+ snapshot(key) {
151
+ const entry = this.cache.get(key);
152
+ return { checkedAt: entry?.checkedAt ?? 0, models: entry?.models?.map(m => m.slug) ?? [], entitlements: entry?.models?.map(modelEntitlements) ?? [], error: entry?.error ?? true };
153
+ }
154
+ }