@bman654/clodex 2.10.0 → 2.11.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.
- package/README.md +5 -4
- package/dist/cli.js +73 -18
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -241,10 +241,11 @@ Manage favorite models (max 20) and short aliases. Favorites feed the endpoint-m
|
|
|
241
241
|
|
|
242
242
|
#### Context stops and the pricing boundary
|
|
243
243
|
|
|
244
|
-
A context window is a cost dial as much as a capacity number. OpenAI prices GPT-5.
|
|
245
|
-
prompts above **272,000 input tokens at 2x input and 1.5x output for the
|
|
246
|
-
request**, which is why the Codex catalog reports a 272,000 window rather than
|
|
247
|
-
model's ceiling.
|
|
244
|
+
A context window is a cost dial as much as a capacity number. OpenAI prices GPT-5.5
|
|
245
|
+
and later prompts above **272,000 input tokens at 2x input and 1.5x output for the
|
|
246
|
+
full request**, which is why the Codex catalog reports a 272,000 window rather than
|
|
247
|
+
the model's ceiling. Newer families inherit the same boundary, so a model released
|
|
248
|
+
after this was written is covered without a clodex update. Clodex follows that: the default `standard` stop stays under the
|
|
248
249
|
line, and a larger window is something you ask for.
|
|
249
250
|
|
|
250
251
|
```sh
|
package/dist/cli.js
CHANGED
|
@@ -382,7 +382,7 @@ import { join } from "path";
|
|
|
382
382
|
// package.json
|
|
383
383
|
var package_default = {
|
|
384
384
|
name: "@bman654/clodex",
|
|
385
|
-
version: "2.
|
|
385
|
+
version: "2.11.0",
|
|
386
386
|
publishConfig: {
|
|
387
387
|
access: "public"
|
|
388
388
|
},
|
|
@@ -469,7 +469,7 @@ var package_default = {
|
|
|
469
469
|
|
|
470
470
|
// src/constants.ts
|
|
471
471
|
var CODEX_RESPONSES_LITE_WS_URL = "wss://chatgpt.com/backend-api/codex/responses";
|
|
472
|
-
var CODEX_RESPONSES_LITE_VERSION = "0.
|
|
472
|
+
var CODEX_RESPONSES_LITE_VERSION = "0.153.3";
|
|
473
473
|
var CODEX_RESPONSES_WEBSOCKETS_BETA = "responses_websockets=2026-02-06";
|
|
474
474
|
var TEST_TIMEOUT_MS = 1e4;
|
|
475
475
|
var CONFLICTING_ENV_VARS = [
|
|
@@ -5873,6 +5873,18 @@ var CHATGPT_CODEX_UNSUPPORTED_MODELS = /* @__PURE__ */ new Set([
|
|
|
5873
5873
|
// confirmed: rejected by chatgpt.com/backend-api/codex
|
|
5874
5874
|
]);
|
|
5875
5875
|
var OPENAI_OAUTH_MODEL_SEEDS = [
|
|
5876
|
+
// GPT-6 family. The window and ceiling are what the live Codex catalog returned on
|
|
5877
|
+
// 2026-09-04 and are deliberately NOT the published API numbers: the model card
|
|
5878
|
+
// lists a 1,050,000 context window, but the Codex client is served a smaller one,
|
|
5879
|
+
// and this path is Codex-only. Output limit and the pricing band come from the
|
|
5880
|
+
// card (https://developers.openai.com/api/docs/models/gpt-6-astra), which states
|
|
5881
|
+
// "Prompts with more than 272K input tokens are priced at 2x input and cache rates
|
|
5882
|
+
// and 1.5x output for the full request" — the same boundary the GPT-5.6 family has.
|
|
5883
|
+
{ id: "gpt-6-astra", name: "GPT-6 Astra", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true, useResponsesLite: true, preferWebSockets: true },
|
|
5884
|
+
// "An alias for our flagship general-purpose models, with safeguards calibrated
|
|
5885
|
+
// for defensive cybersecurity work" — access is gated on a separate opt-in
|
|
5886
|
+
// program, so most installs will never see this id in their catalog.
|
|
5887
|
+
{ id: "gpt-daybreak-blue-latest", name: "GPT Daybreak Blue", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true, useResponsesLite: true, preferWebSockets: true },
|
|
5876
5888
|
// GPT-5.6 family (Sol / Terra / Luna)
|
|
5877
5889
|
{ id: "gpt-5.6-sol", name: "GPT-5.6 Sol", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true },
|
|
5878
5890
|
{ id: "gpt-5.6-terra", name: "GPT-5.6 Terra", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true },
|
|
@@ -5891,9 +5903,17 @@ var OPENAI_OAUTH_MODEL_SEEDS = [
|
|
|
5891
5903
|
{ id: "o1", name: "o1", reasoning: true },
|
|
5892
5904
|
{ id: "o1-mini", name: "o1 Mini", reasoning: true }
|
|
5893
5905
|
];
|
|
5894
|
-
|
|
5906
|
+
function hasPricingBoundary(id) {
|
|
5907
|
+
const version = /^gpt-(\d+)(?:\.(\d+))?(?:-|$)/i.exec(id);
|
|
5908
|
+
if (version) {
|
|
5909
|
+
const major = Number(version[1]);
|
|
5910
|
+
const minor = version[2] ? Number(version[2]) : 0;
|
|
5911
|
+
if (major > 5 || major === 5 && minor >= 5) return true;
|
|
5912
|
+
}
|
|
5913
|
+
return /^gpt-daybreak(?:-|$)/i.test(id);
|
|
5914
|
+
}
|
|
5895
5915
|
function openAiPricingMetadata(id) {
|
|
5896
|
-
if (!
|
|
5916
|
+
if (!hasPricingBoundary(id)) return {};
|
|
5897
5917
|
return {
|
|
5898
5918
|
pricingBoundary: GPT_5_6_PRICING_BOUNDARY,
|
|
5899
5919
|
pricingBoundaryNote: GPT_5_6_PRICING_NOTE
|
|
@@ -5910,7 +5930,8 @@ function applyOAuthSeedContextMetadata(models) {
|
|
|
5910
5930
|
effectiveContextPercent: model.effectiveContextPercent ?? seed?.effectiveContextPercent ?? DEFAULT_EFFECTIVE_CONTEXT_PERCENT,
|
|
5911
5931
|
pricingBoundary: model.pricingBoundary ?? seed?.pricingBoundary ?? pricing.pricingBoundary,
|
|
5912
5932
|
pricingBoundaryNote: model.pricingBoundaryNote ?? seed?.pricingBoundaryNote ?? pricing.pricingBoundaryNote,
|
|
5913
|
-
maxOutputTokens: model.maxOutputTokens ?? seed?.maxOutputTokens
|
|
5933
|
+
maxOutputTokens: model.maxOutputTokens ?? seed?.maxOutputTokens,
|
|
5934
|
+
reasoning: seed?.reasoning ?? model.reasoning
|
|
5914
5935
|
};
|
|
5915
5936
|
});
|
|
5916
5937
|
}
|
|
@@ -10253,7 +10274,7 @@ async function createLanguageModel(spec) {
|
|
|
10253
10274
|
}
|
|
10254
10275
|
var ANTHROPIC_EFFORT_LEVELS = ["low", "medium", "high"];
|
|
10255
10276
|
var OPENAI_EFFORT_LEVELS = ["low", "medium", "high", "xhigh"];
|
|
10256
|
-
var
|
|
10277
|
+
var CODEX_EXTENDED_EFFORT_LEVELS = ["none", "low", "medium", "high", "xhigh", "max"];
|
|
10257
10278
|
var GEMINI_EFFORT_LEVELS = ["low", "medium", "high"];
|
|
10258
10279
|
var MISTRAL_EFFORT_LEVELS = ["high", "off"];
|
|
10259
10280
|
var XAI_EFFORT_LEVELS = ["none", "low", "medium", "high"];
|
|
@@ -10417,14 +10438,32 @@ function mapCodexEffortToAnthropic(effort) {
|
|
|
10417
10438
|
return void 0;
|
|
10418
10439
|
}
|
|
10419
10440
|
}
|
|
10420
|
-
function
|
|
10421
|
-
return
|
|
10441
|
+
function isCodexReasoningFamily(modelId) {
|
|
10442
|
+
return !isChatVariant(modelId) && supportsExtendedCodexEffort(modelId);
|
|
10443
|
+
}
|
|
10444
|
+
function isChatVariant(modelId) {
|
|
10445
|
+
return /-chat(?:-|$)/i.test(modelId);
|
|
10446
|
+
}
|
|
10447
|
+
function supportsExtendedCodexEffort(modelId) {
|
|
10448
|
+
const version = /^gpt-(\d+)(?:\.(\d+))?(?:-|$)/i.exec(modelId);
|
|
10449
|
+
if (version) {
|
|
10450
|
+
const major = Number(version[1]);
|
|
10451
|
+
const minor = version[2] ? Number(version[2]) : 0;
|
|
10452
|
+
if (major > 5 || major === 5 && minor >= 6) return true;
|
|
10453
|
+
}
|
|
10454
|
+
return /^gpt-daybreak(?:-|$)/i.test(modelId);
|
|
10455
|
+
}
|
|
10456
|
+
function supportsNoneEffort(modelId) {
|
|
10457
|
+
return /^gpt-5\.6(?:-|$)/i.test(modelId) || /^gpt-daybreak-blue(?:-|$)/i.test(modelId);
|
|
10422
10458
|
}
|
|
10423
10459
|
function isReasoningSummaryUnsupportedModel(modelId) {
|
|
10424
10460
|
return /codex-spark(?:-|$)/i.test(modelId);
|
|
10425
10461
|
}
|
|
10426
10462
|
function mapCodexEffortToOpenAI(effort, modelId) {
|
|
10427
|
-
if (
|
|
10463
|
+
if (effort === "none") {
|
|
10464
|
+
return modelId && supportsNoneEffort(modelId) ? "none" : void 0;
|
|
10465
|
+
}
|
|
10466
|
+
if (modelId && supportsExtendedCodexEffort(modelId) && CODEX_EXTENDED_EFFORT_LEVELS.includes(effort)) {
|
|
10428
10467
|
return effort;
|
|
10429
10468
|
}
|
|
10430
10469
|
if (effort === "xhigh") return "high";
|
|
@@ -10565,9 +10604,9 @@ function getReasoningCapabilities(npm, modelId, metadata) {
|
|
|
10565
10604
|
}
|
|
10566
10605
|
if (npm === "@ai-sdk/openai" || npm === "@ai-sdk/azure") {
|
|
10567
10606
|
const prefersResponses = modelPrefersResponsesApi(modelId);
|
|
10568
|
-
if (prefersResponses || metadata?.reasoning) {
|
|
10607
|
+
if (prefersResponses || isCodexReasoningFamily(modelId) || metadata?.reasoning) {
|
|
10569
10608
|
return {
|
|
10570
|
-
levels:
|
|
10609
|
+
levels: supportsExtendedCodexEffort(modelId) ? CODEX_EXTENDED_EFFORT_LEVELS.filter((level) => level !== "none" || supportsNoneEffort(modelId)) : [...OPENAI_EFFORT_LEVELS],
|
|
10571
10610
|
defaultLevel: "medium",
|
|
10572
10611
|
supportsSummaries: true,
|
|
10573
10612
|
mode: "controllable",
|
|
@@ -10731,10 +10770,14 @@ function effortProviderOptions(npm, effort, modelId, metadata) {
|
|
|
10731
10770
|
return mapped ? { openrouter: { reasoning: { effort: mapped, exclude: false } } } : void 0;
|
|
10732
10771
|
}
|
|
10733
10772
|
if (npm === "@ai-sdk/openai" || npm === "@ai-sdk/azure") {
|
|
10734
|
-
if (!modelId ||
|
|
10773
|
+
if (!modelId || isChatVariant(modelId)) return void 0;
|
|
10774
|
+
if (!(modelPrefersResponsesApi(modelId) || isCodexReasoningFamily(modelId))) {
|
|
10775
|
+
return void 0;
|
|
10776
|
+
}
|
|
10735
10777
|
const reasoningEffort = mapCodexEffortToOpenAI(effort, modelId);
|
|
10736
10778
|
if (!reasoningEffort) return void 0;
|
|
10737
|
-
|
|
10779
|
+
const openaiOptions = { reasoningEffort, forceReasoning: true };
|
|
10780
|
+
return isReasoningSummaryUnsupportedModel(modelId) ? { openai: { ...openaiOptions, reasoningSummary: null } } : { openai: openaiOptions };
|
|
10738
10781
|
}
|
|
10739
10782
|
if (npm === "@ai-sdk/xai") {
|
|
10740
10783
|
if (!modelId || !isXaiReasoningEffortModel(modelId)) return void 0;
|
|
@@ -15021,7 +15064,7 @@ function parseOpenAiModelEntries(body) {
|
|
|
15021
15064
|
}
|
|
15022
15065
|
return [];
|
|
15023
15066
|
}
|
|
15024
|
-
function buildDynamicOAuthModel(entry, seedById) {
|
|
15067
|
+
function buildDynamicOAuthModel(entry, seedById, codexCatalog) {
|
|
15025
15068
|
const seed = seedById.get(entry.id);
|
|
15026
15069
|
if (seed) {
|
|
15027
15070
|
return {
|
|
@@ -15052,7 +15095,19 @@ function buildDynamicOAuthModel(entry, seedById) {
|
|
|
15052
15095
|
...openAiPricingMetadata(id),
|
|
15053
15096
|
modelFormat: "openai",
|
|
15054
15097
|
npm: "@ai-sdk/openai",
|
|
15055
|
-
|
|
15098
|
+
// Assume a model from the Codex listing reasons. That endpoint reports no
|
|
15099
|
+
// reasoning field of its own, so the old `modelPrefersResponsesApi(id)` was an
|
|
15100
|
+
// id-pattern GUESS that silently said "no" to every family it had not been
|
|
15101
|
+
// taught yet — gpt-6-astra and gpt-daybreak-blue-latest both landed as
|
|
15102
|
+
// non-reasoning that way, which dropped the user's chosen effort and removed
|
|
15103
|
+
// the effort selector from the patched binary (getPatchReasoningCapabilities
|
|
15104
|
+
// early-returns on a `false`). Verified against all 11 models in the live
|
|
15105
|
+
// catalog on 2026-09-04.
|
|
15106
|
+
//
|
|
15107
|
+
// This only decides what the effort UI offers. It is NOT on its own enough to
|
|
15108
|
+
// put reasoning.effort on the wire — effortProviderOptions admits by family —
|
|
15109
|
+
// so a wrong `true` here costs an unusable menu entry, not a 400.
|
|
15110
|
+
reasoning: codexCatalog ? true : modelPrefersResponsesApi(id),
|
|
15056
15111
|
useResponsesLite: entry.useResponsesLite,
|
|
15057
15112
|
preferWebSockets: entry.preferWebSockets
|
|
15058
15113
|
};
|
|
@@ -15081,7 +15136,7 @@ async function fetchJsonWithAuth(url, accessToken, timeoutMs) {
|
|
|
15081
15136
|
async function refreshOpenAiOAuthModels(accessToken) {
|
|
15082
15137
|
const TIMEOUT_MS = 1e4;
|
|
15083
15138
|
const seedById = new Map(buildOpenAiOAuthModels().map((m) => [m.id, m]));
|
|
15084
|
-
const toModels = (entries) => entries.map((entry) => buildDynamicOAuthModel(entry, seedById));
|
|
15139
|
+
const toModels = (entries, codexCatalog) => entries.map((entry) => buildDynamicOAuthModel(entry, seedById, codexCatalog));
|
|
15085
15140
|
const claudeVersion = getInstalledClaudeVersion();
|
|
15086
15141
|
const codexResult = await fetchJsonWithAuth(
|
|
15087
15142
|
`https://chatgpt.com/backend-api/codex/models?client_version=${claudeVersion}`,
|
|
@@ -15090,7 +15145,7 @@ async function refreshOpenAiOAuthModels(accessToken) {
|
|
|
15090
15145
|
);
|
|
15091
15146
|
const codexEntries = parseOpenAiModelEntries(codexResult.body);
|
|
15092
15147
|
if (codexEntries.length > 0) {
|
|
15093
|
-
return { models: toModels(codexEntries), source: "live" };
|
|
15148
|
+
return { models: toModels(codexEntries, true), source: "live" };
|
|
15094
15149
|
}
|
|
15095
15150
|
const chatGptResult = await fetchJsonWithAuth(
|
|
15096
15151
|
"https://chatgpt.com/backend-api/models",
|
|
@@ -15099,7 +15154,7 @@ async function refreshOpenAiOAuthModels(accessToken) {
|
|
|
15099
15154
|
);
|
|
15100
15155
|
const chatGptEntries = parseOpenAiModelEntries(chatGptResult.body).filter(({ id }) => !CHATGPT_CODEX_UNSUPPORTED_MODELS.has(id));
|
|
15101
15156
|
if (chatGptEntries.length > 0) {
|
|
15102
|
-
return { models: toModels(chatGptEntries), source: "live" };
|
|
15157
|
+
return { models: toModels(chatGptEntries, false), source: "live" };
|
|
15103
15158
|
}
|
|
15104
15159
|
const failures = [codexResult.error, chatGptResult.error].filter((error) => error !== void 0);
|
|
15105
15160
|
const credentialFailure = failures.find((error) => /(?:\brejected\b|\b401\b|\b403\b)/i.test(error));
|