codex-multi-auth 2.5.0 → 2.6.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 +4 -1
- package/config/codex-legacy.json +425 -0
- package/dist/lib/auth/browser.d.ts +4 -0
- package/dist/lib/auth/browser.d.ts.map +1 -1
- package/dist/lib/auth/browser.js +73 -19
- package/dist/lib/auth/callback-guidance.d.ts +39 -0
- package/dist/lib/auth/callback-guidance.d.ts.map +1 -0
- package/dist/lib/auth/callback-guidance.js +106 -0
- package/dist/lib/auth/server.d.ts.map +1 -1
- package/dist/lib/auth/server.js +1 -0
- package/dist/lib/codex-manager/commands/best.js +2 -2
- package/dist/lib/codex-manager/commands/forecast.js +4 -4
- package/dist/lib/codex-manager/commands/report.js +4 -4
- package/dist/lib/codex-manager/help.js +2 -2
- package/dist/lib/codex-manager/login-oauth.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-oauth.js +11 -0
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts +1 -1
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts.map +1 -1
- package/dist/lib/codex-manager/quota-cache-helpers.js +2 -2
- package/dist/lib/codex-manager/repair-commands.js +4 -4
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +5 -1
- package/dist/lib/quota-probe.d.ts.map +1 -1
- package/dist/lib/quota-probe.js +5 -2
- package/dist/lib/request/helpers/model-map.d.ts +15 -1
- package/dist/lib/request/helpers/model-map.d.ts.map +1 -1
- package/dist/lib/request/helpers/model-map.js +45 -1
- package/dist/lib/runtime/quota-probe.d.ts.map +1 -1
- package/dist/lib/runtime/quota-probe.js +5 -2
- package/dist/lib/types.d.ts +6 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/wsl.d.ts +28 -0
- package/dist/lib/wsl.d.ts.map +1 -0
- package/dist/lib/wsl.js +57 -0
- package/package.json +1 -1
- package/scripts/codex.js +129 -15
package/dist/lib/wsl.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WSL (Windows Subsystem for Linux) detection.
|
|
3
|
+
*
|
|
4
|
+
* WSL reports `process.platform === "linux"`, so every platform switch in this
|
|
5
|
+
* package treats it as a native Linux host. That is wrong for anything crossing
|
|
6
|
+
* the Windows boundary: the default browser, the clipboard, and the loopback
|
|
7
|
+
* interface that receives the OAuth callback all belong to the Windows host
|
|
8
|
+
* rather than to the distro.
|
|
9
|
+
*/
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
let cachedIsWsl;
|
|
12
|
+
function detectWsl() {
|
|
13
|
+
if (process.platform !== "linux")
|
|
14
|
+
return false;
|
|
15
|
+
// Set by WSL itself; present in every interop-enabled distro shell.
|
|
16
|
+
if ((process.env.WSL_DISTRO_NAME ?? "").length > 0 ||
|
|
17
|
+
(process.env.WSL_INTEROP ?? "").length > 0) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
// Fallback for shells that strip the environment (systemd units, cron).
|
|
21
|
+
try {
|
|
22
|
+
return /microsoft|wsl/i.test(fs.readFileSync("/proc/version", "utf-8"));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Whether the current process is running inside WSL.
|
|
30
|
+
*
|
|
31
|
+
* The result is cached because it cannot change within a process lifetime.
|
|
32
|
+
*/
|
|
33
|
+
export function isWsl() {
|
|
34
|
+
if (cachedIsWsl === undefined) {
|
|
35
|
+
cachedIsWsl = detectWsl();
|
|
36
|
+
}
|
|
37
|
+
return cachedIsWsl;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The WSL distro name (for example `Debian`), when WSL exposes it.
|
|
41
|
+
*
|
|
42
|
+
* @returns The distro name, or `undefined` outside WSL or when unset.
|
|
43
|
+
*/
|
|
44
|
+
export function getWslDistroName() {
|
|
45
|
+
if (!isWsl())
|
|
46
|
+
return undefined;
|
|
47
|
+
const name = (process.env.WSL_DISTRO_NAME ?? "").trim();
|
|
48
|
+
return name.length > 0 ? name : undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Clear the memoized {@link isWsl} result.
|
|
52
|
+
*
|
|
53
|
+
* @internal Test seam — production code must not call this.
|
|
54
|
+
*/
|
|
55
|
+
export function resetWslDetectionCacheForTests() {
|
|
56
|
+
cachedIsWsl = undefined;
|
|
57
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-multi-auth",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
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",
|
package/scripts/codex.js
CHANGED
|
@@ -475,6 +475,10 @@ async function applyForcedAccountSelection(rawArgs, env = process.env) {
|
|
|
475
475
|
|
|
476
476
|
function resolveModelFamilyForStatus(model) {
|
|
477
477
|
const normalized = typeof model === "string" ? model.trim().toLowerCase() : "";
|
|
478
|
+
// GPT-5.6 general tiers share the gpt-5.2 prompt family (see
|
|
479
|
+
// lib/request/helpers/model-map.ts MODEL_PROFILES). Check before the generic
|
|
480
|
+
// gpt-5 catch-all, which would otherwise mis-bucket them as codex.
|
|
481
|
+
if (normalized.startsWith("gpt-5.6")) return "gpt-5.2";
|
|
478
482
|
if (normalized.startsWith("gpt-5.2")) return "gpt-5.2";
|
|
479
483
|
if (normalized.startsWith("gpt-5.1")) return "gpt-5.1";
|
|
480
484
|
if (normalized.includes("codex-max")) return "codex-max";
|
|
@@ -1160,7 +1164,7 @@ function canonicalizeRequestedModelName(model) {
|
|
|
1160
1164
|
return "";
|
|
1161
1165
|
}
|
|
1162
1166
|
|
|
1163
|
-
return stripped.replace(/-(none|minimal|low|medium|high|xhigh)$/i, "");
|
|
1167
|
+
return stripped.replace(/-(none|minimal|low|medium|high|xhigh|max|ultra)$/i, "");
|
|
1164
1168
|
}
|
|
1165
1169
|
|
|
1166
1170
|
function canonicalizeUnsupportedModelKey(model) {
|
|
@@ -1169,7 +1173,7 @@ function canonicalizeUnsupportedModelKey(model) {
|
|
|
1169
1173
|
if (!stripped) {
|
|
1170
1174
|
return "";
|
|
1171
1175
|
}
|
|
1172
|
-
return stripped.replace(/-(none|minimal|low|medium|high|xhigh)$/i, "");
|
|
1176
|
+
return stripped.replace(/-(none|minimal|low|medium|high|xhigh|max|ultra)$/i, "");
|
|
1173
1177
|
}
|
|
1174
1178
|
|
|
1175
1179
|
function extractUnsupportedModelFromOutput(output) {
|
|
@@ -1757,6 +1761,9 @@ function hasCliAuthCredentialsStoreOverride(args) {
|
|
|
1757
1761
|
// This wrapper runs before the TypeScript build, so it cannot import that source.
|
|
1758
1762
|
const SUPPORTED_REASONING_EFFORTS_BY_MODEL = {
|
|
1759
1763
|
[CURRENT_CODEX_MODEL]: ["low", "medium", "high", "xhigh"],
|
|
1764
|
+
"gpt-5.6-sol": ["low", "medium", "high", "xhigh", "max", "ultra"],
|
|
1765
|
+
"gpt-5.6-terra": ["low", "medium", "high", "xhigh", "max", "ultra"],
|
|
1766
|
+
"gpt-5.6-luna": ["low", "medium", "high", "xhigh", "max"],
|
|
1760
1767
|
"gpt-5.5": ["none", "low", "medium", "high", "xhigh"],
|
|
1761
1768
|
"gpt-5.5-pro": ["medium", "high", "xhigh"],
|
|
1762
1769
|
"gpt-5.4": ["none", "low", "medium", "high", "xhigh"],
|
|
@@ -1777,9 +1784,26 @@ const REASONING_FALLBACKS = {
|
|
|
1777
1784
|
medium: ["medium", "low", "high", "minimal", "none", "xhigh"],
|
|
1778
1785
|
high: ["high", "medium", "xhigh", "low", "minimal", "none"],
|
|
1779
1786
|
xhigh: ["xhigh", "high", "medium", "low", "minimal", "none"],
|
|
1787
|
+
// `max` and `ultra` arrived with GPT-5.6. Step down one rung at a time so a
|
|
1788
|
+
// request against a pre-5.6 model lands on that model's strongest tier.
|
|
1789
|
+
max: ["max", "xhigh", "high", "medium", "low", "minimal", "none"],
|
|
1790
|
+
ultra: ["ultra", "max", "xhigh", "high", "medium", "low", "minimal", "none"],
|
|
1780
1791
|
};
|
|
1781
1792
|
|
|
1782
1793
|
const KNOWN_REASONING_EFFORTS = new Set(Object.keys(REASONING_FALLBACKS));
|
|
1794
|
+
|
|
1795
|
+
// Effort suffixes generated as model aliases (e.g. `gpt-5.5-high`). This is the
|
|
1796
|
+
// pre-5.6 set only: `max`/`ultra` are NOT auto-aliased onto general models,
|
|
1797
|
+
// matching lib/request/helpers/model-map.ts `REASONING_VARIANTS`. GPT-5.6 tiers
|
|
1798
|
+
// register their own effort aliases explicitly via `addRequestedModelEffortAliases`.
|
|
1799
|
+
const REASONING_ALIAS_VARIANTS = [
|
|
1800
|
+
"none",
|
|
1801
|
+
"minimal",
|
|
1802
|
+
"low",
|
|
1803
|
+
"medium",
|
|
1804
|
+
"high",
|
|
1805
|
+
"xhigh",
|
|
1806
|
+
];
|
|
1783
1807
|
const REQUESTED_MODEL_ALIASES = new Map();
|
|
1784
1808
|
const DEFAULT_GENERAL_GPT5_MODEL = "gpt-5.5";
|
|
1785
1809
|
const GPT_5_5_CANONICAL_MODEL = "gpt-5.5";
|
|
@@ -1788,6 +1812,14 @@ const GPT_5_5_RELEASE_MODEL = "gpt-5.5-2026-04-23";
|
|
|
1788
1812
|
const GPT_5_5_PRO_RELEASE_MODEL = "gpt-5.5-pro-2026-04-23";
|
|
1789
1813
|
const GPT_5_5_RELEASE_COMPAT_MODEL = "gpt-5.5-20260423";
|
|
1790
1814
|
const GPT_5_5_PRO_RELEASE_COMPAT_MODEL = "gpt-5.5-pro-20260423";
|
|
1815
|
+
// GPT-5.6 tiers. Sol and Terra expose `ultra`; Luna stops at `max`. No tier
|
|
1816
|
+
// accepts `none`/`minimal`. Bare `gpt-5.6` aliases to the flagship (Sol).
|
|
1817
|
+
const GPT_5_6_SOL_MODEL = "gpt-5.6-sol";
|
|
1818
|
+
const GPT_5_6_TERRA_MODEL = "gpt-5.6-terra";
|
|
1819
|
+
const GPT_5_6_LUNA_MODEL = "gpt-5.6-luna";
|
|
1820
|
+
const GPT_5_6_FLAGSHIP_ALIAS = "gpt-5.6";
|
|
1821
|
+
const GPT_5_6_SOL_TERRA_EFFORTS = ["low", "medium", "high", "xhigh", "max", "ultra"];
|
|
1822
|
+
const GPT_5_6_LUNA_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
1791
1823
|
const GENERAL_GPT5_VERSION_CATALOG = {
|
|
1792
1824
|
1: {
|
|
1793
1825
|
base: "gpt-5.1",
|
|
@@ -1823,7 +1855,17 @@ function addRequestedModelAlias(alias, normalizedModel) {
|
|
|
1823
1855
|
|
|
1824
1856
|
function addRequestedModelReasoningAliases(alias, normalizedModel) {
|
|
1825
1857
|
addRequestedModelAlias(alias, normalizedModel);
|
|
1826
|
-
for (const effort of
|
|
1858
|
+
for (const effort of REASONING_ALIAS_VARIANTS) {
|
|
1859
|
+
addRequestedModelAlias(`${alias}-${effort}`, normalizedModel);
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
// Register a model plus one alias per effort it actually supports. Unlike
|
|
1864
|
+
// `addRequestedModelReasoningAliases`, this does not assume the pre-5.6 variant
|
|
1865
|
+
// list: GPT-5.6 rejects `none`/`minimal` and only Sol/Terra accept `ultra`.
|
|
1866
|
+
function addRequestedModelEffortAliases(alias, normalizedModel, efforts) {
|
|
1867
|
+
addRequestedModelAlias(alias, normalizedModel);
|
|
1868
|
+
for (const effort of efforts) {
|
|
1827
1869
|
addRequestedModelAlias(`${alias}-${effort}`, normalizedModel);
|
|
1828
1870
|
}
|
|
1829
1871
|
}
|
|
@@ -1961,6 +2003,26 @@ function seedRequestedModelAliases() {
|
|
|
1961
2003
|
addRequestedModelReasoningAliases("gpt-5-nano", "gpt-5-nano");
|
|
1962
2004
|
addRequestedModelReasoningAliases("gpt-5.1-chat-latest", "gpt-5.1");
|
|
1963
2005
|
addRequestedModelReasoningAliases("gpt-5-chat-latest", DEFAULT_GENERAL_GPT5_MODEL);
|
|
2006
|
+
addRequestedModelEffortAliases(
|
|
2007
|
+
GPT_5_6_SOL_MODEL,
|
|
2008
|
+
GPT_5_6_SOL_MODEL,
|
|
2009
|
+
GPT_5_6_SOL_TERRA_EFFORTS,
|
|
2010
|
+
);
|
|
2011
|
+
addRequestedModelEffortAliases(
|
|
2012
|
+
GPT_5_6_TERRA_MODEL,
|
|
2013
|
+
GPT_5_6_TERRA_MODEL,
|
|
2014
|
+
GPT_5_6_SOL_TERRA_EFFORTS,
|
|
2015
|
+
);
|
|
2016
|
+
addRequestedModelEffortAliases(
|
|
2017
|
+
GPT_5_6_LUNA_MODEL,
|
|
2018
|
+
GPT_5_6_LUNA_MODEL,
|
|
2019
|
+
GPT_5_6_LUNA_EFFORTS,
|
|
2020
|
+
);
|
|
2021
|
+
addRequestedModelEffortAliases(
|
|
2022
|
+
GPT_5_6_FLAGSHIP_ALIAS,
|
|
2023
|
+
GPT_5_6_SOL_MODEL,
|
|
2024
|
+
GPT_5_6_SOL_TERRA_EFFORTS,
|
|
2025
|
+
);
|
|
1964
2026
|
addRequestedModelReasoningAliases(CURRENT_CODEX_MODEL, CURRENT_CODEX_MODEL);
|
|
1965
2027
|
addRequestedModelReasoningAliases("gpt-5.3-codex-spark", CURRENT_CODEX_MODEL);
|
|
1966
2028
|
addRequestedModelReasoningAliases(LEGACY_CODEX_MODEL, CURRENT_CODEX_MODEL);
|
|
@@ -2052,6 +2114,25 @@ function resolveCodexRequestedModel(normalized) {
|
|
|
2052
2114
|
return "";
|
|
2053
2115
|
}
|
|
2054
2116
|
|
|
2117
|
+
// Resolve GPT-5.6 identifiers, including ones that are not exact aliases (e.g. a
|
|
2118
|
+
// future `gpt-5.6-terra-fast`). Without this the general GPT-5 resolver sees
|
|
2119
|
+
// minor `6`, finds no catalog entry, and silently falls back to 5.5. Unknown
|
|
2120
|
+
// tiers resolve to Sol, matching OpenAI's bare `gpt-5.6` alias.
|
|
2121
|
+
function resolveGpt56RequestedModel(stripped) {
|
|
2122
|
+
const tokens = tokenizeRequestedModel(stripped);
|
|
2123
|
+
const gptIndex = tokens.indexOf("gpt");
|
|
2124
|
+
const isGpt56 =
|
|
2125
|
+
gptIndex !== -1 &&
|
|
2126
|
+
tokens[gptIndex + 1] === "5" &&
|
|
2127
|
+
tokens[gptIndex + 2] === "6";
|
|
2128
|
+
if (!isGpt56 || tokens.includes("codex")) {
|
|
2129
|
+
return "";
|
|
2130
|
+
}
|
|
2131
|
+
if (tokens.includes("terra")) return GPT_5_6_TERRA_MODEL;
|
|
2132
|
+
if (tokens.includes("luna")) return GPT_5_6_LUNA_MODEL;
|
|
2133
|
+
return GPT_5_6_SOL_MODEL;
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2055
2136
|
function resolveGeneralGpt5RequestedModel(stripped) {
|
|
2056
2137
|
const tokens = tokenizeRequestedModel(stripped);
|
|
2057
2138
|
const gptIndex = tokens.indexOf("gpt");
|
|
@@ -2100,6 +2181,11 @@ function normalizeRequestedModel(model) {
|
|
|
2100
2181
|
return codexModel;
|
|
2101
2182
|
}
|
|
2102
2183
|
|
|
2184
|
+
const gpt56Model = resolveGpt56RequestedModel(stripped);
|
|
2185
|
+
if (gpt56Model) {
|
|
2186
|
+
return gpt56Model;
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2103
2189
|
const generalModel = resolveGeneralGpt5RequestedModel(stripped);
|
|
2104
2190
|
if (generalModel) {
|
|
2105
2191
|
return generalModel;
|
|
@@ -2108,16 +2194,7 @@ function normalizeRequestedModel(model) {
|
|
|
2108
2194
|
return "";
|
|
2109
2195
|
}
|
|
2110
2196
|
|
|
2111
|
-
function
|
|
2112
|
-
if (typeof effort !== "string") return effort;
|
|
2113
|
-
const normalizedEffort = effort.trim().toLowerCase();
|
|
2114
|
-
if (!KNOWN_REASONING_EFFORTS.has(normalizedEffort)) {
|
|
2115
|
-
return effort;
|
|
2116
|
-
}
|
|
2117
|
-
|
|
2118
|
-
const normalizedModel = normalizeRequestedModel(model);
|
|
2119
|
-
const supportedEfforts =
|
|
2120
|
-
SUPPORTED_REASONING_EFFORTS_BY_MODEL[normalizedModel] ?? null;
|
|
2197
|
+
function resolveSupportedReasoningEffort(normalizedEffort, supportedEfforts) {
|
|
2121
2198
|
if (!supportedEfforts || supportedEfforts.includes(normalizedEffort)) {
|
|
2122
2199
|
return normalizedEffort;
|
|
2123
2200
|
}
|
|
@@ -2132,6 +2209,27 @@ function coerceReasoningEffortForModel(model, effort) {
|
|
|
2132
2209
|
return normalizedEffort;
|
|
2133
2210
|
}
|
|
2134
2211
|
|
|
2212
|
+
function coerceReasoningEffortForModel(model, effort) {
|
|
2213
|
+
if (typeof effort !== "string") return effort;
|
|
2214
|
+
const normalizedEffort = effort.trim().toLowerCase();
|
|
2215
|
+
if (!KNOWN_REASONING_EFFORTS.has(normalizedEffort)) {
|
|
2216
|
+
return effort;
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
const normalizedModel = normalizeRequestedModel(model);
|
|
2220
|
+
const supportedEfforts =
|
|
2221
|
+
SUPPORTED_REASONING_EFFORTS_BY_MODEL[normalizedModel] ?? null;
|
|
2222
|
+
const resolved = resolveSupportedReasoningEffort(
|
|
2223
|
+
normalizedEffort,
|
|
2224
|
+
supportedEfforts,
|
|
2225
|
+
);
|
|
2226
|
+
|
|
2227
|
+
// `ultra` is a client-side tier: Codex rewrites it to `max` before the
|
|
2228
|
+
// request leaves the client, so it must never reach the wire. Mirror
|
|
2229
|
+
// lib/request/helpers/model-map.ts / request-transformer's getReasoningConfig.
|
|
2230
|
+
return resolved === "ultra" ? "max" : resolved;
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2135
2233
|
function extractRequestedModel(args) {
|
|
2136
2234
|
for (let i = 0; i < args.length; i += 1) {
|
|
2137
2235
|
const arg = args[i];
|
|
@@ -4959,5 +5057,21 @@ async function main() {
|
|
|
4959
5057
|
}
|
|
4960
5058
|
}
|
|
4961
5059
|
|
|
4962
|
-
|
|
4963
|
-
|
|
5060
|
+
// Model-resolution internals, exported for unit tests. Kept in sync with
|
|
5061
|
+
// lib/request/helpers/model-map.ts (see test/codex-model-resolution.test.ts,
|
|
5062
|
+
// which asserts wrapper<->lib parity).
|
|
5063
|
+
export {
|
|
5064
|
+
normalizeRequestedModel,
|
|
5065
|
+
coerceReasoningEffortForModel,
|
|
5066
|
+
resolveModelFamilyForStatus,
|
|
5067
|
+
canonicalizeRequestedModelName,
|
|
5068
|
+
};
|
|
5069
|
+
|
|
5070
|
+
// Run the wrapper only when actually launched (as the `codex-multi-auth-codex`
|
|
5071
|
+
// bin). Tests set CODEX_MULTI_AUTH_WRAPPER_IMPORT_ONLY to import the module for
|
|
5072
|
+
// its exported helpers without forwarding to the real Codex CLI. The flag is
|
|
5073
|
+
// never set in production, so bin launches are unaffected.
|
|
5074
|
+
if (!process.env.CODEX_MULTI_AUTH_WRAPPER_IMPORT_ONLY) {
|
|
5075
|
+
const exitCode = await main();
|
|
5076
|
+
process.exitCode = normalizeExitCode(exitCode);
|
|
5077
|
+
}
|