@nyssance/codex-acp-v2 0.7.3 → 0.7.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.4 — 2026-09-30
4
+
5
+ ### Added
6
+
7
+ - `CODEX_ACP_MODEL_CATALOGS`: extra model catalog files for gateway models. Codex builds its model
8
+ table once at app-server start and ignores a per-thread `model_catalog_json`, so gateway models ran on
9
+ fallback metadata and every reply opened with "Model metadata for `…` not found". The adapter now dumps
10
+ Codex's own catalog (`codex debug models`), adds the extra entries hidden, and starts the app-server
11
+ with the merged file.
12
+
13
+ ### Changed
14
+
15
+ - Generated against Codex 0.159.2 (`@openai/codex` ^0.159.2): `tooManyDenials` turn errors are
16
+ classified `too_many_denials` (not retryable); `thread/items/list` cursors may be item anchors.
17
+
3
18
  ## 0.7.3 — 2026-09-30
4
19
 
5
20
  ### Changed
package/README.md CHANGED
@@ -91,6 +91,7 @@ adjust defaults.
91
91
  | Variable | Effect |
92
92
  | --- | --- |
93
93
  | `CODEX_PATH` | Codex executable to spawn (`codex app-server`). Default: bundled `@openai/codex`. |
94
+ | `CODEX_ACP_MODEL_CATALOGS` | Extra Codex model catalog files (`{models: [...]}`, joined with the platform path delimiter) for gateway models. Codex reads model metadata only at app-server start, so these are merged, hidden from the ChatGPT group, into Codex's own catalog there; without them a gateway model runs on fallback metadata and Codex warns on every turn. |
94
95
  | `CODEX_CONFIG` | JSON object merged into every thread's Codex config. |
95
96
  | `MODEL_PROVIDER` | Codex model provider for new threads. |
96
97
  | `INITIAL_AGENT_MODE` | `read-only`, `agent` (default), or `agent-full-access`. |
package/dist/index.js CHANGED
@@ -21844,7 +21844,7 @@ var package_default = {
21844
21844
  publishConfig: {
21845
21845
  access: "public"
21846
21846
  },
21847
- version: "0.7.3",
21847
+ version: "0.7.4",
21848
21848
  description: "Native ACP v2 agent for the OpenAI Codex app-server",
21849
21849
  packageManager: "bun@1.4.0",
21850
21850
  engines: {
@@ -21916,7 +21916,7 @@ var package_default = {
21916
21916
  "vscode-jsonrpc": "^9.0.2"
21917
21917
  },
21918
21918
  optionalDependencies: {
21919
- "@openai/codex": "^0.158.0"
21919
+ "@openai/codex": "^0.159.2"
21920
21920
  }
21921
21921
  };
21922
21922
 
@@ -22076,6 +22076,8 @@ function classifyTurnError(info) {
22076
22076
  case "cyberPolicy":
22077
22077
  case "misalignmentPolicyViolation":
22078
22078
  return failure2("policy", false, "refusal");
22079
+ case "tooManyDenials":
22080
+ return failure2("too_many_denials");
22079
22081
  case "sessionBudgetExceeded":
22080
22082
  return failure2("budget");
22081
22083
  case "usageLimitExceeded":
@@ -28604,7 +28606,8 @@ function threadIdOf(notification) {
28604
28606
  }
28605
28607
 
28606
28608
  // src/codex/process.ts
28607
- import { existsSync } from "fs";
28609
+ import { existsSync, mkdtempSync, readFileSync as readFileSync2, writeFileSync } from "fs";
28610
+ import os3 from "os";
28608
28611
  import path8 from "path";
28609
28612
  import { spawn, spawnSync } from "child_process";
28610
28613
  import { createRequire } from "module";
@@ -28916,7 +28919,9 @@ function startCodexProcess(codexPath, env = process.env) {
28916
28919
  if (probe.error !== undefined)
28917
28920
  throw new Error(`Could not run Codex (${launcher.command}): ${probe.error.message}`);
28918
28921
  assertCodexVersion(probe.stdout.length > 0 ? probe.stdout : probe.stderr);
28919
- const child = launcher.shell ? spawn(`${launcher.command} app-server`, { shell: true, env }) : spawn(launcher.command, [...launcher.prefixArgs, "app-server"], { env });
28922
+ const catalog = mergedModelCatalog(launcher, env);
28923
+ const catalogOverride = catalog === null ? null : `model_catalog_json='${catalog}'`;
28924
+ const child = launcher.shell ? spawn(`${launcher.command}${catalogOverride === null ? "" : ` -c "${catalogOverride}"`} app-server`, { shell: true, env }) : spawn(launcher.command, [...launcher.prefixArgs, ...catalogOverride === null ? [] : ["-c", catalogOverride], "app-server"], { env });
28920
28925
  let stderr = "";
28921
28926
  child.stderr.on("data", (data) => {
28922
28927
  stderr = (stderr + data.toString()).slice(-STDERR_RETAIN_BYTES);
@@ -28941,6 +28946,44 @@ function startCodexProcess(codexPath, env = process.env) {
28941
28946
  exitCode: () => child.exitCode
28942
28947
  };
28943
28948
  }
28949
+ var EXTRA_MODEL_CATALOGS_ENV = "CODEX_ACP_MODEL_CATALOGS";
28950
+ function mergedModelCatalog(launcher, env) {
28951
+ const raw = env[EXTRA_MODEL_CATALOGS_ENV];
28952
+ if (raw === undefined || raw.trim() === "")
28953
+ return null;
28954
+ const files = raw.split(path8.delimiter).filter((file2) => file2.length > 0);
28955
+ const dump = spawnSync(launcher.command, [...launcher.prefixArgs, "debug", "models"], {
28956
+ shell: launcher.shell,
28957
+ env,
28958
+ encoding: "utf8",
28959
+ maxBuffer: 64 * 1024 * 1024
28960
+ });
28961
+ if (dump.error !== undefined || dump.status !== 0) {
28962
+ throw new Error(`codex debug models failed: ${dump.error?.message ?? dump.stderr.trim()}`);
28963
+ }
28964
+ const base = JSON.parse(dump.stdout);
28965
+ if (!Array.isArray(base.models))
28966
+ throw new Error("codex debug models did not return {models: [...]}");
28967
+ const models = base.models;
28968
+ const slugs = new Set(models.map((model) => model["slug"]));
28969
+ for (const file2 of files) {
28970
+ const extra = JSON.parse(readFileSync2(file2, "utf8"));
28971
+ if (!Array.isArray(extra.models))
28972
+ throw new Error(`${EXTRA_MODEL_CATALOGS_ENV}: ${file2} is not {models: [...]}`);
28973
+ for (const entry of extra.models) {
28974
+ if (typeof entry["slug"] !== "string")
28975
+ throw new Error(`${EXTRA_MODEL_CATALOGS_ENV}: ${file2} has an entry without a slug`);
28976
+ if (slugs.has(entry["slug"]))
28977
+ continue;
28978
+ slugs.add(entry["slug"]);
28979
+ models.push({ ...entry, visibility: "hide" });
28980
+ }
28981
+ }
28982
+ const directory = mkdtempSync(path8.join(os3.tmpdir(), "codex-acp-v2-catalog-"));
28983
+ const target = path8.join(directory, "models.json");
28984
+ writeFileSync(target, JSON.stringify({ ...base, models }));
28985
+ return target;
28986
+ }
28944
28987
 
28945
28988
  // src/index.ts
28946
28989
  var CODEX_EXIT_GRACE_MS = 2000;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.7.3",
6
+ "version": "0.7.4",
7
7
  "description": "Native ACP v2 agent for the OpenAI Codex app-server",
8
8
  "packageManager": "bun@1.4.0",
9
9
  "engines": {
@@ -75,6 +75,6 @@
75
75
  "vscode-jsonrpc": "^9.0.2"
76
76
  },
77
77
  "optionalDependencies": {
78
- "@openai/codex": "^0.158.0"
78
+ "@openai/codex": "^0.159.2"
79
79
  }
80
80
  }