@bman654/clodex 2.18.4 → 2.18.6

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/dist/cli.js CHANGED
@@ -74,7 +74,7 @@ import {
74
74
  withRegistryWriteLockSync,
75
75
  writeParentNoticeLines,
76
76
  writeParentNoticeLinesSync
77
- } from "./chunk-YGEPQOPA.js";
77
+ } from "./chunk-VFYRDLDD.js";
78
78
 
79
79
  // src/cli.ts
80
80
  import pc13 from "picocolors";
@@ -346,7 +346,7 @@ import { join } from "path";
346
346
  // package.json
347
347
  var package_default = {
348
348
  name: "@bman654/clodex",
349
- version: "2.18.4",
349
+ version: "2.18.6",
350
350
  publishConfig: {
351
351
  access: "public"
352
352
  },
@@ -433,7 +433,7 @@ var package_default = {
433
433
 
434
434
  // src/constants.ts
435
435
  var CODEX_RESPONSES_LITE_WS_URL = "wss://chatgpt.com/backend-api/codex/responses";
436
- var CODEX_RESPONSES_LITE_VERSION = "0.156.0";
436
+ var CODEX_RESPONSES_LITE_VERSION = "0.159.0";
437
437
  var CODEX_RESPONSES_WEBSOCKETS_BETA = "responses_websockets=2026-02-06";
438
438
  var TEST_TIMEOUT_MS = 1e4;
439
439
  var CONFLICTING_ENV_VARS = [
@@ -630,6 +630,7 @@ var HEURISTIC_RULES = [
630
630
  [/claude/i, 2e5],
631
631
  [/deepseek-v4|deepseek-r1|deepseek-reasoner/i, 1e6],
632
632
  [/deepseek/i, 64e3],
633
+ [/gpt-6\.1-sol/i, 105e4],
633
634
  [/gpt-6-(?:astra|sol|luna)/i, 105e4],
634
635
  [/gpt-5|gpt-4\.1|o3-|o4-/i, 1e6],
635
636
  [/gpt-4o|gpt-4-turbo|gpt-4/i, 128e3],
@@ -4916,31 +4917,6 @@ var opencode_go_models_default = [
4916
4917
  upstreamModelId: "deepseek-v4.1-flash",
4917
4918
  family: "deepseek"
4918
4919
  },
4919
- {
4920
- id: "glm-5.1",
4921
- name: "GLM-5.1",
4922
- contextWindow: 202752,
4923
- cost: {
4924
- input: 1.4,
4925
- output: 4.4,
4926
- cache_read: 0.26
4927
- },
4928
- modelFormat: "openai",
4929
- npm: "@ai-sdk/openai-compatible",
4930
- apiUrl: "https://opencode.ai/zen/go/v1",
4931
- reasoning: true,
4932
- modalities: [
4933
- "text"
4934
- ],
4935
- compatibility: {
4936
- supportsReasoningEffort: false,
4937
- supportsStore: false,
4938
- supportsDeveloperRole: false,
4939
- maxTokensField: "max_tokens"
4940
- },
4941
- upstreamModelId: "glm-5.1",
4942
- family: "glm"
4943
- },
4944
4920
  {
4945
4921
  id: "glm-5.2",
4946
4922
  name: "GLM-5.2",
@@ -5009,6 +4985,39 @@ var opencode_go_models_default = [
5009
4985
  upstreamModelId: "gpt-5.6-luna",
5010
4986
  family: "gpt"
5011
4987
  },
4988
+ {
4989
+ id: "gpt-6-luna",
4990
+ name: "GPT-6 Luna",
4991
+ contextWindow: 105e4,
4992
+ pricingBoundary: 272e3,
4993
+ pricingBoundaryNote: "Above it, OpenCode Go lists $0.20 input and $0.75 output per million tokens.",
4994
+ cost: {
4995
+ input: 0.1,
4996
+ output: 0.5,
4997
+ cache_read: 0.01,
4998
+ cache_write: 0.125
4999
+ },
5000
+ modelFormat: "openai",
5001
+ npm: "@ai-sdk/openai",
5002
+ apiUrl: "https://opencode.ai/zen/go/v1",
5003
+ reasoning: true,
5004
+ modalities: [
5005
+ "text",
5006
+ "image"
5007
+ ],
5008
+ compatibility: {
5009
+ reasoningEffortMap: {
5010
+ none: "none",
5011
+ low: "low",
5012
+ medium: "medium",
5013
+ high: "high",
5014
+ xhigh: "xhigh",
5015
+ max: "max"
5016
+ }
5017
+ },
5018
+ upstreamModelId: "gpt-6-luna",
5019
+ family: "gpt"
5020
+ },
5012
5021
  {
5013
5022
  id: "hy3",
5014
5023
  name: "Hy3",
@@ -5193,7 +5202,8 @@ var opencode_go_models_default = [
5193
5202
  cost: {
5194
5203
  input: 0.3,
5195
5204
  output: 1.2,
5196
- cache_read: 0.06
5205
+ cache_read: 0.06,
5206
+ cache_write: 0.375
5197
5207
  },
5198
5208
  modelFormat: "openai",
5199
5209
  npm: "@ai-sdk/openai-compatible",
@@ -6052,16 +6062,33 @@ function compareCodexClientVersions(a, b) {
6052
6062
  }
6053
6063
  return 0;
6054
6064
  }
6055
- function requiresNewerCodexClient(model) {
6056
- if (!model.useResponsesLite) return false;
6065
+ function atLeast(version, floor) {
6066
+ const order = compareCodexClientVersions(version, floor);
6067
+ return order === 0 || order === 1;
6068
+ }
6069
+ function codexClientRequirement(model) {
6070
+ if (!model.useResponsesLite) return void 0;
6057
6071
  const minimum = readCodexClientVersion(model.minimalClientVersion);
6058
- return minimum !== void 0 && compareCodexClientVersions(minimum, CODEX_RESPONSES_LITE_VERSION) === 1;
6072
+ const withheldAt = readCodexClientVersion(model.withheldAtClientVersion);
6073
+ const blockingMinimum = minimum !== void 0 && compareCodexClientVersions(minimum, CODEX_RESPONSES_LITE_VERSION) === 1 ? minimum : void 0;
6074
+ const blockingWithheld = withheldAt !== void 0 && atLeast(withheldAt, CODEX_RESPONSES_LITE_VERSION) ? withheldAt : void 0;
6075
+ if (blockingMinimum !== void 0 && (blockingWithheld === void 0 || compareCodexClientVersions(blockingMinimum, blockingWithheld) === 1)) {
6076
+ return { kind: "minimum", version: blockingMinimum };
6077
+ }
6078
+ return blockingWithheld === void 0 ? void 0 : { kind: "withheld", version: blockingWithheld };
6079
+ }
6080
+ function requiresNewerCodexClient(model) {
6081
+ return codexClientRequirement(model) !== void 0;
6059
6082
  }
6060
6083
  function codexClientVersionWarning(models) {
6061
- const unavailable = models.filter(requiresNewerCodexClient);
6084
+ const unavailable = models.flatMap((model) => {
6085
+ const requirement = codexClientRequirement(model);
6086
+ return requirement ? [{ id: model.id, requirement }] : [];
6087
+ });
6062
6088
  if (unavailable.length === 0) return void 0;
6063
- const details = unavailable.map((model) => `${printableServerText(model.id)} (requires ${model.minimalClientVersion})`).join(", ");
6064
- return `Hidden ChatGPT-plan models: ${details}. clodex sends Codex client version ${CODEX_RESPONSES_LITE_VERSION} for Responses-Lite; their catalog minimum exceeds this version. Update clodex to a release supporting their required version to use them.`;
6089
+ const details = unavailable.map(({ id, requirement }) => `${printableServerText(id)} (requires ${requirement.kind === "minimum" ? requirement.version : `a version newer than ${requirement.version}`})`).join(", ");
6090
+ const reason = unavailable.every(({ requirement }) => requirement.kind === "minimum") ? "their catalog minimum exceeds this version" : "the ChatGPT catalog does not offer them to this version";
6091
+ return `Hidden ChatGPT-plan models: ${details}. clodex sends Codex client version ${CODEX_RESPONSES_LITE_VERSION} for Responses-Lite; ${reason}. Update clodex to a release supporting their required version to use them.`;
6065
6092
  }
6066
6093
 
6067
6094
  // src/data/openai-oauth-models.ts
@@ -6072,6 +6099,13 @@ var CHATGPT_CODEX_UNSUPPORTED_MODELS = /* @__PURE__ */ new Set([
6072
6099
  // confirmed: rejected by chatgpt.com/backend-api/codex
6073
6100
  ]);
6074
6101
  var OPENAI_OAUTH_MODEL_SEEDS = [
6102
+ // GPT-6.1 Sol: the 272K window and 872K ceiling are what the live Codex catalog
6103
+ // returned on 2026-09-29; a request near 872K has not been tried. The output limit
6104
+ // is the model card's. The catalog reports minimal_client_version 0.153.0, but on a
6105
+ // Plus account versions through 0.158.0 were refused and 0.159.0 worked (#298), so
6106
+ // this seed records that observed gate. A live refresh stores the catalog's value
6107
+ // instead. CODEX_RESPONSES_LITE_VERSION must stay at or above this.
6108
+ { id: "gpt-6.1-sol", name: "GPT-6.1 Sol", contextWindow: 272e3, maxContextWindow: 872e3, maxOutputTokens: 128e3, reasoning: true, useResponsesLite: true, preferWebSockets: true, minimalClientVersion: "0.159.0" },
6075
6109
  // GPT-6 family. The window, ceiling and Responses-Lite flags are what the live
6076
6110
  // Codex catalog returned (Astra on 2026-09-04, Sol and Luna on 2026-09-22) and are
6077
6111
  // deliberately NOT the published API numbers: the model cards list a 1,050,000
@@ -16612,12 +16646,7 @@ async function resolveRefreshCredentialWithSource(provider, resolveKey, selected
16612
16646
  return resolved;
16613
16647
  }
16614
16648
 
16615
- // src/registry/refresh-models.ts
16616
- async function refreshOAuthProvider(provider, accessToken) {
16617
- const tpl = provider.templateId ?? provider.id;
16618
- if (tpl === "openai" || tpl === "openai-oauth") return refreshOpenAiOAuthModels(accessToken);
16619
- throw new Error(`refreshOAuthProvider: unsupported template "${tpl}"`);
16620
- }
16649
+ // src/registry/openai-oauth-catalog.ts
16621
16650
  function positiveInteger2(value) {
16622
16651
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
16623
16652
  }
@@ -16737,7 +16766,41 @@ async function fetchJsonWithAuth(url, accessToken, timeoutMs) {
16737
16766
  }
16738
16767
  }
16739
16768
  }
16740
- async function refreshOpenAiOAuthModels(accessToken) {
16769
+ async function markModelsWithheldAtRequestVersion(models, accessToken, timeoutMs, previous) {
16770
+ const pinned = await fetchJsonWithAuth(
16771
+ `https://chatgpt.com/backend-api/codex/models?client_version=${CODEX_RESPONSES_LITE_VERSION}`,
16772
+ accessToken,
16773
+ timeoutMs
16774
+ );
16775
+ const offered = readOfferedIds(pinned.body);
16776
+ if (!offered) return carryWithheldMarkers(models, previous);
16777
+ return models.map((model) => offered.has(model.id) ? model : { ...model, withheldAtClientVersion: CODEX_RESPONSES_LITE_VERSION });
16778
+ }
16779
+ function readOfferedIds(body) {
16780
+ if (!body || typeof body !== "object") return void 0;
16781
+ const record = body;
16782
+ const shape = Array.isArray(record.models) ? { rows: record.models, key: "slug" } : Array.isArray(record.data) ? { rows: record.data, key: "id" } : void 0;
16783
+ if (!shape || shape.rows.length === 0) return void 0;
16784
+ const ids = /* @__PURE__ */ new Set();
16785
+ for (const row of shape.rows) {
16786
+ const id = row !== null && typeof row === "object" ? row[shape.key] : void 0;
16787
+ if (typeof id !== "string" || id === "" || id !== id.trim()) return void 0;
16788
+ ids.add(id);
16789
+ }
16790
+ return ids;
16791
+ }
16792
+ function carryWithheldMarkers(models, previous) {
16793
+ const withheld = new Map(previous.flatMap((model) => {
16794
+ const version = readCodexClientVersion(model.withheldAtClientVersion);
16795
+ return version ? [[model.id, version]] : [];
16796
+ }));
16797
+ if (withheld.size === 0) return models;
16798
+ return models.map((model) => {
16799
+ const version = withheld.get(model.id);
16800
+ return version ? { ...model, withheldAtClientVersion: version } : model;
16801
+ });
16802
+ }
16803
+ async function refreshOpenAiOAuthModels(accessToken, previous = []) {
16741
16804
  const TIMEOUT_MS = 1e4;
16742
16805
  const seedById = new Map(buildOpenAiOAuthModels().map((m) => [m.id, m]));
16743
16806
  const toModels = (entries, codexCatalog) => entries.map((entry) => buildDynamicOAuthModel(entry, seedById, codexCatalog));
@@ -16749,7 +16812,11 @@ async function refreshOpenAiOAuthModels(accessToken) {
16749
16812
  );
16750
16813
  const codexEntries = parseOpenAiModelEntries(codexResult.body);
16751
16814
  if (codexEntries.length > 0) {
16752
- return { models: toModels(codexEntries, true), source: "live" };
16815
+ const models = toModels(codexEntries, true);
16816
+ return {
16817
+ models: await markModelsWithheldAtRequestVersion(models, accessToken, TIMEOUT_MS, previous),
16818
+ source: "live"
16819
+ };
16753
16820
  }
16754
16821
  const chatGptResult = await fetchJsonWithAuth(
16755
16822
  "https://chatgpt.com/backend-api/models",
@@ -16758,7 +16825,10 @@ async function refreshOpenAiOAuthModels(accessToken) {
16758
16825
  );
16759
16826
  const chatGptEntries = parseOpenAiModelEntries(chatGptResult.body).filter(({ id }) => !CHATGPT_CODEX_UNSUPPORTED_MODELS.has(id));
16760
16827
  if (chatGptEntries.length > 0) {
16761
- return { models: toModels(chatGptEntries, false), source: "live" };
16828
+ return {
16829
+ models: carryWithheldMarkers(toModels(chatGptEntries, false), previous),
16830
+ source: "live"
16831
+ };
16762
16832
  }
16763
16833
  const failures = [codexResult.error, chatGptResult.error].filter((error) => error !== void 0);
16764
16834
  const credentialFailure = failures.find((error) => /(?:\brejected\b|\b401\b|\b403\b)/i.test(error));
@@ -16769,6 +16839,15 @@ async function refreshOpenAiOAuthModels(accessToken) {
16769
16839
  credentialRejected: credentialFailure !== void 0
16770
16840
  };
16771
16841
  }
16842
+
16843
+ // src/registry/refresh-models.ts
16844
+ async function refreshOAuthProvider(provider, accessToken) {
16845
+ const tpl = provider.templateId ?? provider.id;
16846
+ if (tpl === "openai" || tpl === "openai-oauth") {
16847
+ return refreshOpenAiOAuthModels(accessToken, provider.modelsCache?.models);
16848
+ }
16849
+ throw new Error(`refreshOAuthProvider: unsupported template "${tpl}"`);
16850
+ }
16772
16851
  function warningSuffix(models) {
16773
16852
  const warning = codexClientVersionWarning(applyOAuthSeedContextMetadata(models));
16774
16853
  return warning ? ` ${warning}` : "";