codex-multi-auth 2.17.3 → 2.18.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.
@@ -12,66 +12,55 @@ const CHATGPT_CODEX_UNSUPPORTED_MODEL_PATTERN = /model is not supported when usi
12
12
  const NORMALIZED_UNSUPPORTED_MODEL_PATTERN = /the model ['"]([^'"]+)['"] is not currently available for this chatgpt account/i;
13
13
  const MODEL_ACCESS_DENIED_PATTERN = /the model [`'"]([^`'"]+)[`'"] does not exist or you do not have access to it/i;
14
14
  export const DEFAULT_UNSUPPORTED_CODEX_FALLBACK_CHAIN = {
15
- // GPT-6 Astra rolls out org by org, so an account that is not entitled yet
16
- // gets a real unsupported-model response for it. This chain only fires when
17
- // the user has opted into `fallbackOnUnsupportedCodexModel` (default
18
- // `false`), and only on that response, so it never silently swaps the model
19
- // out from under a request the account could have served.
15
+ // GPT-6 models roll out org by org, so an account that is not entitled yet
16
+ // gets a real unsupported-model response for them. This chain only fires
17
+ // when the user has opted into `fallbackOnUnsupportedCodexModel` (default
18
+ // `false`), and only on that response, so it never silently swaps the
19
+ // model out from under a request the account could have served.
20
20
  //
21
21
  // This table is walked ONE HOP AT A TIME, not as a per-request candidate
22
- // list. index.ts reassigns `model` to whatever came back and passes that as
23
- // `requestedModel` on the next unsupported response, so reaching `gpt-5.5`
24
- // from Astra requires `gpt-5.6-sol` to carry its own entry below. A second
25
- // element here is only ever consulted when the first is already in
26
- // `attemptedModels` for that same call.
22
+ // list. index.ts reassigns `model` to whatever came back and passes that
23
+ // as `requestedModel` on the next unsupported response, so reaching the
24
+ // terminal models from a launch model requires every intermediate model
25
+ // to carry its own entry below. A second element here is only ever
26
+ // consulted when the first is already in `attemptedModels` for that same
27
+ // call.
27
28
  //
28
- // Depth is not free: every hop spends one of the shared per-request outbound
29
- // attempts (`tryConsumeOutboundRequestAttempt`). A single-account balanced
30
- // session gets a budget of 5, and the aeon walk needs 4 (it needed all 5
31
- // until `gpt-5.4` was retired as the floor), leaving one attempt for a retry
32
- // or a stream failover. Spend two and the tail hop becomes unreachable,
33
- // ending as an attempt-budget-exhausted 503 rather than `gpt-5.5`. Hops are
29
+ // Depth is not free: every hop spends one of the shared per-request
30
+ // outbound attempts (`tryConsumeOutboundRequestAttempt`). A single-account
31
+ // balanced session gets a budget of 5, and the deepest walks — 6.1 Sol and
32
+ // the retired ids that migrate through Astra — spend all 5, the same shape
33
+ // the aeon walk had before `gpt-5.4` was retired as the floor. Hops are
34
34
  // ordered most-valuable-first so what is lost first matters least. Do not
35
- // add a hop to a GPT-6 row without
36
- // re-checking that budget; `test/gpt6-astra-models.test.ts` asserts it.
37
- "gpt-6-astra": ["gpt-5.6-sol", "gpt-5.5"],
38
- // aeon steps to the flagship first: still GPT-6, still Astra, just without
39
- // the long-horizon behaviour.
40
- "gpt-6-astra-aeon": ["gpt-6-astra", "gpt-5.6-sol"],
41
- // Sol and Luna step to the 5.6 tier they replace, never sideways into Astra:
42
- // an account without the new tier is far likelier to lack Astra too, and
43
- // Astra is the priciest hop available ($10/$50 per 1M against Luna's
44
- // $0.10/$0.50). Every hop on these walks still costs more than Luna itself.
35
+ // add a hop to a GPT-6 row without re-checking that budget;
36
+ // `test/gpt6-astra-models.test.ts` asserts it.
37
+ "gpt-6.1-sol": ["gpt-6-sol"],
38
+ // Astra steps to the workhorse rather than to a smaller tier: an account
39
+ // without the flagship is still likelier than not to hold the standard
40
+ // GPT-6 tier, and `gpt-6-sol` keeps the walk inside the generation.
41
+ "gpt-6-astra": ["gpt-6-sol"],
42
+ // Sol and Luna step to the 5.6 tier they replace, never sideways into a
43
+ // pricier model: an account without the new tier is far likelier to lack
44
+ // Astra too, and Astra is the priciest hop available ($10/$50 per 1M
45
+ // against Luna's $0.10/$0.50). Every hop on these walks still costs more
46
+ // than Luna itself.
45
47
  "gpt-6-sol": ["gpt-5.6-sol"],
46
48
  "gpt-6-luna": ["gpt-5.6-luna"],
47
- // The hop that makes the Astra path reach a model every account has. GPT-5.6
48
- // shipped without a chain entry, so an unsupported 5.6 response ended the
49
- // walk; with Astra above it that would have stranded the fallback one rung
50
- // short of the floor it documents.
51
- "gpt-5.6-sol": ["gpt-5.5"],
52
- // Luna gained its row once `gpt-6-luna` started stepping into it; without
53
- // it the Luna walk would stop one rung short of `gpt-5.5`, the same
54
- // stranding the Sol row fixed. It also applies to a direct `gpt-5.6-luna`
55
- // request, which used to end its walk on an unsupported response and now
56
- // retries on the pricier `gpt-5.5`.
57
- "gpt-5.6-luna": ["gpt-5.5"],
58
- // Terra gained its row once the retired codex minis and `gpt-5-mini` began
59
- // stepping into it; without it those walks stopped at Terra instead of the
60
- // `gpt-5.5` floor every other retired id reaches.
61
- "gpt-5.6-terra": ["gpt-5.5"],
62
- "gpt-5": ["gpt-5.5"],
63
- "gpt-5-pro": ["gpt-5.5-pro"],
64
- "gpt-5.5-2026-04-23": ["gpt-5.5"],
65
- "gpt-5.5-20260423": ["gpt-5.5"],
66
- "gpt-5.5-pro-2026-04-23": ["gpt-5.5-pro"],
67
- "gpt-5.5-pro-20260423": ["gpt-5.5-pro"],
68
- // `gpt-5.5` and `gpt-5.5-pro` are the floor: they used to step to `gpt-5.4`,
69
- // which the Codex backend no longer serves (`retirement_at: 2026-08-31` in
70
- // the upstream catalog), so that hop could only ever fail.
71
- //
49
+ // The hop that makes every general walk reach a model almost every account
50
+ // has: `gpt-6-luna` ships on the most plans of any catalog model, which is
51
+ // why the quota-probe chain also ends on it.
52
+ "gpt-5.6-sol": ["gpt-6-luna"],
53
+ // Luna's own row crosses to Sol rather than stopping: a `gpt-5.6-luna`
54
+ // request whose tier is absent retries on the same-generation workhorse
55
+ // instead of ending on an unsupported response.
56
+ "gpt-5.6-luna": ["gpt-5.6-sol"],
57
+ "gpt-5.6-terra": ["gpt-5.6-sol"],
58
+ "gpt-5": ["gpt-5.6-sol"],
59
+ "gpt-5-pro": ["gpt-6-astra"],
72
60
  // A retired id still reaches the backend verbatim through the pass-through
73
61
  // rotation proxy, and the backend rejects it as unsupported. One hop to the
74
- // replacement OpenAI names for it turns that into a working request.
62
+ // replacement OpenAI names for it turns that into a working request, and
63
+ // from there the same staircase above continues toward Luna.
75
64
  ...Object.fromEntries(Object.entries(RETIRED_MODEL_REPLACEMENTS).map(([retired, replacement]) => [
76
65
  retired,
77
66
  [replacement],
@@ -252,7 +252,7 @@ function normalizeErrorPayload(errorBody, bodyText, statusText, status, diagnost
252
252
  error: {
253
253
  message: `The model '${unsupportedModel}' is not currently available for this ChatGPT account when using Codex OAuth. ` +
254
254
  "This is an account/workspace entitlement gate, not a temporary rate limit. " +
255
- "Try 'gpt-5.6-sol' or 'gpt-5.5', or enable automatic fallback via " +
255
+ "Try 'gpt-6.1-sol' or 'gpt-5.6-sol', or enable automatic fallback via " +
256
256
  'unsupportedCodexPolicy: "fallback" (or CODEX_AUTH_UNSUPPORTED_MODEL_POLICY=fallback). ' +
257
257
  "(Legacy: CODEX_AUTH_FALLBACK_UNSUPPORTED_MODEL=1 or fallbackOnUnsupportedCodexModel).",
258
258
  type: "entitlement_error",
@@ -40,9 +40,9 @@ export interface ModelProfile {
40
40
  * still read naturally.
41
41
  */
42
42
  export declare const CURRENT_CODEX_MODEL = "gpt-5.6-sol";
43
- export declare const DEFAULT_MODEL = "gpt-5.5";
43
+ export declare const DEFAULT_MODEL = "gpt-6.1-sol";
44
44
  export declare const DEFAULT_PROBE_MODEL = "gpt-5.6-sol";
45
- export declare const QUOTA_PROBE_MODEL_CHAIN: readonly ["gpt-5.6-sol", "gpt-5.5", "gpt-6-luna"];
45
+ export declare const QUOTA_PROBE_MODEL_CHAIN: readonly ["gpt-5.6-sol", "gpt-6.1-sol", "gpt-6-luna"];
46
46
  /**
47
47
  * Effective model profiles keyed by canonical model name.
48
48
  *
@@ -67,20 +67,21 @@ export const CURRENT_CODEX_MODEL = "gpt-5.6-sol";
67
67
  * `gpt-5.1-codex-mini`, rather than up to Sol.
68
68
  */
69
69
  const CODEX_MINI_REPLACEMENT_MODEL = "gpt-5.6-terra";
70
- export const DEFAULT_MODEL = "gpt-5.5";
70
+ // The default tracks whatever upstream defaults a fresh Codex session to:
71
+ // `gpt-6.1-sol` entered the bundled catalog on 2026-09-29 as priority 1
72
+ // (openai/codex #49318), above Astra. `gpt-5.5`, the previous default here,
73
+ // retires from ChatGPT/Codex on 2026-10-14, so keeping it would have landed
74
+ // every unresolvable request — and the legacy `gpt-5` alias — on a dying id.
75
+ export const DEFAULT_MODEL = "gpt-6.1-sol";
71
76
  // Model used for diagnostic live/quota probes (`check`, `report`, `best`).
72
77
  // Deliberately distinct from DEFAULT_MODEL: GPT-5.6 is the latest general family
73
- // (issue #627), so the probe leads with it, while DEFAULT_MODEL stays on 5.5 so
74
- // actual request routing and the legacy `gpt-5` alias remain opt-in per 2.5.0.
78
+ // (issue #627) with a year of rollout behind it, so the probe leads with it —
79
+ // a probe only needs a response's quota headers, and leading with a fresh
80
+ // launch model (Astra on 2026-09-03, 6.1 Sol on 2026-09-29) spends one failed
81
+ // request per probe on every account not yet entitled and buys nothing. Move
82
+ // DEFAULT_PROBE_MODEL forward once a newer model is broadly available.
75
83
  // Bare `gpt-5.6` aliases to Sol; we pin the canonical id so the probe display
76
84
  // and report `modelSelection` read `gpt-5.6-sol` without a remap arrow.
77
- //
78
- // GPT-6 Astra deliberately does NOT lead the probe as of its 2026-09-03 launch.
79
- // A probe only needs a response's quota headers, and Astra is still rolling out
80
- // org by org, so leading with it would spend one failed request per probe for
81
- // every account without entitlement yet and buy nothing. Move DEFAULT_PROBE_MODEL
82
- // to `gpt-6-astra` once it is broadly available, and put `gpt-5.6-sol` directly
83
- // behind it in QUOTA_PROBE_MODEL_CHAIN.
84
85
  export const DEFAULT_PROBE_MODEL = "gpt-5.6-sol";
85
86
  // Single source of truth for the live/quota probe fallback chain. Both the
86
87
  // manager probe (lib/quota-probe.ts) and the runtime probe (lib/runtime/quota-probe.ts)
@@ -126,17 +127,16 @@ const GPT_5_6_LUNA_EFFORTS = [
126
127
  /**
127
128
  * GPT-6 Astra, OpenAI's 2026-09-03 frontier release.
128
129
  *
129
- * The launch lineup was the flagship plus `aeon`, a long-horizon variant built
130
- * for runs measured in days; Sol and Luna followed on 2026-09-22 (below).
131
- * `gpt-6-astra` is the API model name OpenAI published at launch;
132
- * `gpt-6-astra-aeon` is the second slug that shipped beside it in the Codex
133
- * model list. "Astra Pro" is a plan tier, not a separate slug we have seen, so
134
- * it is deliberately not registered as its own canonical model — the GPT-6
135
- * resolver below claims `gpt-6-astra-pro` and every other unrecognised GPT-6 id
136
- * for the flagship rather than letting it fall through to GPT-5.5.
130
+ * Sol and Luna followed on 2026-09-22 (below). `gpt-6-astra` is the API model
131
+ * name OpenAI published at launch. The long-horizon `gpt-6-astra-aeon` slug
132
+ * that leaked beside it never appeared in the bundled catalog or the public
133
+ * model docs and is retired below — its ids now alias the flagship. "Astra
134
+ * Pro" is a plan tier, not a separate slug we have seen, so it is deliberately
135
+ * not registered as its own canonical model — the GPT-6 resolver below claims
136
+ * `gpt-6-astra-pro` and every other unrecognised GPT-6 id for the flagship
137
+ * rather than letting it fall through to the default.
137
138
  */
138
139
  const GPT_6_ASTRA_MODEL = "gpt-6-astra";
139
- const GPT_6_ASTRA_AEON_MODEL = "gpt-6-astra-aeon";
140
140
  /** Bare `gpt-6` resolves to the flagship, mirroring bare `gpt-5.6` -> Sol. */
141
141
  const GPT_6_FLAGSHIP_ALIAS = "gpt-6";
142
142
  /**
@@ -171,6 +171,20 @@ const GPT_6_LUNA_EFFORTS = [
171
171
  "xhigh",
172
172
  "max",
173
173
  ];
174
+ /**
175
+ * GPT-6.1 Sol, the first 6.1 release: added to the upstream catalog on
176
+ * 2026-09-29 (openai/codex #49318) as the default model — priority 1, above
177
+ * Astra — with "near-Astra performance at a lower cost". The same commit
178
+ * demoted `gpt-6-sol` to "previous generation workhorse". The catalog ships
179
+ * the full low..ultra ladder with a `low` default (the API model page
180
+ * documents `medium` for direct-API callers; the Codex catalog this wrapper
181
+ * mirrors says `low`). Sol is the only 6.1 tier yet, so bare `gpt-6.1` and
182
+ * any unrecognised 6.1 id resolve to it, matching the bare-alias convention.
183
+ */
184
+ const GPT_6_1_SOL_MODEL = "gpt-6.1-sol";
185
+ /** Bare `gpt-6.1` resolves to Sol — the only tier OpenAI ships at 6.1. */
186
+ const GPT_6_1_FLAGSHIP_ALIAS = "gpt-6.1";
187
+ const GPT_6_1_SOL_EFFORTS = GPT_6_ASTRA_EFFORTS;
174
188
  /**
175
189
  * Cyber-specialty models from the upstream Codex catalog
176
190
  * (openai/codex `codex-rs/models-manager/models.json`).
@@ -192,47 +206,55 @@ const DAYBREAK_EFFORTS = [
192
206
  "max",
193
207
  "ultra",
194
208
  ];
195
- const GPT_5_5_CANONICAL_MODEL = "gpt-5.5";
196
- const GPT_5_5_PRO_CANONICAL_MODEL = "gpt-5.5-pro";
197
- const GPT_5_5_RELEASE_MODEL = "gpt-5.5-2026-04-23";
198
- const GPT_5_5_PRO_RELEASE_MODEL = "gpt-5.5-pro-2026-04-23";
199
- const GPT_5_5_RELEASE_COMPAT_MODEL = "gpt-5.5-20260423";
200
- const GPT_5_5_PRO_RELEASE_COMPAT_MODEL = "gpt-5.5-pro-20260423";
201
209
  /**
202
- * Where an unrecognised `gpt-5.<minor>` id lands. Every minor below 5.5 is
203
- * retired (OpenAI deprecations page, upstream catalog removals), so each maps
204
- * to the replacement OpenAI names for it rather than to a model that no longer
205
- * answers: 5.1/5.2 to Sol, 5.4 to GPT-6 Sol/Luna as upstream Codex migrates it,
206
- * and every `pro` to the one live pro model.
210
+ * Where an unrecognised `gpt-5.<minor>` id lands. Every known minor is
211
+ * retired (OpenAI deprecations page, upstream catalog removals, the
212
+ * 2026-10-14 `gpt-5.5` OAuth shutdown), so each maps to the replacement
213
+ * OpenAI names for it rather than to a model that no longer answers:
214
+ * 5.1/5.2 to Sol, 5.4 to GPT-6 Sol/Luna as upstream Codex migrates it,
215
+ * 5.5 to GPT-6 Sol likewise, and every `pro` to the frontier flagship that
216
+ * replaced the API-only `gpt-5.5-pro`.
207
217
  */
208
218
  const GENERAL_GPT5_VERSION_CATALOG = {
209
219
  1: {
210
220
  base: GPT_5_6_SOL_MODEL,
211
- pro: GPT_5_5_PRO_CANONICAL_MODEL,
221
+ pro: GPT_6_ASTRA_MODEL,
212
222
  },
213
223
  2: {
214
224
  base: GPT_5_6_SOL_MODEL,
215
- pro: GPT_5_5_PRO_CANONICAL_MODEL,
225
+ pro: GPT_6_ASTRA_MODEL,
216
226
  },
217
227
  4: {
218
228
  base: GPT_6_SOL_MODEL,
219
- pro: GPT_5_5_PRO_CANONICAL_MODEL,
229
+ pro: GPT_6_ASTRA_MODEL,
220
230
  mini: GPT_6_LUNA_MODEL,
221
231
  nano: GPT_6_LUNA_MODEL,
222
232
  },
223
233
  5: {
224
- base: GPT_5_5_CANONICAL_MODEL,
225
- pro: GPT_5_5_PRO_CANONICAL_MODEL,
234
+ base: GPT_6_SOL_MODEL,
235
+ pro: GPT_6_ASTRA_MODEL,
226
236
  mini: GPT_5_6_TERRA_MODEL,
227
237
  nano: GPT_5_6_LUNA_MODEL,
228
238
  },
229
239
  };
230
- const GENERAL_GPT5_STABLE_VARIANTS = GENERAL_GPT5_VERSION_CATALOG[5];
240
+ /**
241
+ * Landing spot for a `gpt-5.<minor>` whose minor this catalog does not know
242
+ * (a `gpt-5.7` or `gpt-5.9` id, say): the newest generation the 5.x line
243
+ * still serves. Deliberately NOT the migration target `gpt-6-sol` — an id
244
+ * naming a 5.x minor keeps its generation, the same way every known minor
245
+ * above lands on a living 5.x or the replacement OpenAI actually named.
246
+ */
247
+ const GENERAL_GPT5_STABLE_VARIANTS = {
248
+ base: GPT_5_6_SOL_MODEL,
249
+ pro: GPT_6_ASTRA_MODEL,
250
+ mini: GPT_5_6_TERRA_MODEL,
251
+ nano: GPT_5_6_LUNA_MODEL,
252
+ };
231
253
  // `gpt-5-mini`/`gpt-5-nano` point at snapshots OpenAI retires on 2026-12-11;
232
254
  // the deprecations page names Terra and Luna as their replacements.
233
255
  const GENERAL_GPT5_GENERIC_VARIANTS = {
234
- base: DEFAULT_MODEL,
235
- pro: GPT_5_5_PRO_CANONICAL_MODEL,
256
+ base: GPT_5_6_SOL_MODEL,
257
+ pro: GPT_6_ASTRA_MODEL,
236
258
  mini: GPT_5_6_TERRA_MODEL,
237
259
  nano: GPT_5_6_LUNA_MODEL,
238
260
  };
@@ -258,11 +280,11 @@ export const MODEL_PROFILES = {
258
280
  supportedReasoningEfforts: GPT_6_ASTRA_EFFORTS,
259
281
  capabilities: TOOL_CAPABILITIES.full,
260
282
  },
261
- [GPT_6_ASTRA_AEON_MODEL]: {
262
- normalizedModel: GPT_6_ASTRA_AEON_MODEL,
283
+ [GPT_6_1_SOL_MODEL]: {
284
+ normalizedModel: GPT_6_1_SOL_MODEL,
263
285
  promptFamily: "gpt-5.2",
264
- defaultReasoningEffort: "medium",
265
- supportedReasoningEfforts: GPT_6_ASTRA_EFFORTS,
286
+ defaultReasoningEffort: "low",
287
+ supportedReasoningEfforts: GPT_6_1_SOL_EFFORTS,
266
288
  capabilities: TOOL_CAPABILITIES.full,
267
289
  },
268
290
  [GPT_6_SOL_MODEL]: {
@@ -317,26 +339,15 @@ export const MODEL_PROFILES = {
317
339
  supportedReasoningEfforts: GPT_5_6_LUNA_EFFORTS,
318
340
  capabilities: TOOL_CAPABILITIES.full,
319
341
  },
320
- [GPT_5_5_CANONICAL_MODEL]: {
321
- normalizedModel: GPT_5_5_CANONICAL_MODEL,
322
- promptFamily: "gpt-5.2",
323
- defaultReasoningEffort: "none",
324
- supportedReasoningEfforts: ["none", "low", "medium", "high", "xhigh"],
325
- capabilities: TOOL_CAPABILITIES.full,
326
- },
327
- [GPT_5_5_PRO_CANONICAL_MODEL]: {
328
- normalizedModel: GPT_5_5_PRO_CANONICAL_MODEL,
329
- promptFamily: "gpt-5.2",
330
- defaultReasoningEffort: "high",
331
- supportedReasoningEfforts: ["medium", "high", "xhigh"],
332
- capabilities: TOOL_CAPABILITIES.computerAndCompact,
333
- },
334
- // Every model older than 5.5 is retired: `gpt-5.1`, `gpt-5.2` and the whole
335
- // 5.4 family left the upstream Codex catalog, the codex models and the
336
- // chat-latest snapshots are past their shutdown date on OpenAI's
337
- // deprecations page, and `gpt-5-mini`/`gpt-5-nano` shut down 2026-12-11.
338
- // Their ids stay accepted as aliases of the named replacement (below) so an
339
- // old config keeps working, but no request is sent under a dead name.
342
+ // 5.5 and older are all retired: `gpt-5.5` leaves ChatGPT/Codex on
343
+ // 2026-10-14, `gpt-5.5-pro` left the bundled Codex catalog earlier (it is
344
+ // API-only now, which this OAuth surface cannot serve), `gpt-5.1`,
345
+ // `gpt-5.2` and the whole 5.4 family left the upstream Codex catalog, the
346
+ // codex models and the chat-latest snapshots are past their shutdown date
347
+ // on OpenAI's deprecations page, and `gpt-5-mini`/`gpt-5-nano` shut down
348
+ // 2026-12-11. Their ids stay accepted as aliases of the named replacement
349
+ // (below) so an old config keeps working, but no request is sent under a
350
+ // dead name.
340
351
  };
341
352
  const MODEL_MAP = {};
342
353
  function addAlias(alias, normalizedModel) {
@@ -368,17 +379,21 @@ function addGpt56Aliases() {
368
379
  }
369
380
  function addGpt6Aliases() {
370
381
  addEffortAliases(GPT_6_ASTRA_MODEL, GPT_6_ASTRA_MODEL, GPT_6_ASTRA_EFFORTS);
371
- addEffortAliases(GPT_6_ASTRA_AEON_MODEL, GPT_6_ASTRA_AEON_MODEL, GPT_6_ASTRA_EFFORTS);
372
382
  addEffortAliases(GPT_6_FLAGSHIP_ALIAS, GPT_6_ASTRA_MODEL, GPT_6_ASTRA_EFFORTS);
373
383
  // `astra` on its own is how the model is spoken about everywhere; accept it
374
- // rather than letting it fall through to GPT-5.5.
384
+ // rather than letting it fall through to the default.
375
385
  addEffortAliases("astra", GPT_6_ASTRA_MODEL, GPT_6_ASTRA_EFFORTS);
376
- addEffortAliases("astra-aeon", GPT_6_ASTRA_AEON_MODEL, GPT_6_ASTRA_EFFORTS);
386
+ // `astra-aeon` was only ever a leaked slug and is retired now, so the name
387
+ // resolves to the flagship it was a variant of. Its `gpt-6-astra-aeon`
388
+ // form comes from the retired table, not from a dedicated registration.
389
+ addEffortAliases("astra-aeon", GPT_6_ASTRA_MODEL, GPT_6_ASTRA_EFFORTS);
377
390
  // No bare `sol`/`luna` aliases: those names already mean the 5.6 tiers to
378
391
  // anyone who used them before 2026-09-22, and re-pointing them would swap a
379
392
  // user's model generation without asking.
380
393
  addEffortAliases(GPT_6_SOL_MODEL, GPT_6_SOL_MODEL, GPT_6_SOL_EFFORTS);
381
394
  addEffortAliases(GPT_6_LUNA_MODEL, GPT_6_LUNA_MODEL, GPT_6_LUNA_EFFORTS);
395
+ addEffortAliases(GPT_6_1_SOL_MODEL, GPT_6_1_SOL_MODEL, GPT_6_1_SOL_EFFORTS);
396
+ addEffortAliases(GPT_6_1_FLAGSHIP_ALIAS, GPT_6_1_SOL_MODEL, GPT_6_1_SOL_EFFORTS);
382
397
  }
383
398
  function addDaybreakAliases() {
384
399
  addEffortAliases(DAYBREAK_BLUE_MODEL, DAYBREAK_BLUE_MODEL, DAYBREAK_EFFORTS);
@@ -387,14 +402,12 @@ function addDaybreakAliases() {
387
402
  addEffortAliases("daybreak-red", DAYBREAK_RED_MODEL, DAYBREAK_EFFORTS);
388
403
  }
389
404
  function addGeneralAliases() {
390
- addReasoningAliases(GPT_5_5_CANONICAL_MODEL, GPT_5_5_CANONICAL_MODEL);
391
- addReasoningAliases(GPT_5_5_RELEASE_MODEL, GPT_5_5_CANONICAL_MODEL);
392
- addReasoningAliases(GPT_5_5_RELEASE_COMPAT_MODEL, GPT_5_5_CANONICAL_MODEL);
393
- addReasoningAliases(GPT_5_5_PRO_CANONICAL_MODEL, GPT_5_5_PRO_CANONICAL_MODEL);
394
- addReasoningAliases(GPT_5_5_PRO_RELEASE_MODEL, GPT_5_5_PRO_CANONICAL_MODEL);
395
- addReasoningAliases(GPT_5_5_PRO_RELEASE_COMPAT_MODEL, GPT_5_5_PRO_CANONICAL_MODEL);
396
- addReasoningAliases("gpt-5-pro", GPT_5_5_PRO_CANONICAL_MODEL);
397
- addReasoningAliases("gpt-5", DEFAULT_MODEL);
405
+ // `gpt-5` and `gpt-5-pro` are the last un-versioned ids upstream published.
406
+ // With 5.5 retired, "the gpt-5 line" is Sol 5.6 and "the pro tier" is the
407
+ // Astra flagship that replaced the API-only `gpt-5.5-pro`. The dated and
408
+ // pro-suffixed forms of 5.5 itself come from the retired table below.
409
+ addReasoningAliases("gpt-5-pro", GPT_6_ASTRA_MODEL);
410
+ addReasoningAliases("gpt-5", GPT_5_6_SOL_MODEL);
398
411
  }
399
412
  /**
400
413
  * Retired general ids, each kept as an alias of the replacement OpenAI names
@@ -405,12 +418,27 @@ function addGeneralAliases() {
405
418
  * efforts the replacement does not accept are coerced as for any request.
406
419
  */
407
420
  const RETIRED_GENERAL_MODEL_REPLACEMENTS = {
421
+ // `gpt-6-astra-aeon` never appeared in the bundled Codex catalog or the
422
+ // public model docs — it existed only as a Statsig-flag leak — so the id
423
+ // is dead and goes to the flagship it was a long-horizon variant of.
424
+ "gpt-6-astra-aeon": GPT_6_ASTRA_MODEL,
425
+ // `gpt-5.5` leaves ChatGPT/Codex OAuth on 2026-10-14; the bundled catalog
426
+ // already relabels it "legacy" and names GPT-6 Sol as the migration
427
+ // target. `gpt-5.5-pro` left the bundled catalog earlier — it is API-only
428
+ // now, a surface this OAuth wrapper cannot reach — so its ids go to the
429
+ // frontier flagship. The dated snapshot ids retire with them.
430
+ "gpt-5.5": GPT_6_SOL_MODEL,
431
+ "gpt-5.5-2026-04-23": GPT_6_SOL_MODEL,
432
+ "gpt-5.5-20260423": GPT_6_SOL_MODEL,
433
+ "gpt-5.5-pro": GPT_6_ASTRA_MODEL,
434
+ "gpt-5.5-pro-2026-04-23": GPT_6_ASTRA_MODEL,
435
+ "gpt-5.5-pro-20260423": GPT_6_ASTRA_MODEL,
408
436
  "gpt-5.4": GPT_6_SOL_MODEL,
409
437
  "gpt-5.4-mini": GPT_6_LUNA_MODEL,
410
438
  "gpt-5.4-nano": GPT_6_LUNA_MODEL,
411
- "gpt-5.4-pro": GPT_5_5_PRO_CANONICAL_MODEL,
439
+ "gpt-5.4-pro": GPT_6_ASTRA_MODEL,
412
440
  "gpt-5.2": GPT_5_6_SOL_MODEL,
413
- "gpt-5.2-pro": GPT_5_5_PRO_CANONICAL_MODEL,
441
+ "gpt-5.2-pro": GPT_6_ASTRA_MODEL,
414
442
  "gpt-5.1": GPT_5_6_SOL_MODEL,
415
443
  "gpt-5-mini": GPT_5_6_TERRA_MODEL,
416
444
  "gpt-5-nano": GPT_5_6_LUNA_MODEL,
@@ -534,11 +562,17 @@ function resolveGpt6CatalogModel(modelId) {
534
562
  // never forms and it used to fall through to GPT-5.5 while still passing
535
563
  // capability-policy's catalog gate. Gate and resolver have to agree on the
536
564
  // same id or the policy store keys state a request never reads.
537
- const isGpt6 = versionToken === "6" || tokens.includes("gpt6");
565
+ const gpt6Index = tokens.indexOf("gpt6");
566
+ const isGpt6 = versionToken === "6" || gpt6Index !== -1;
567
+ // A 6.1 minor shows up as the token after `6` (`gpt-6.1-sol`) or after
568
+ // `gpt6` (`gpt6.1-sol`); both forms have to land on the 6.1 generation,
569
+ // not on the 6.0 tier the trailing `sol`/`luna` tokens name.
570
+ const isGpt61 = (isGpt6 && gptIndex !== -1 && tokens[gptIndex + 2] === "1") ||
571
+ (gpt6Index !== -1 && tokens[gpt6Index + 1] === "1");
538
572
  // A bare `astra` token counts too. OpenAI's own launch material and every
539
573
  // picker label say "Astra" without the `gpt-6` prefix, so `Astra Pro` and
540
574
  // `astra-fast` reach this resolver with no version tokens at all; without
541
- // this clause they miss every branch and land on GPT-5.5.
575
+ // this clause they miss every branch and land on the default.
542
576
  //
543
577
  // It is anchored, not a free-floating substring: an id that names a
544
578
  // DIFFERENT GPT major version does not get claimed for the frontier model
@@ -551,10 +585,18 @@ function resolveGpt6CatalogModel(modelId) {
551
585
  if ((!isGpt6 && !isAstra) || tokens.includes("codex")) {
552
586
  return undefined;
553
587
  }
588
+ // `aeon` was the leaked long-horizon Astra variant; retired, its ids run on
589
+ // the flagship. `astra` keeps its own canonical id because Astra is a
590
+ // behaviourally different model, not a rename of the Sol workhorse.
554
591
  if (tokens.includes("aeon"))
555
- return GPT_6_ASTRA_AEON_MODEL;
592
+ return GPT_6_ASTRA_MODEL;
556
593
  if (isAstra)
557
594
  return GPT_6_ASTRA_MODEL;
595
+ // Every unrecognised 6.1 id resolves to the generation's only tier, Sol —
596
+ // the same in-minor flagship rule the 5.6 resolver applies, kept behind
597
+ // `astra` so `gpt-6.1-astra` names the frontier model it actually means.
598
+ if (isGpt61)
599
+ return GPT_6_1_SOL_MODEL;
558
600
  // Before Sol and Luna existed every non-Astra GPT-6 id fell to the line
559
601
  // below, so `gpt-6-luna` silently ran Astra at 100x Luna's price. `terra`
560
602
  // goes to Sol because there is no GPT-6 Terra and upstream migrates
@@ -19,7 +19,7 @@ export { isHostSystemPrompt, filterHostSystemPromptsWithCachedPrompt, } from "./
19
19
  * diagnostics all agree on the same effective model.
20
20
  *
21
21
  * @param model - Original model name (e.g., "gpt-5-codex-low", "openai/gpt-5.3-codex")
22
- * @returns Normalized model name (e.g., "gpt-5.3-codex", "gpt-5.5", "gpt-5.4")
22
+ * @returns Normalized model name (e.g., "gpt-5.6-sol", "gpt-6.1-sol", "gpt-6-astra")
23
23
  */
24
24
  export declare function normalizeModel(model: string | undefined): string;
25
25
  /**
@@ -15,7 +15,7 @@ export { isHostSystemPrompt, filterHostSystemPromptsWithCachedPrompt, } from "./
15
15
  * diagnostics all agree on the same effective model.
16
16
  *
17
17
  * @param model - Original model name (e.g., "gpt-5-codex-low", "openai/gpt-5.3-codex")
18
- * @returns Normalized model name (e.g., "gpt-5.3-codex", "gpt-5.5", "gpt-5.4")
18
+ * @returns Normalized model name (e.g., "gpt-5.6-sol", "gpt-6.1-sol", "gpt-6-astra")
19
19
  */
20
20
  export function normalizeModel(model) {
21
21
  return resolveNormalizedModel(model);
@@ -23,8 +23,8 @@ declare const schema: z.ZodObject<{
23
23
  model: z.ZodString;
24
24
  checkedAt: z.ZodOptional<z.ZodNumber>;
25
25
  probes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
26
- verified: "verified";
27
26
  unsupported: "unsupported";
27
+ verified: "verified";
28
28
  unverified: "unverified";
29
29
  downgraded: "downgraded";
30
30
  }>>>;
@@ -51,8 +51,8 @@ declare const schema: z.ZodObject<{
51
51
  model: z.ZodString;
52
52
  checkedAt: z.ZodOptional<z.ZodNumber>;
53
53
  probes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
54
- verified: "verified";
55
54
  unsupported: "unsupported";
55
+ verified: "verified";
56
56
  unverified: "unverified";
57
57
  downgraded: "downgraded";
58
58
  }>>>;
@@ -94,7 +94,7 @@ export declare const UI_COPY: {
94
94
  readonly experimentalHelpMenu: "Enter Select | 1 Sync | 2 Backup | 3 Guard | 4 Budget | [ - Down | ] + Up | S Save | Q Back";
95
95
  readonly experimentalHelpPreview: "Enter Select | A Apply | Q Back";
96
96
  readonly experimentalHelpStatus: "Enter Select | Q Back";
97
- readonly experimentalSync: "Sync Accounts to oc-chatgpt-multi-auth";
97
+ readonly experimentalSync: "Sync Accounts to oc-codex-multi-auth";
98
98
  readonly experimentalApplySync: "Apply Sync";
99
99
  readonly experimentalBackup: "Save Pool Backup";
100
100
  readonly experimentalBackupPrompt: "Backup file name (.json): ";
@@ -95,7 +95,7 @@ export const UI_COPY = {
95
95
  experimentalHelpMenu: "Enter Select | 1 Sync | 2 Backup | 3 Guard | 4 Budget | [ - Down | ] + Up | S Save | Q Back",
96
96
  experimentalHelpPreview: "Enter Select | A Apply | Q Back",
97
97
  experimentalHelpStatus: "Enter Select | Q Back",
98
- experimentalSync: "Sync Accounts to oc-chatgpt-multi-auth",
98
+ experimentalSync: "Sync Accounts to oc-codex-multi-auth",
99
99
  experimentalApplySync: "Apply Sync",
100
100
  experimentalBackup: "Save Pool Backup",
101
101
  experimentalBackupPrompt: "Backup file name (.json): ",
@@ -51,7 +51,7 @@ export declare const SHORT_CONTEXT_MAX_INPUT_TOKENS = 272000;
51
51
  * `test/usage-pricing-coverage.test.ts` fails if a NEW routable model appears
52
52
  * in neither list.
53
53
  */
54
- export declare const UNPRICED_ROUTABLE_MODELS: readonly ["gpt-6-astra-aeon", "gpt-daybreak-blue-latest", "gpt-daybreak-red-latest", "gpt-5.5-pro"];
54
+ export declare const UNPRICED_ROUTABLE_MODELS: readonly ["gpt-daybreak-blue-latest", "gpt-daybreak-red-latest"];
55
55
  export declare function getUsageModelPricing(model: string | null | undefined): UsageModelPricing | null;
56
56
  export declare function estimateUsageCostUsd(model: string | null | undefined, tokens: UsageTokenCounts): number | null;
57
57
  export declare function listUsageModelPricing(): Record<string, UsageModelPricing>;
@@ -1,4 +1,4 @@
1
- import { RETIRED_MODEL_REPLACEMENTS } from "../request/helpers/model-map.js";
1
+ import { getNormalizedModel, RETIRED_MODEL_REPLACEMENTS, } from "../request/helpers/model-map.js";
2
2
  /**
3
3
  * Largest input still billed at the short-context rate. OpenAI's GPT-6 model
4
4
  * pages say "Prompts with more than 272K input tokens are priced at 2x input
@@ -48,6 +48,37 @@ const MODEL_PRICING = {
48
48
  },
49
49
  },
50
50
  },
51
+ // GPT-6.1 Sol, published with the model on 2026-09-29: same $2 / $10 shape
52
+ // as 6 Sol but a cheaper cached-input rate ($0.10 vs $0.20) and a separate
53
+ // cache-write rate this table has no field for — cache writes bill as input
54
+ // here. Long-context (>272K input) doubles input and cache rates and
55
+ // multiplies output 1.5x; the Fast tier is the usual 2x.
56
+ "gpt-6.1-sol": {
57
+ inputUsdPerMillion: 2,
58
+ outputUsdPerMillion: 10,
59
+ cachedInputUsdPerMillion: 0.1,
60
+ reasoningUsdPerMillion: 10,
61
+ longContext: {
62
+ inputUsdPerMillion: 4,
63
+ outputUsdPerMillion: 15,
64
+ cachedInputUsdPerMillion: 0.2,
65
+ reasoningUsdPerMillion: 15,
66
+ },
67
+ serviceTiers: {
68
+ priority: {
69
+ inputUsdPerMillion: 4,
70
+ outputUsdPerMillion: 20,
71
+ cachedInputUsdPerMillion: 0.2,
72
+ reasoningUsdPerMillion: 20,
73
+ longContext: {
74
+ inputUsdPerMillion: 8,
75
+ outputUsdPerMillion: 30,
76
+ cachedInputUsdPerMillion: 0.4,
77
+ reasoningUsdPerMillion: 30,
78
+ },
79
+ },
80
+ },
81
+ },
51
82
  // GPT-6 Sol and Luna, from the OpenAI API pricing page (read 2026-09-23;
52
83
  // short- and long-context rows). Both publish a Fast tier at exactly 2x,
53
84
  // like Astra.
@@ -103,12 +134,6 @@ const MODEL_PRICING = {
103
134
  },
104
135
  },
105
136
  },
106
- "gpt-5.5": {
107
- inputUsdPerMillion: 2,
108
- outputUsdPerMillion: 12,
109
- cachedInputUsdPerMillion: 0.2,
110
- reasoningUsdPerMillion: 12,
111
- },
112
137
  "gpt-5.6-sol": {
113
138
  inputUsdPerMillion: 5,
114
139
  outputUsdPerMillion: 30,
@@ -143,16 +168,10 @@ const MODEL_PRICING = {
143
168
  * in neither list.
144
169
  */
145
170
  export const UNPRICED_ROUTABLE_MODELS = [
146
- // OpenAI published a rate for the Astra flagship at launch but not for the
147
- // long-horizon `aeon` variant, and the Daybreak cyber models are sold under
148
- // a separate controlled-access agreement with no public per-token rate.
149
- // Pricing `aeon` off the flagship would be a guess on the model whose whole
150
- // purpose is running for days, which is exactly where a wrong rate does the
151
- // most damage.
152
- "gpt-6-astra-aeon",
171
+ // The Daybreak cyber models are sold under a separate controlled-access
172
+ // agreement with no public per-token rate.
153
173
  "gpt-daybreak-blue-latest",
154
174
  "gpt-daybreak-red-latest",
155
- "gpt-5.5-pro",
156
175
  ];
157
176
  function normalizeModelName(model) {
158
177
  const trimmed = model?.trim().toLowerCase();
@@ -179,7 +198,13 @@ export function getUsageModelPricing(model) {
179
198
  // the ledger stores `costUsd` when a row is written and never re-prices it.
180
199
  const effective = !/^(api|zdr)\//.test(model ?? "") && Object.hasOwn(RETIRED_MODEL_REPLACEMENTS, normalized)
181
200
  ? RETIRED_MODEL_REPLACEMENTS[normalized]
182
- : normalized;
201
+ : // Bare aliases (`gpt-6.1`, `gpt-6`, `gpt-5.6`, `astra`) and
202
+ // effort-suffixed ids (`gpt-6.1-sol-max`) reach the ledger raw too;
203
+ // `getNormalizedModel` is the exact/alias-only resolver — NOT
204
+ // `resolveNormalizedModel`, which hands back DEFAULT_MODEL for
205
+ // anything unrecognized and would price an unknown model at the
206
+ // default's rate.
207
+ (getNormalizedModel(normalized) ?? normalized);
183
208
  if (!effective || !Object.hasOwn(MODEL_PRICING, effective)) {
184
209
  return null;
185
210
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-multi-auth",
3
- "version": "2.17.3",
3
+ "version": "2.18.0",
4
4
  "description": "Codex CLI multi-account OAuth manager with account switching, health checks, runtime rotation, diagnostics, and recovery tools for @openai/codex",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",