fix(acpx): migrate codex adapter to maintained @agentclientprotocol/codex-acp (#109075)

* fix(acpx): migrate codex adapter to maintained @agentclientprotocol/codex-acp

The bundled codex ACP adapter pinned the npm-deprecated
@zed-industries/codex-acp@0.16.0, which embeds codex crates from the
rust-v0.137.0 era: GPT-5.6-era models are unknown to it and sessions fail
with 'requires a newer version of Codex'. Migrate to the maintained
@agentclientprotocol/codex-acp@1.1.4 (Node CLI, depends on @openai/codex
^0.144.4 matching the codex plugin pin):

- Wrapper generation resolves the adapter bin from its package manifest and
  delivers startup config via CODEX_CONFIG; OpenClaw-owned wrapper args are
  stripped before launch. Explicit new-adapter commands keep their own
  -c/--config args untouched; only retired Zed commands migrate, with their
  -c TOML overrides (dotted/quoted keys, attached forms, MCP config)
  faithfully converted.
- Model overrides emit the bare model id plus a separate
  model_reasoning_effort; composite model/effort ids are accepted as parse
  input but never emitted.
- Process reaper recognizes the maintained adapter tree and packaged codex
  app-server children without claiming native codex plugin processes.

Live proof: direct adapter smoke with local subscription auth initialized
1.1.4, advertised model gpt-5.6-sol with separate medium effort, and
completed a turn. Fixes #108664

* fix(acpx): pin codex-acp 1.1.2 to satisfy the lockfile release-age gate

1.1.4 is under the 48-hour minimumReleaseAge and fails lockfile
verification repo-wide. 1.1.2 (2026-07-09) passes the gate, carries the
same CODEX_CONFIG startup contract, and its ^0.144.0 codex dependency
resolves to the same 0.144.4 the codex plugin pins. Lockfile re-resolved
from main without any release-age bypass; shrinkwrap regenerated.

* chore(acpx): split oversized auth-bridge test file, register adapter as CLI-resolved dep

codex-auth-bridge.test.ts crossed the max-lines gate after the migration
regressions; the command-migration cluster moves to
codex-auth-bridge.migration.test.ts. knip's CLI-resolved dependency list
swaps the retired zed adapter for @agentclientprotocol/codex-acp (invoked
via generated wrapper/npx, never imported).
This commit is contained in:
Peter Steinberger
2026-07-16 08:51:30 -07:00
committed by GitHub
parent c46cc1e2d4
commit 0fa77124e9
14 changed files with 1088 additions and 304 deletions
+1 -1
View File
@@ -200,7 +200,7 @@ const bundledPluginIgnoredRuntimeDependencies = [
"@openai/codex",
"@pierre/theme",
"@tloncorp/tlon-skill",
"@zed-industries/codex-acp",
"@agentclientprotocol/codex-acp",
"jiti",
"json5",
"lit",
+355 -114
View File
@@ -9,8 +9,9 @@
"version": "2026.7.2",
"dependencies": {
"@agentclientprotocol/claude-agent-acp": "0.55.0",
"@zed-industries/codex-acp": "0.16.0",
"@agentclientprotocol/codex-acp": "1.1.2",
"acpx": "0.11.2",
"smol-toml": "1.7.0",
"zod": "4.4.3"
}
},
@@ -31,6 +32,32 @@
"node": ">=22"
}
},
"node_modules/@agentclientprotocol/codex-acp": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@agentclientprotocol/codex-acp/-/codex-acp-1.1.2.tgz",
"integrity": "sha512-qE/R1WdqJJ9OFHsHGvbmVmS2j9iCMZzpWT3g2XIViXrGHu1fLOALLINBIlW+WzKDllCh131aB6cqcIWSt0otbw==",
"license": "Apache-2.0",
"dependencies": {
"@agentclientprotocol/sdk": "^1.2.1",
"@openai/codex": "^0.144.0",
"diff": "^9.0.0",
"open": "^11.0.0",
"vscode-jsonrpc": "^9.0.1",
"zod": "^4.0.0"
},
"bin": {
"codex-acp": "dist/index.js"
}
},
"node_modules/@agentclientprotocol/codex-acp/node_modules/@agentclientprotocol/sdk": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-1.2.1.tgz",
"integrity": "sha512-jwYUdOQR7tc+Zfch53VL4JJyUNK/46q03uUTYb+PjECsmnNl94XFXOfYLJ8RBpMNidXd1rpOAVgb0vqD98xImA==",
"license": "Apache-2.0",
"peerDependencies": {
"zod": "^3.25.0 || ^4.0.0"
}
},
"node_modules/@agentclientprotocol/sdk": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-1.1.0.tgz",
@@ -694,125 +721,134 @@
}
}
},
"node_modules/@openai/codex": {
"version": "0.144.4",
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.4.tgz",
"integrity": "sha512-DTHzYatlKq9dw55E0/HsbK4tRCEKabuJ10ybbqpsG8gVv/kvwEdg3Z4OI3cvLXKa21xkIa4lkGlZoO/HmqmFFw==",
"license": "Apache-2.0",
"bin": {
"codex": "bin/codex.js"
},
"engines": {
"node": ">=16"
},
"optionalDependencies": {
"@openai/codex-darwin-arm64": "npm:@openai/codex@0.144.4-darwin-arm64",
"@openai/codex-darwin-x64": "npm:@openai/codex@0.144.4-darwin-x64",
"@openai/codex-linux-arm64": "npm:@openai/codex@0.144.4-linux-arm64",
"@openai/codex-linux-x64": "npm:@openai/codex@0.144.4-linux-x64",
"@openai/codex-win32-arm64": "npm:@openai/codex@0.144.4-win32-arm64",
"@openai/codex-win32-x64": "npm:@openai/codex@0.144.4-win32-x64"
}
},
"node_modules/@openai/codex-darwin-arm64": {
"name": "@openai/codex",
"version": "0.144.4-darwin-arm64",
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.4-darwin-arm64.tgz",
"integrity": "sha512-6J3g498cM2oA7vYIJhpuGJlnIi/M5JdYmjB5BZ1Of5HQ0ziIlplFSvH801oVy9J5TQFp642ODzOu/ZEokDUXsg==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16"
}
},
"node_modules/@openai/codex-darwin-x64": {
"name": "@openai/codex",
"version": "0.144.4-darwin-x64",
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.4-darwin-x64.tgz",
"integrity": "sha512-k1HC8gdbAy+VmMbekYkhM+r+QE2Xfgd67n1VSp94tjz7aXVKoalHcDkdKNM/uUQ8o2tvbiwhHSUftJF8Sm9/Lw==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16"
}
},
"node_modules/@openai/codex-linux-arm64": {
"name": "@openai/codex",
"version": "0.144.4-linux-arm64",
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.4-linux-arm64.tgz",
"integrity": "sha512-OlKx65579OwIzech9Tt3OUH9+hFZfFrCBP1hL2MudnMIoNr1+cFZjB5YIj5MWMRoBD+K5W3wdBIpQSH855b5Sg==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16"
}
},
"node_modules/@openai/codex-linux-x64": {
"name": "@openai/codex",
"version": "0.144.4-linux-x64",
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.4-linux-x64.tgz",
"integrity": "sha512-2jxrmV6+/7eBNdg5uhhmOEPFu2o28eYY/ClLzWhSBHH8uo3f2KA1z9JQcVtwlbToW03nEPlEzYNYfCF1UBqsVQ==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16"
}
},
"node_modules/@openai/codex-win32-arm64": {
"name": "@openai/codex",
"version": "0.144.4-win32-arm64",
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.4-win32-arm64.tgz",
"integrity": "sha512-CCgfI1smFhHZTIpTuBwDJwBr/AR40RTqaFxbBWVabu0RMeYDteRuPiDfdTlktf3C43Y1q10VZXhVGYtCokDg2w==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16"
}
},
"node_modules/@openai/codex-win32-x64": {
"name": "@openai/codex",
"version": "0.144.4-win32-x64",
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.4-win32-x64.tgz",
"integrity": "sha512-iL1ky0ERgdQJOKzom/Ms1fhpwkSmpsA9eVrzAqURFlYGS8z7JqwEgm33+nLGCsY7y25d8Xs/LJ91Oiqz3yXcUg==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16"
}
},
"node_modules/@stablelib/base64": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz",
"integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==",
"license": "MIT"
},
"node_modules/@zed-industries/codex-acp": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zed-industries/codex-acp/-/codex-acp-0.16.0.tgz",
"integrity": "sha512-XKzqztT5R8Wg1BVFnk6/U4JVx5GNUaZgxpf9gP2Cw6BsknvJWh3aefcAGZQljgdMivRqczjNKYL4F6H65dc5vA==",
"license": "Apache-2.0",
"bin": {
"codex-acp": "bin/codex-acp.js"
},
"optionalDependencies": {
"@zed-industries/codex-acp-darwin-arm64": "0.16.0",
"@zed-industries/codex-acp-darwin-x64": "0.16.0",
"@zed-industries/codex-acp-linux-arm64": "0.16.0",
"@zed-industries/codex-acp-linux-x64": "0.16.0",
"@zed-industries/codex-acp-win32-arm64": "0.16.0",
"@zed-industries/codex-acp-win32-x64": "0.16.0"
}
},
"node_modules/@zed-industries/codex-acp-darwin-arm64": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zed-industries/codex-acp-darwin-arm64/-/codex-acp-darwin-arm64-0.16.0.tgz",
"integrity": "sha512-2AmbWsc/+Mpn6U8UOIlPLvgwGsGOr/LFpgcvrnjcCT9V1yY92MLrqzjMX82+VjTrRLRuXvc25SB5Z1++4Pw29g==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"bin": {
"codex-acp-darwin-arm64": "bin/codex-acp"
}
},
"node_modules/@zed-industries/codex-acp-darwin-x64": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zed-industries/codex-acp-darwin-x64/-/codex-acp-darwin-x64-0.16.0.tgz",
"integrity": "sha512-QCWggk0s4GTPLCR7eznyx29Dls4gzUKvp4MjZ4nzPX5gDL/02PGY+oCV1WsQOsnzWRK0RxM+GlK19rG1qzqplw==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"bin": {
"codex-acp-darwin-x64": "bin/codex-acp"
}
},
"node_modules/@zed-industries/codex-acp-linux-arm64": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zed-industries/codex-acp-linux-arm64/-/codex-acp-linux-arm64-0.16.0.tgz",
"integrity": "sha512-8HaZGWVPVs1N6yqImLCKlnlcYTYc9BMCEhaVJk0ON9lyofhK9mOBBAHQndKC4Scqq5JLUHQIOyb8+jwHUe3hSQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"bin": {
"codex-acp-linux-arm64": "bin/codex-acp"
}
},
"node_modules/@zed-industries/codex-acp-linux-x64": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zed-industries/codex-acp-linux-x64/-/codex-acp-linux-x64-0.16.0.tgz",
"integrity": "sha512-xs5zZBLpJuciEbZNx6ZSNL0qCa9h3i/zWpj40sp6QtF+L4Ow/7qzHdBzboGhHdcz1jrLedfZeRFDA2Elj8TLMA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"bin": {
"codex-acp-linux-x64": "bin/codex-acp"
}
},
"node_modules/@zed-industries/codex-acp-win32-arm64": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zed-industries/codex-acp-win32-arm64/-/codex-acp-win32-arm64-0.16.0.tgz",
"integrity": "sha512-4V3pDJvEyNkgVqWqlm0bLYEZ8liGXXp8InuHzCy5cgr+SFur6BuasA29tisN8NUrLus/ZvMhXCrOsNKurYAWQw==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"bin": {
"codex-acp-win32-arm64": "bin/codex-acp.exe"
}
},
"node_modules/@zed-industries/codex-acp-win32-x64": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/@zed-industries/codex-acp-win32-x64/-/codex-acp-win32-x64-0.16.0.tgz",
"integrity": "sha512-ZriI/ay5E3DCg8s22LZykIRI2XzQL6sZg/t81K+6qc86ldscaSWQSOT6KSnRcv31QJCMfBlFxMj22pZiGSVjQA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"bin": {
"codex-acp-win32-x64": "bin/codex-acp.exe"
}
},
"node_modules/accepts": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
@@ -1030,6 +1066,21 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/bundle-name": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
"integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
"license": "MIT",
"dependencies": {
"run-applescript": "^7.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -1165,6 +1216,46 @@
}
}
},
"node_modules/default-browser": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz",
"integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==",
"license": "MIT",
"dependencies": {
"bundle-name": "^4.1.0",
"default-browser-id": "^5.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/default-browser-id": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz",
"integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/define-lazy-prop": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
"integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -1174,6 +1265,15 @@
"node": ">= 0.8"
}
},
"node_modules/diff": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz",
"integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -1642,12 +1742,72 @@
"node": ">= 0.10"
}
},
"node_modules/is-docker": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
"integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
"license": "MIT",
"bin": {
"is-docker": "cli.js"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-in-ssh": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz",
"integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==",
"license": "MIT",
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-inside-container": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
"integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
"license": "MIT",
"dependencies": {
"is-docker": "^3.0.0"
},
"bin": {
"is-inside-container": "cli.js"
},
"engines": {
"node": ">=14.16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-promise": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
"license": "MIT"
},
"node_modules/is-wsl": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz",
"integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==",
"license": "MIT",
"dependencies": {
"is-inside-container": "^1.0.0"
},
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -1800,6 +1960,26 @@
"wrappy": "1"
}
},
"node_modules/open": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz",
"integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==",
"license": "MIT",
"dependencies": {
"default-browser": "^5.4.0",
"define-lazy-prop": "^3.0.0",
"is-in-ssh": "^1.0.0",
"is-inside-container": "^1.0.0",
"powershell-utils": "^0.1.0",
"wsl-utils": "^0.3.0"
},
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -1837,6 +2017,18 @@
"node": ">=16.20.0"
}
},
"node_modules/powershell-utils": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz",
"integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==",
"license": "MIT",
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -1918,6 +2110,18 @@
"node": ">= 18"
}
},
"node_modules/run-applescript": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz",
"integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -2091,6 +2295,18 @@
"node": ">=18"
}
},
"node_modules/smol-toml": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.0.tgz",
"integrity": "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">= 18"
},
"funding": {
"url": "https://github.com/sponsors/cyyynthia"
}
},
"node_modules/standardwebhooks": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz",
@@ -2233,6 +2449,15 @@
"node": ">= 0.8"
}
},
"node_modules/vscode-jsonrpc": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.1.tgz",
"integrity": "sha512-rfuA6T75H6m5EkbhtEPzre9pT0HPcDI2MMy4+nPFIBks5J8JBAUHD4tRYSgaBOijIEC7SRkC1kKyXTLqbmh9jw==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -2254,6 +2479,22 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
"node_modules/wsl-utils": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz",
"integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==",
"license": "MIT",
"dependencies": {
"is-wsl": "^3.1.0",
"powershell-utils": "^0.1.0"
},
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zod": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
+2 -1
View File
@@ -9,8 +9,9 @@
"type": "module",
"dependencies": {
"@agentclientprotocol/claude-agent-acp": "0.55.0",
"@zed-industries/codex-acp": "0.16.0",
"@agentclientprotocol/codex-acp": "1.1.2",
"acpx": "0.11.2",
"smol-toml": "1.7.0",
"zod": "4.4.3"
},
"devDependencies": {
+1 -1
View File
@@ -210,7 +210,7 @@ Defaults are:
- `openclaw -> openclaw acp`
- `claude -> bundled @agentclientprotocol/claude-agent-acp@0.55.0`
- `codex -> bundled @zed-industries/codex-acp@0.16.0 through OpenClaw's isolated CODEX_HOME wrapper`
- `codex -> bundled @agentclientprotocol/codex-acp@1.1.2 through OpenClaw's isolated CODEX_HOME wrapper`
- `copilot -> copilot --acp --stdio`
- `cursor -> cursor-agent acp`
- `droid -> droid exec --output-format acp`
+7
View File
@@ -0,0 +1,7 @@
export const CODEX_ACP_PACKAGE = "@agentclientprotocol/codex-acp";
export const CODEX_ACP_BIN = "codex-acp";
export const LEGACY_CODEX_ACP_PACKAGE = "@zed-industries/codex-acp";
// OpenClaw's generated wrapper consumes this startup config before launching
// the adapter. The adapter itself receives CODEX_CONFIG, never wrapper flags.
export const OPENCLAW_CODEX_CONFIG_ARG = "--openclaw-codex-config";
@@ -0,0 +1,323 @@
// ACPX tests cover codex auth bridge plugin behavior.
import { execFile } from "node:child_process";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { promisify } from "node:util";
import { afterEach, describe, expect, it, vi } from "vitest";
import { OPENCLAW_CODEX_CONFIG_ARG } from "./codex-adapter.js";
import { prepareAcpxCodexAuthConfig } from "./codex-auth-bridge.js";
import { splitCommandParts } from "./command-line.js";
import { resolveAcpxPluginConfig } from "./config.js";
const execFileAsync = promisify(execFile);
const tempDirs: string[] = [];
const previousEnv = {
CODEX_HOME: process.env.CODEX_HOME,
OPENCLAW_AGENT_DIR: process.env.OPENCLAW_AGENT_DIR,
};
async function makeTempDir(): Promise<string> {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-acpx-codex-auth-"));
tempDirs.push(dir);
return dir;
}
function quoteArg(value: string): string {
return JSON.stringify(value);
}
function restoreEnv(name: keyof typeof previousEnv): void {
const value = previousEnv[name];
if (value === undefined) {
delete process.env[name];
} else {
process.env[name] = value;
}
}
function generatedCodexPaths(stateDir: string): {
configPath: string;
wrapperPath: string;
} {
const baseDir = path.join(stateDir, "acpx");
const codexHome = path.join(baseDir, "codex-home");
return {
configPath: path.join(codexHome, "config.toml"),
wrapperPath: path.join(baseDir, "codex-acp-wrapper.mjs"),
};
}
function generatedClaudePaths(stateDir: string): {
wrapperPath: string;
} {
const baseDir = path.join(stateDir, "acpx");
return {
wrapperPath: path.join(baseDir, "claude-agent-acp-wrapper.mjs"),
};
}
function expectCodexWrapperCommand(command: string | undefined, wrapperPath: string): void {
expect(command).toContain(quoteArg(process.execPath));
expect(command).toContain(quoteArg(wrapperPath));
}
function expectClaudeWrapperCommand(command: string | undefined, wrapperPath: string): void {
expect(command).toContain(quoteArg(process.execPath));
expect(command).toContain(quoteArg(wrapperPath));
}
afterEach(async () => {
vi.restoreAllMocks();
restoreEnv("CODEX_HOME");
restoreEnv("OPENCLAW_AGENT_DIR");
for (const dir of tempDirs.splice(0)) {
await fs.rm(dir, { recursive: true, force: true });
}
});
describe("prepareAcpxCodexAuthConfig command migration", () => {
it("migrates an explicitly configured Zed Codex ACP command to the local wrapper", async () => {
const root = await makeTempDir();
const sourceCodexHome = path.join(root, "source-codex");
const stateDir = path.join(root, "state");
const generated = generatedCodexPaths(stateDir);
await fs.mkdir(sourceCodexHome, { recursive: true });
await fs.writeFile(
path.join(sourceCodexHome, "config.toml"),
'notify = ["SkyComputerUseClient", "turn-ended"]\n',
);
process.env.CODEX_HOME = sourceCodexHome;
const pluginConfig = resolveAcpxPluginConfig({
rawConfig: {
agents: {
codex: {
command:
'npx @zed-industries/codex-acp@0.12.0 -c=model=\'"gpt-5.4"\' -cmodel_reasoning_effort=\'"high"\' --config=\'mcp_servers."foo.bar"={ command = "node", args = ["server.js"] }\'',
},
},
},
workspaceDir: root,
});
const installedBinPath = path.join(root, "codex-acp.js");
await fs.writeFile(
installedBinPath,
"console.log(JSON.stringify({ argv: process.argv.slice(2), codexConfig: process.env.CODEX_CONFIG }));\n",
"utf8",
);
const resolved = await prepareAcpxCodexAuthConfig({
pluginConfig,
stateDir,
resolveInstalledCodexAcpBinPath: async () => installedBinPath,
});
expectCodexWrapperCommand(resolved.agents.codex, generated.wrapperPath);
expect(resolved.agents.codex).not.toContain("npx @zed-industries/codex-acp@0.12.0");
expect(resolved.agents.codex).not.toContain(quoteArg("-c"));
expect(resolved.agents.codex).toContain(quoteArg(OPENCLAW_CODEX_CONFIG_ARG));
expect(resolved.agents.codex).toContain(
quoteArg(
JSON.stringify({
model: "gpt-5.4",
model_reasoning_effort: "high",
mcp_servers: { "foo.bar": { command: "node", args: ["server.js"] } },
}),
),
);
const isolatedConfig = await fs.readFile(generated.configPath, "utf8");
expect(isolatedConfig).toContain('[mcp_servers."foo.bar"]');
expect(isolatedConfig).toContain('command = "node"');
expect(isolatedConfig).not.toContain("notify");
expect(isolatedConfig).not.toContain("SkyComputerUseClient");
const wrapper = await fs.readFile(generated.wrapperPath, "utf8");
expect(wrapper).toContain("process.argv.slice(2)");
expect(wrapper).toContain("CODEX_HOME: codexHome");
expect(wrapper).not.toContain(sourceCodexHome);
const [nodePath, wrapperPath, ...wrapperArgs] = splitCommandParts(resolved.agents.codex ?? "");
if (!nodePath || !wrapperPath) {
throw new Error("expected generated Codex ACP wrapper command");
}
const { stdout } = await execFileAsync(
nodePath,
[
wrapperPath,
...wrapperArgs,
OPENCLAW_CODEX_CONFIG_ARG,
JSON.stringify({ model: "gpt-5.6-sol", model_reasoning_effort: "medium" }),
],
{ cwd: root },
);
const launched = JSON.parse(stdout.trim()) as { argv?: unknown; codexConfig?: unknown };
expect(launched.argv).toStrictEqual([]);
expect(JSON.parse(String(launched.codexConfig))).toEqual({
model: "gpt-5.6-sol",
model_reasoning_effort: "medium",
mcp_servers: { "foo.bar": { command: "node", args: ["server.js"] } },
});
});
it("forwards maintained Codex ACP config flags without legacy migration", async () => {
const root = await makeTempDir();
const stateDir = path.join(root, "state");
const generated = generatedCodexPaths(stateDir);
const installedBinPath = path.join(root, "codex-acp.js");
await fs.writeFile(
installedBinPath,
"console.log(JSON.stringify({ argv: process.argv.slice(2), codexConfig: process.env.CODEX_CONFIG }));\n",
"utf8",
);
const pluginConfig = resolveAcpxPluginConfig({
rawConfig: {
agents: {
codex: {
command:
"npx @agentclientprotocol/codex-acp@1.1.2 cli -c 'model=\"gpt-5.6-sol\"' --config 'model_reasoning_effort=\"low\"'",
},
},
},
workspaceDir: root,
});
const resolved = await prepareAcpxCodexAuthConfig({
pluginConfig,
stateDir,
resolveInstalledCodexAcpBinPath: async () => installedBinPath,
});
expectCodexWrapperCommand(resolved.agents.codex, generated.wrapperPath);
const commandParts = splitCommandParts(resolved.agents.codex ?? "");
expect(commandParts.slice(2)).toStrictEqual([
"cli",
"-c",
'model="gpt-5.6-sol"',
"--config",
'model_reasoning_effort="low"',
]);
expect(commandParts).not.toContain(OPENCLAW_CODEX_CONFIG_ARG);
const [nodePath, wrapperPath, ...wrapperArgs] = commandParts;
if (!nodePath || !wrapperPath) {
throw new Error("expected generated Codex ACP wrapper command");
}
const { stdout } = await execFileAsync(
nodePath,
[
wrapperPath,
...wrapperArgs,
OPENCLAW_CODEX_CONFIG_ARG,
JSON.stringify({ model: "gpt-5.6-sol", model_reasoning_effort: "medium" }),
],
{ cwd: root, env: { ...process.env, CODEX_CONFIG: "" } },
);
const launched = JSON.parse(stdout.trim()) as { argv?: unknown; codexConfig?: unknown };
expect(launched.argv).toStrictEqual(commandParts.slice(2));
expect(JSON.parse(String(launched.codexConfig))).toEqual({
model: "gpt-5.6-sol",
model_reasoning_effort: "medium",
});
});
it("does not carry migrated MCP config across isolated Codex homes or rebuilds", async () => {
const root = await makeTempDir();
const sourceCodexHome = path.join(root, "source-codex");
const legacyStateDir = path.join(root, "legacy-state");
const maintainedStateDir = path.join(root, "maintained-state");
await fs.mkdir(sourceCodexHome, { recursive: true });
await fs.writeFile(path.join(sourceCodexHome, "config.toml"), "", "utf8");
process.env.CODEX_HOME = sourceCodexHome;
const legacyConfig = resolveAcpxPluginConfig({
rawConfig: {
agents: {
codex: {
command:
"npx @zed-industries/codex-acp@0.12.0 --config='mcp_servers.legacy={ command = \"node\" }'",
},
},
},
workspaceDir: root,
});
const maintainedConfig = resolveAcpxPluginConfig({ rawConfig: {}, workspaceDir: root });
await prepareAcpxCodexAuthConfig({
pluginConfig: legacyConfig,
stateDir: legacyStateDir,
resolveInstalledCodexAcpBinPath: async () => undefined,
});
await prepareAcpxCodexAuthConfig({
pluginConfig: maintainedConfig,
stateDir: maintainedStateDir,
resolveInstalledCodexAcpBinPath: async () => undefined,
});
expect(await fs.readFile(generatedCodexPaths(legacyStateDir).configPath, "utf8")).toContain(
"[mcp_servers.legacy]",
);
expect(
await fs.readFile(generatedCodexPaths(maintainedStateDir).configPath, "utf8"),
).not.toContain("mcp_servers");
await prepareAcpxCodexAuthConfig({
pluginConfig: maintainedConfig,
stateDir: legacyStateDir,
resolveInstalledCodexAcpBinPath: async () => undefined,
});
expect(await fs.readFile(generatedCodexPaths(legacyStateDir).configPath, "utf8")).not.toContain(
"mcp_servers",
);
});
it("migrates config flags from a bare Codex ACP executable", async () => {
const root = await makeTempDir();
const stateDir = path.join(root, "state");
const generated = generatedCodexPaths(stateDir);
const pluginConfig = resolveAcpxPluginConfig({
rawConfig: {
agents: {
codex: {
command: "codex-acp -cmodel='\"gpt-5.4\"'",
},
},
},
workspaceDir: root,
});
const resolved = await prepareAcpxCodexAuthConfig({
pluginConfig,
stateDir,
resolveInstalledCodexAcpBinPath: async () => path.join(root, "codex-acp.js"),
});
expectCodexWrapperCommand(resolved.agents.codex, generated.wrapperPath);
expect(resolved.agents.codex).not.toContain(quoteArg("-c"));
expect(resolved.agents.codex).toContain(quoteArg(JSON.stringify({ model: "gpt-5.4" })));
});
it("normalizes an explicitly configured Claude ACP npx command to the local wrapper", async () => {
const root = await makeTempDir();
const stateDir = path.join(root, "state");
const generated = generatedClaudePaths(stateDir);
const pluginConfig = resolveAcpxPluginConfig({
rawConfig: {
agents: {
claude: {
command: "npx -y @agentclientprotocol/claude-agent-acp@0.31.4 --permission-mode bypass",
},
},
},
workspaceDir: root,
});
const resolved = await prepareAcpxCodexAuthConfig({
pluginConfig,
stateDir,
resolveInstalledClaudeAcpBinPath: async () => path.join(root, "claude-agent-acp.js"),
});
expectClaudeWrapperCommand(resolved.agents.claude, generated.wrapperPath);
expect(resolved.agents.claude).not.toContain("npx -y @agentclientprotocol/claude-agent-acp");
expect(resolved.agents.claude).toContain("--permission-mode");
expect(resolved.agents.claude).toContain("bypass");
});
});
+34 -78
View File
@@ -5,6 +5,7 @@ import os from "node:os";
import path from "node:path";
import { promisify } from "node:util";
import { afterEach, describe, expect, it, vi } from "vitest";
import { OPENCLAW_CODEX_CONFIG_ARG } from "./codex-adapter.js";
import { prepareAcpxCodexAuthConfig } from "./codex-auth-bridge.js";
import { resolveAcpxPluginConfig } from "./config.js";
import { OPENCLAW_ACPX_LEASE_ID_ARG, OPENCLAW_GATEWAY_INSTANCE_ID_ARG } from "./process-lease.js";
@@ -151,10 +152,10 @@ describe("prepareAcpxCodexAuthConfig", () => {
const installedBinPath = path.join(
root,
"node_modules",
"@zed-industries",
"@agentclientprotocol",
"codex-acp",
"bin",
"codex-acp.js",
"dist",
"index.js",
);
process.env.OPENCLAW_AGENT_DIR = agentDir;
@@ -219,9 +220,9 @@ describe("prepareAcpxCodexAuthConfig", () => {
});
const wrapper = await fs.readFile(generated.wrapperPath, "utf8");
expect(wrapper).toContain('"@zed-industries/codex-acp@0.16.0"');
expect(wrapper).toContain('"@agentclientprotocol/codex-acp@1.1.2"');
expect(wrapper).toContain('"--", "codex-acp"');
expect(wrapper).not.toContain("@zed-industries/codex-acp@^0.11.1");
expect(wrapper).not.toContain("@zed-industries/codex-acp");
});
it("falls back to the patched Claude ACP package when the local adapter is unavailable", async () => {
@@ -261,8 +262,8 @@ describe("prepareAcpxCodexAuthConfig", () => {
});
const wrapper = await fs.readFile(generated.wrapperPath, "utf8");
expect(wrapper).toContain("@zed-industries/codex-acp");
expectWrapperToContainPathSuffix(wrapper, ["bin", "codex-acp.js"]);
expect(wrapper).toContain("@agentclientprotocol/codex-acp");
expectWrapperToContainPathSuffix(wrapper, ["dist", "index.js"]);
expect(wrapper).toContain("defaultArgs = [installedBinPath]");
});
@@ -326,14 +327,14 @@ describe("prepareAcpxCodexAuthConfig", () => {
expect(wrapper).toContain("defaultArgs = [installedBinPath]");
});
it("launches the locally installed Codex ACP bin with isolated CODEX_HOME", async () => {
it("launches maintained Codex ACP with isolated CODEX_HOME and model overrides", async () => {
const root = await makeTempDir();
const stateDir = path.join(root, "state");
const generated = generatedCodexPaths(stateDir);
const installedBinPath = path.join(root, "codex-acp-bin.js");
await fs.writeFile(
installedBinPath,
"console.log(JSON.stringify({ argv: process.argv.slice(2), codexHome: process.env.CODEX_HOME }));\n",
"console.log(JSON.stringify({ argv: process.argv.slice(2), codexConfig: process.env.CODEX_CONFIG, codexHome: process.env.CODEX_HOME }));\n",
"utf8",
);
const pluginConfig = resolveAcpxPluginConfig({
@@ -355,13 +356,36 @@ describe("prepareAcpxCodexAuthConfig", () => {
"lease-1",
"--openclaw-gateway-instance-id",
"gateway-1",
OPENCLAW_CODEX_CONFIG_ARG,
JSON.stringify({ model_providers: { custom: { wire_api: "responses" } } }),
OPENCLAW_CODEX_CONFIG_ARG,
JSON.stringify({ model: "gpt-5.6-sol", model_reasoning_effort: "medium" }),
],
{
cwd: root,
env: {
...process.env,
CODEX_CONFIG: JSON.stringify({
sandbox_mode: "workspace-write",
model_providers: { custom: { base_url: "https://example.test/v1" } },
}),
},
},
);
const launched = JSON.parse(stdout.trim()) as { argv?: unknown; codexHome?: unknown };
const launched = JSON.parse(stdout.trim()) as {
argv?: unknown;
codexConfig?: unknown;
codexHome?: unknown;
};
expect(launched.argv).toStrictEqual([]);
expect(JSON.parse(String(launched.codexConfig))).toEqual({
sandbox_mode: "workspace-write",
model_providers: {
custom: { base_url: "https://example.test/v1", wire_api: "responses" },
},
model: "gpt-5.6-sol",
model_reasoning_effort: "medium",
});
const expectedCodexHome = await fs.realpath(path.join(stateDir, "acpx", "codex-home"));
expect(path.resolve(String(launched.codexHome))).toBe(expectedCodexHome);
});
@@ -639,74 +663,6 @@ describe("prepareAcpxCodexAuthConfig", () => {
expect(isolatedConfig).not.toContain("SkyComputerUseClient");
});
it("normalizes an explicitly configured Codex ACP command to the local wrapper", async () => {
const root = await makeTempDir();
const sourceCodexHome = path.join(root, "source-codex");
const stateDir = path.join(root, "state");
const generated = generatedCodexPaths(stateDir);
await fs.mkdir(sourceCodexHome, { recursive: true });
await fs.writeFile(
path.join(sourceCodexHome, "config.toml"),
'notify = ["SkyComputerUseClient", "turn-ended"]\n',
);
process.env.CODEX_HOME = sourceCodexHome;
const pluginConfig = resolveAcpxPluginConfig({
rawConfig: {
agents: {
codex: {
command: "npx @zed-industries/codex-acp@0.12.0 -c 'model=\"gpt-5.4\"'",
},
},
},
workspaceDir: root,
});
const resolved = await prepareAcpxCodexAuthConfig({
pluginConfig,
stateDir,
resolveInstalledCodexAcpBinPath: async () => path.join(root, "codex-acp.js"),
});
expectCodexWrapperCommand(resolved.agents.codex, generated.wrapperPath);
expect(resolved.agents.codex).not.toContain("npx @zed-industries/codex-acp@0.12.0");
expect(resolved.agents.codex).toContain(quoteArg("-c"));
expect(resolved.agents.codex).toContain(quoteArg('model="gpt-5.4"'));
const isolatedConfig = await fs.readFile(generated.configPath, "utf8");
expect(isolatedConfig).not.toContain("notify");
expect(isolatedConfig).not.toContain("SkyComputerUseClient");
const wrapper = await fs.readFile(generated.wrapperPath, "utf8");
expect(wrapper).toContain("process.argv.slice(2)");
expect(wrapper).toContain("CODEX_HOME: codexHome");
expect(wrapper).not.toContain(sourceCodexHome);
});
it("normalizes an explicitly configured Claude ACP npx command to the local wrapper", async () => {
const root = await makeTempDir();
const stateDir = path.join(root, "state");
const generated = generatedClaudePaths(stateDir);
const pluginConfig = resolveAcpxPluginConfig({
rawConfig: {
agents: {
claude: {
command: "npx -y @agentclientprotocol/claude-agent-acp@0.31.4 --permission-mode bypass",
},
},
},
workspaceDir: root,
});
const resolved = await prepareAcpxCodexAuthConfig({
pluginConfig,
stateDir,
resolveInstalledClaudeAcpBinPath: async () => path.join(root, "claude-agent-acp.js"),
});
expectClaudeWrapperCommand(resolved.agents.claude, generated.wrapperPath);
expect(resolved.agents.claude).not.toContain("npx -y @agentclientprotocol/claude-agent-acp");
expect(resolved.agents.claude).toContain("--permission-mode");
expect(resolved.agents.claude).toContain("bypass");
});
it("captures Codex wrapper stderr in a stream-aware redacted per-lease log", async () => {
const { log, stateDir } = await captureGeneratedCodexWrapperStderr(
`const chunks = [
+216 -9
View File
@@ -8,6 +8,17 @@ import { createRequire } from "node:module";
import os from "node:os";
import path from "node:path";
import { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
import {
parse as parseToml,
stringify as stringifyToml,
type TomlTableWithoutBigInt,
} from "smol-toml";
import {
CODEX_ACP_BIN,
CODEX_ACP_PACKAGE,
LEGACY_CODEX_ACP_PACKAGE,
OPENCLAW_CODEX_CONFIG_ARG,
} from "./codex-adapter.js";
import {
extractTrustedCodexProjectPaths,
renderIsolatedCodexConfig,
@@ -21,8 +32,6 @@ import {
OPENCLAW_GATEWAY_INSTANCE_ID_ARG,
} from "./process-lease.js";
const CODEX_ACP_PACKAGE = "@zed-industries/codex-acp";
const CODEX_ACP_BIN = "codex-acp";
const CLAUDE_ACP_PACKAGE = "@agentclientprotocol/claude-agent-acp";
const CLAUDE_ACP_BIN = "claude-agent-acp";
const RUN_CONFIGURED_COMMAND_SENTINEL = "--openclaw-run-configured";
@@ -229,6 +238,8 @@ function buildAdapterWrapperScript(params: {
binName: string;
installedBinPath?: string;
envSetup: string;
envConfigSetup?: string;
openClawWrapperArgs?: string[];
stderrLogFileNamePrefix?: string;
}): string {
return `#!/usr/bin/env node
@@ -245,6 +256,7 @@ const stderrLogMaxChars = 256 * 1024;
const openClawWrapperArgs = new Set([
${quoteCommandPart(OPENCLAW_ACPX_LEASE_ID_ARG)},
${quoteCommandPart(OPENCLAW_GATEWAY_INSTANCE_ID_ARG)},
${(params.openClawWrapperArgs ?? []).map(quoteCommandPart).join(",\n ")}
]);
function readOpenClawWrapperArg(args, name) {
@@ -256,6 +268,21 @@ function readOpenClawWrapperArg(args, name) {
return typeof value === "string" && value.trim() ? value.trim() : undefined;
}
function readOpenClawWrapperArgs(args, name) {
const values = [];
for (let index = 0; index < args.length; index += 1) {
if (args[index] !== name) {
continue;
}
const value = args[index + 1];
if (typeof value === "string" && value.trim()) {
values.push(value.trim());
}
index += 1;
}
return values;
}
function safeDiagnosticFilePart(value) {
const sanitized = String(value || "").replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 120);
return sanitized || "pid-" + process.pid;
@@ -400,6 +427,7 @@ function stripOpenClawWrapperArgs(args) {
}
const rawConfiguredArgs = process.argv.slice(2);
${params.envConfigSetup ?? ""}
const stderrLogPath = resolveStderrLogPath(rawConfiguredArgs);
if (stderrLogPath) {
try {
@@ -556,6 +584,7 @@ function buildCodexAcpWrapperScript(installedBinPath?: string): string {
binName: CODEX_ACP_BIN,
installedBinPath,
stderrLogFileNamePrefix: "codex-acp-wrapper.stderr",
openClawWrapperArgs: [OPENCLAW_CODEX_CONFIG_ARG],
envSetup: `const codexHome = fileURLToPath(new URL("./codex-home/", import.meta.url));
const codexAuthPath = fileURLToPath(new URL("./codex-home/auth.json", import.meta.url));
const codexApiKey = (process.env.CODEX_API_KEY || process.env.OPENAI_API_KEY || "").trim();
@@ -590,6 +619,58 @@ const env = {
...process.env,
CODEX_HOME: codexHome,
};`,
envConfigSetup: `function isCodexConfigObject(value) {
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
}
function mergeCodexConfig(base, override) {
const merged = Object.assign(Object.create(null), base);
for (const [key, value] of Object.entries(override)) {
const existing = merged[key];
merged[key] =
isCodexConfigObject(existing) && isCodexConfigObject(value)
? mergeCodexConfig(existing, value)
: value;
}
return merged;
}
const openClawCodexConfigs = readOpenClawWrapperArgs(
rawConfiguredArgs,
${quoteCommandPart(OPENCLAW_CODEX_CONFIG_ARG)},
);
if (openClawCodexConfigs.length > 0) {
let existingCodexConfig = {};
if (typeof env.CODEX_CONFIG === "string" && env.CODEX_CONFIG.trim()) {
try {
const parsedCodexConfig = JSON.parse(env.CODEX_CONFIG);
if (!parsedCodexConfig || typeof parsedCodexConfig !== "object" || Array.isArray(parsedCodexConfig)) {
throw new Error("CODEX_CONFIG must be a JSON object");
}
existingCodexConfig = parsedCodexConfig;
} catch {
console.error("[openclaw] CODEX_CONFIG must be a valid JSON object");
process.exit(1);
}
}
for (const openClawCodexConfig of openClawCodexConfigs) {
try {
const parsedOpenClawCodexConfig = JSON.parse(openClawCodexConfig);
if (
!parsedOpenClawCodexConfig ||
typeof parsedOpenClawCodexConfig !== "object" ||
Array.isArray(parsedOpenClawCodexConfig)
) {
throw new Error("invalid OpenClaw Codex config");
}
existingCodexConfig = mergeCodexConfig(existingCodexConfig, parsedOpenClawCodexConfig);
} catch {
console.error("[openclaw] invalid generated Codex ACP startup config");
process.exit(1);
}
}
env.CODEX_CONFIG = JSON.stringify(existingCodexConfig);
}`,
});
}
@@ -726,14 +807,121 @@ function extractConfiguredAdapterArgs(params: {
return undefined;
}
function buildCodexAcpWrapperCommand(wrapperPath: string, configuredCommand?: string): string {
const configuredAdapterArgs = extractConfiguredAdapterArgs({
function isConfigRecord(value: unknown): value is Record<string, unknown> {
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
}
function mergeConfigRecords(
base: Record<string, unknown>,
override: Record<string, unknown>,
): Record<string, unknown> {
const merged: Record<string, unknown> = { ...base };
for (const [key, value] of Object.entries(override)) {
const existing = merged[key];
const nextValue =
isConfigRecord(existing) && isConfigRecord(value)
? mergeConfigRecords(existing, value)
: value;
Object.defineProperty(merged, key, {
value: nextValue,
configurable: true,
enumerable: true,
writable: true,
});
}
return merged;
}
function parseLegacyCodexConfigAssignment(assignment: string): Record<string, unknown> {
const separator = assignment.indexOf("=");
if (separator <= 0) {
throw new Error(`Invalid legacy Codex ACP config override: ${assignment}`);
}
const rawKey = assignment.slice(0, separator).trim();
const key = rawKey === "use_legacy_landlock" ? "features.use_legacy_landlock" : rawKey;
const rawValue = assignment.slice(separator + 1).trim();
try {
return parseToml(`${key} = ${rawValue}`) as Record<string, unknown>;
} catch {
const literal = rawValue.replace(/^["']+|["']+$/g, "");
return parseToml(`${key} = ${JSON.stringify(literal)}`) as Record<string, unknown>;
}
}
type LegacyCodexArgsMigration = {
config: Record<string, unknown>;
forwardedArgs: string[];
hadOverrides: boolean;
};
function migrateLegacyCodexArgs(args: string[]): LegacyCodexArgsMigration {
let config: Record<string, unknown> = {};
const forwardedArgs: string[] = [];
let hadOverrides = false;
for (let index = 0; index < args.length; index += 1) {
const arg = args[index] ?? "";
let assignment: string | undefined;
if (arg === "-c" || arg === "--config") {
assignment = args[(index += 1)];
} else if (arg.startsWith("--config=")) {
assignment = arg.slice("--config=".length);
} else if (arg.startsWith("-c=")) {
assignment = arg.slice("-c=".length);
} else if (arg.startsWith("-c") && arg.length > 2) {
assignment = arg.slice(2);
} else {
forwardedArgs.push(arg);
continue;
}
if (!assignment) {
throw new Error(`Missing value for legacy Codex ACP option ${arg}`);
}
hadOverrides = true;
config = mergeConfigRecords(config, parseLegacyCodexConfigAssignment(assignment));
}
return { config, forwardedArgs, hadOverrides };
}
type CodexAdapterLaunch = {
args: string[];
migratedConfig?: Record<string, unknown>;
};
function resolveCodexAdapterLaunch(configuredCommand?: string): CodexAdapterLaunch | undefined {
const legacyAdapterArgs = extractConfiguredAdapterArgs({
configuredCommand,
packageName: LEGACY_CODEX_ACP_PACKAGE,
binName: CODEX_ACP_BIN,
});
if (legacyAdapterArgs) {
const migration = migrateLegacyCodexArgs(legacyAdapterArgs);
return {
args: [
...(migration.hadOverrides
? [OPENCLAW_CODEX_CONFIG_ARG, JSON.stringify(migration.config)]
: []),
...migration.forwardedArgs,
],
...(migration.hadOverrides ? { migratedConfig: migration.config } : {}),
};
}
const maintainedAdapterArgs = extractConfiguredAdapterArgs({
configuredCommand,
packageName: CODEX_ACP_PACKAGE,
binName: CODEX_ACP_BIN,
});
if (configuredAdapterArgs) {
return buildWrapperCommand(wrapperPath, configuredAdapterArgs);
if (!maintainedAdapterArgs) {
return undefined;
}
// The maintained adapter owns its CLI subcommands and forwarded Codex flags.
// Only the Zed package and bare legacy forms reach the migration branch above.
return { args: maintainedAdapterArgs };
}
function buildCodexAcpWrapperCommand(wrapperPath: string, configuredCommand?: string): string {
const launch = resolveCodexAdapterLaunch(configuredCommand);
if (launch) {
return buildWrapperCommand(wrapperPath, launch.args);
}
return buildWrapperCommand(wrapperPath, [
RUN_CONFIGURED_COMMAND_SENTINEL,
@@ -741,6 +929,20 @@ function buildCodexAcpWrapperCommand(wrapperPath: string, configuredCommand?: st
]);
}
async function persistMigratedCodexMcpConfig(params: {
codexHome: string;
migratedConfig: Record<string, unknown> | undefined;
}): Promise<void> {
const mcpServers = params.migratedConfig?.mcp_servers;
if (!isConfigRecord(mcpServers)) {
return;
}
const configPath = path.join(params.codexHome, "config.toml");
const current = parseToml(await fs.readFile(configPath, "utf8")) as Record<string, unknown>;
const merged = mergeConfigRecords(current, { mcp_servers: mcpServers });
await fs.writeFile(configPath, stringifyToml(merged as TomlTableWithoutBigInt), "utf8");
}
function buildClaudeAcpWrapperCommand(wrapperPath: string, configuredCommand?: string): string {
const configuredAdapterArgs = extractConfiguredAdapterArgs({
configuredCommand,
@@ -763,10 +965,17 @@ export async function prepareAcpxCodexAuthConfig(params: {
}): Promise<ResolvedAcpxPluginConfig> {
void params.logger;
const codexBaseDir = path.join(params.stateDir, "acpx");
await prepareIsolatedCodexHome({
const configuredCodexCommand = params.pluginConfig.agents.codex;
const configuredClaudeCommand = params.pluginConfig.agents.claude;
const codexLaunch = resolveCodexAdapterLaunch(configuredCodexCommand);
const codexHome = await prepareIsolatedCodexHome({
baseDir: codexBaseDir,
workspaceDir: params.pluginConfig.cwd,
});
await persistMigratedCodexMcpConfig({
codexHome,
migratedConfig: codexLaunch?.migratedConfig,
});
const installedCodexBinPath = await (
params.resolveInstalledCodexAcpBinPath ?? resolveInstalledCodexAcpBinPath
)();
@@ -775,8 +984,6 @@ export async function prepareAcpxCodexAuthConfig(params: {
)();
const wrapperPath = await writeCodexAcpWrapper(codexBaseDir, installedCodexBinPath);
const claudeWrapperPath = await writeClaudeAcpWrapper(codexBaseDir, installedClaudeBinPath);
const configuredCodexCommand = params.pluginConfig.agents.codex;
const configuredClaudeCommand = params.pluginConfig.agents.claude;
return {
...params.pluginConfig,
+2 -1
View File
@@ -15,7 +15,8 @@ describe("acpx package manifest", () => {
it("keeps runtime dependencies in the package manifest", () => {
expect(packageJson.dependencies?.acpx).toBeTypeOf("string");
expect(packageJson.dependencies?.acpx).not.toBe("");
expect(packageJson.dependencies?.["@zed-industries/codex-acp"]).toBe("0.16.0");
expect(packageJson.dependencies?.["@agentclientprotocol/codex-acp"]).toBe("1.1.2");
expect(packageJson.dependencies?.["@zed-industries/codex-acp"]).toBeUndefined();
expect(packageJson.dependencies?.["@agentclientprotocol/claude-agent-acp"]).toBe("0.55.0");
expect(packageJson.devDependencies?.["@agentclientprotocol/claude-agent-acp"]).toBeUndefined();
});
+33 -2
View File
@@ -13,10 +13,18 @@ const CODEX_WRAPPER_COMMAND = `node ${WRAPPER_ROOT}/codex-acp-wrapper.mjs`;
const CODEX_WRAPPER_COMMAND_WITH_LEASE = `${CODEX_WRAPPER_COMMAND} ${OPENCLAW_ACPX_LEASE_ID_ARG} lease-1 ${OPENCLAW_GATEWAY_INSTANCE_ID_ARG} gateway-1`;
const CLAUDE_WRAPPER_COMMAND = `node ${WRAPPER_ROOT}/claude-agent-acp-wrapper.mjs`;
const PLUGIN_DEPS_CODEX_COMMAND =
"node /tmp/openclaw/plugin-runtime-deps/node_modules/@zed-industries/codex-acp/bin/codex-acp.js";
"node /tmp/openclaw/plugin-runtime-deps/node_modules/@agentclientprotocol/codex-acp/dist/index.js";
const PLUGIN_DEPS_CODEX_APP_SERVER_COMMAND =
"node /tmp/openclaw/plugin-runtime-deps/node_modules/@openai/codex/bin/codex.js app-server";
const PLUGIN_DEPS_CODEX_PLATFORM_COMMAND =
"/tmp/openclaw/plugin-runtime-deps/node_modules/@openai/codex-linux-x64/vendor/codex app-server";
const LOCAL_NODE_MODULES_CODEX_COMMAND = `node ${path.resolve(
"node_modules/@zed-industries/codex-acp/bin/codex-acp.js",
"node_modules/@agentclientprotocol/codex-acp/dist/index.js",
)}`;
const LOCAL_CODEX_APP_SERVER_COMMAND = `node ${path.resolve(
"node_modules/@openai/codex/bin/codex.js",
)} app-server`;
// Legacy adapter subprocesses remain cleanup-owned during upgrades.
const LOCAL_NODE_MODULES_CODEX_PLATFORM_COMMAND = path.resolve(
"node_modules/@zed-industries/codex-acp-linux-x64/bin/codex-acp",
);
@@ -279,6 +287,29 @@ describe("process reaper", () => {
).toEqual([501, 500]);
});
it("reaps packaged Codex app-server orphans without claiming native plugin processes", async () => {
const { deps, killed } = cleanupDeps([
{ pid: 510, ppid: 1, command: PLUGIN_DEPS_CODEX_APP_SERVER_COMMAND },
{ pid: 511, ppid: 510, command: PLUGIN_DEPS_CODEX_PLATFORM_COMMAND },
{ pid: 512, ppid: 1, command: LOCAL_CODEX_APP_SERVER_COMMAND },
]);
const result = await reapStaleOpenClawOwnedAcpxOrphans({
wrapperRoot: WRAPPER_ROOT,
deps,
});
expect(result.skippedReason).toBeUndefined();
expect(result.inspectedPids).toEqual([510, 511]);
expect(
collectMatching(
killed,
(entry) => entry.signal === "SIGTERM",
(entry) => entry.pid,
),
).toEqual([511, 510]);
});
it("keeps startup scans quiet when process listing is unavailable", async () => {
const result = await reapStaleOpenClawOwnedAcpxOrphans({
wrapperRoot: WRAPPER_ROOT,
+17 -1
View File
@@ -5,6 +5,7 @@
import { createRequire } from "node:module";
import path from "node:path";
import { runExec } from "openclaw/plugin-sdk/process-runtime";
import { CODEX_ACP_PACKAGE, LEGACY_CODEX_ACP_PACKAGE } from "./codex-adapter.js";
import { splitCommandParts } from "./command-line.js";
import { resolveAcpxPluginRoot } from "./config.js";
import { OPENCLAW_ACPX_LEASE_ID_ARG, OPENCLAW_GATEWAY_INSTANCE_ID_ARG } from "./process-lease.js";
@@ -16,7 +17,10 @@ const GENERATED_WRAPPER_BASENAMES = new Set([
]);
const OPENCLAW_PLUGIN_DEPS_MARKER = "/plugin-runtime-deps/";
const OWNED_ACP_PACKAGE_NAMES = [
"@zed-industries/codex-acp",
CODEX_ACP_PACKAGE,
// Shipped Zed adapter processes can survive a gateway upgrade. Keep cleanup
// recognition until their OpenClaw-owned wrapper/process tree is gone.
LEGACY_CODEX_ACP_PACKAGE,
"@zed-industries/codex-acp-darwin-arm64",
"@zed-industries/codex-acp-darwin-x64",
"@zed-industries/codex-acp-linux-arm64",
@@ -26,8 +30,20 @@ const OWNED_ACP_PACKAGE_NAMES = [
"@agentclientprotocol/claude-agent-acp",
"acpx",
];
const PLUGIN_DEPS_CODEX_PACKAGE_NAMES = [
"@openai/codex",
"@openai/codex-darwin-arm64",
"@openai/codex-darwin-x64",
"@openai/codex-linux-arm64",
"@openai/codex-linux-x64",
"@openai/codex-win32-arm64",
"@openai/codex-win32-x64",
];
// Codex app-server is also owned by the native Codex plugin. Recognize its
// package only inside ACPX's isolated plugin-runtime-deps tree.
const ACP_PACKAGE_MARKERS = [
...OWNED_ACP_PACKAGE_NAMES.map((packageName) => `/node_modules/${packageName}/`),
...PLUGIN_DEPS_CODEX_PACKAGE_NAMES.map((packageName) => `/node_modules/${packageName}/`),
"/acpx/dist/",
];
+21 -12
View File
@@ -11,6 +11,7 @@ import {
type AcpRuntimeEvent,
type AcpRuntimeTurn,
} from "../runtime-api.js";
import { OPENCLAW_CODEX_CONFIG_ARG } from "./codex-adapter.js";
import { OPENCLAW_ACPX_LEASE_ID_ARG, OPENCLAW_GATEWAY_INSTANCE_ID_ARG } from "./process-lease.js";
import { AcpxRuntime, testing, type AcpSessionStore } from "./runtime.js";
@@ -21,11 +22,11 @@ type TestSessionStore = {
const DOCUMENTED_OPENCLAW_BRIDGE_COMMAND =
"env OPENCLAW_HIDE_BANNER=1 OPENCLAW_SUPPRESS_NOTES=1 openclaw acp --url ws://127.0.0.1:18789 --token-file ~/.openclaw/gateway.token --session agent:main:main";
const CODEX_ACP_COMMAND = "npx @zed-industries/codex-acp@0.13.0";
const CODEX_ACP_COMMAND = "npx @agentclientprotocol/codex-acp@1.1.2";
const CODEX_ACP_WRAPPER_COMMAND = `node "/tmp/openclaw/acpx/codex-acp-wrapper.mjs"`;
const CODEX_ACP_WRAPPER_COMMAND_WITH_LEASE = `${CODEX_ACP_WRAPPER_COMMAND} ${OPENCLAW_ACPX_LEASE_ID_ARG} lease-close ${OPENCLAW_GATEWAY_INSTANCE_ID_ARG} gateway-test`;
const LOCAL_NODE_MODULES_CODEX_COMMAND = `node "${path.resolve(
"node_modules/@zed-industries/codex-acp/bin/codex-acp.js",
"node_modules/@agentclientprotocol/codex-acp/dist/index.js",
)}"`;
function makeRuntime(
@@ -938,7 +939,7 @@ describe("AcpxRuntime fresh reset wrapper", () => {
reasoningEffort: "medium",
}),
).toBe(
"npx @zed-industries/codex-acp@0.13.0 -c model=gpt-5.4 -c model_reasoning_effort=medium",
`npx @agentclientprotocol/codex-acp@1.1.2 ${OPENCLAW_CODEX_CONFIG_ARG} '{"model":"gpt-5.4","model_reasoning_effort":"medium"}'`,
);
expect(testing.isCodexAcpCommand("openclaw acp")).toBe(false);
});
@@ -976,7 +977,7 @@ describe("AcpxRuntime fresh reset wrapper", () => {
});
});
it("maps explicit Codex ACP thinking to startup reasoning effort", async () => {
it("passes gpt-5.6-sol and medium as separate Codex ACP startup controls", async () => {
const baseStore: TestSessionStore = {
load: vi.fn(async () => undefined),
save: vi.fn(async () => {}),
@@ -997,18 +998,26 @@ describe("AcpxRuntime fresh reset wrapper", () => {
sessionKey: "agent:codex:acp:test",
agent: "codex",
mode: "persistent",
model: "openai/gpt-5.4",
thinking: "x-high",
model: "openai/gpt-5.6-sol",
thinking: "medium",
});
expect(readFirstEnsureSessionInput(ensure)).toEqual({
const ensureInput = readFirstEnsureSessionInput(ensure);
expect(ensureInput).toEqual({
sessionKey: "agent:codex:acp:test",
agent: "codex",
mode: "persistent",
model: "gpt-5.4",
thinking: "x-high",
sessionOptions: { model: "gpt-5.4" },
model: "gpt-5.6-sol",
thinking: "medium",
sessionOptions: { model: "gpt-5.6-sol" },
});
expect(JSON.stringify(ensureInput)).not.toContain("gpt-5.6-sol/medium");
expect(
testing.appendCodexAcpConfigOverrides(CODEX_ACP_WRAPPER_COMMAND, {
model: "gpt-5.6-sol",
reasoningEffort: "medium",
}),
).not.toContain("gpt-5.6-sol/medium");
});
it("normalizes Codex ACP model config controls to adapter ids", async () => {
@@ -1293,7 +1302,7 @@ describe("AcpxRuntime fresh reset wrapper", () => {
),
).toBe(true);
expect(testing.isClaudeAcpCommand("openclaw acp")).toBe(false);
expect(testing.isClaudeAcpCommand("npx @zed-industries/codex-acp")).toBe(false);
expect(testing.isClaudeAcpCommand("npx @agentclientprotocol/codex-acp")).toBe(false);
});
it("keeps stale persistent loads hidden until a fresh record is saved", async () => {
@@ -1427,7 +1436,7 @@ describe("AcpxRuntime fresh reset wrapper", () => {
pid: 901,
ppid: 900,
command:
"node /tmp/openclaw/plugin-runtime-deps/node_modules/@zed-industries/codex-acp/bin/codex-acp.js",
"node /tmp/openclaw/plugin-runtime-deps/node_modules/@agentclientprotocol/codex-acp/dist/index.js",
},
]),
killProcess: vi.fn((pid, signal) => {
+8 -7
View File
@@ -29,6 +29,7 @@ import { redactSensitiveText } from "openclaw/plugin-sdk/security-runtime";
import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
import { sliceUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
import { AcpRuntimeError, type AcpRuntime, type AcpRuntimeErrorCode } from "../runtime-api.js";
import { CODEX_ACP_PACKAGE, OPENCLAW_CODEX_CONFIG_ARG } from "./codex-adapter.js";
import { splitCommandParts } from "./command-line.js";
import {
createAcpxProcessLeaseId,
@@ -472,7 +473,7 @@ function isOpenClawBridgeCommand(command: string | undefined): boolean {
function isCodexAcpCommand(command: string | undefined): boolean {
return isAcpCommand(command, {
packageName: "@zed-industries/codex-acp",
packageName: CODEX_ACP_PACKAGE,
executableName: "codex-acp",
});
}
@@ -619,14 +620,14 @@ function quoteShellArg(value: string): string {
}
function appendCodexAcpConfigOverrides(command: string, override: CodexAcpModelOverride): string {
const configArgs = override.model ? [`model=${override.model}`] : [];
if (override.reasoningEffort) {
configArgs.push(`model_reasoning_effort=${override.reasoningEffort}`);
}
if (configArgs.length === 0) {
const config = {
...(override.model ? { model: override.model } : {}),
...(override.reasoningEffort ? { model_reasoning_effort: override.reasoningEffort } : {}),
};
if (Object.keys(config).length === 0) {
return command;
}
return `${command} ${configArgs.map((arg) => `-c ${quoteShellArg(arg)}`).join(" ")}`;
return `${command} ${OPENCLAW_CODEX_CONFIG_ARG} ${quoteShellArg(JSON.stringify(config))}`;
}
function createModelScopedAgentRegistry(params: {
+68 -77
View File
@@ -360,12 +360,15 @@ importers:
'@agentclientprotocol/claude-agent-acp':
specifier: 0.55.0
version: 0.55.0(@anthropic-ai/sdk@0.109.1(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))
'@zed-industries/codex-acp':
specifier: 0.16.0
version: 0.16.0
'@agentclientprotocol/codex-acp':
specifier: 1.1.2
version: 1.1.2
acpx:
specifier: 0.11.2
version: 0.11.2
smol-toml:
specifier: 1.7.0
version: 1.7.0
zod:
specifier: 4.4.3
version: 4.4.3
@@ -2319,6 +2322,10 @@ packages:
engines: {node: '>=22'}
hasBin: true
'@agentclientprotocol/codex-acp@1.1.2':
resolution: {integrity: sha512-qE/R1WdqJJ9OFHsHGvbmVmS2j9iCMZzpWT3g2XIViXrGHu1fLOALLINBIlW+WzKDllCh131aB6cqcIWSt0otbw==}
hasBin: true
'@agentclientprotocol/sdk@0.28.1':
resolution: {integrity: sha512-Z2Frs6YtPhnZZ+XwFXyQkRDXY0fn8FjCalEs0W4yUhQnY4TztmNq0/RnfzWdFN3vqT3h0jTz5klzYbZHGxCDyQ==}
peerDependencies:
@@ -2329,6 +2336,11 @@ packages:
peerDependencies:
zod: ^3.25.0 || ^4.0.0
'@agentclientprotocol/sdk@1.2.1':
resolution: {integrity: sha512-jwYUdOQR7tc+Zfch53VL4JJyUNK/46q03uUTYb+PjECsmnNl94XFXOfYLJ8RBpMNidXd1rpOAVgb0vqD98xImA==}
peerDependencies:
zod: ^3.25.0 || ^4.0.0
'@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.198':
resolution: {integrity: sha512-ZmiAybQKIKcP1qEAE/vfXvfxtKxG9CnJn98QTXC5Zxiwuy7Mllx2ALXh9dfmsf0V87CGEodlZQmMgUJotNIsUw==}
cpu: [arm64]
@@ -4964,53 +4976,6 @@ packages:
'@wasm-audio-decoders/opus-ml@0.0.2':
resolution: {integrity: sha512-58rWEqDGg+CKCyEeKm2KoxxSwTWtHh/NLTW9ObR4K8CGF6VwuuGudEI1CtniS/oSRmL1nJq/eh8MKARiluw4DQ==}
'@zed-industries/codex-acp-darwin-arm64@0.16.0':
resolution: {integrity: sha512-2AmbWsc/+Mpn6U8UOIlPLvgwGsGOr/LFpgcvrnjcCT9V1yY92MLrqzjMX82+VjTrRLRuXvc25SB5Z1++4Pw29g==}
cpu: [arm64]
os: [darwin]
deprecated: This package has been replaced by @agentclientprotocol/codex-acp. Please migrate to continue receiving updates.
hasBin: true
'@zed-industries/codex-acp-darwin-x64@0.16.0':
resolution: {integrity: sha512-QCWggk0s4GTPLCR7eznyx29Dls4gzUKvp4MjZ4nzPX5gDL/02PGY+oCV1WsQOsnzWRK0RxM+GlK19rG1qzqplw==}
cpu: [x64]
os: [darwin]
deprecated: This package has been replaced by @agentclientprotocol/codex-acp. Please migrate to continue receiving updates.
hasBin: true
'@zed-industries/codex-acp-linux-arm64@0.16.0':
resolution: {integrity: sha512-8HaZGWVPVs1N6yqImLCKlnlcYTYc9BMCEhaVJk0ON9lyofhK9mOBBAHQndKC4Scqq5JLUHQIOyb8+jwHUe3hSQ==}
cpu: [arm64]
os: [linux]
deprecated: This package has been replaced by @agentclientprotocol/codex-acp. Please migrate to continue receiving updates.
hasBin: true
'@zed-industries/codex-acp-linux-x64@0.16.0':
resolution: {integrity: sha512-xs5zZBLpJuciEbZNx6ZSNL0qCa9h3i/zWpj40sp6QtF+L4Ow/7qzHdBzboGhHdcz1jrLedfZeRFDA2Elj8TLMA==}
cpu: [x64]
os: [linux]
deprecated: This package has been replaced by @agentclientprotocol/codex-acp. Please migrate to continue receiving updates.
hasBin: true
'@zed-industries/codex-acp-win32-arm64@0.16.0':
resolution: {integrity: sha512-4V3pDJvEyNkgVqWqlm0bLYEZ8liGXXp8InuHzCy5cgr+SFur6BuasA29tisN8NUrLus/ZvMhXCrOsNKurYAWQw==}
cpu: [arm64]
os: [win32]
deprecated: This package has been replaced by @agentclientprotocol/codex-acp. Please migrate to continue receiving updates.
hasBin: true
'@zed-industries/codex-acp-win32-x64@0.16.0':
resolution: {integrity: sha512-ZriI/ay5E3DCg8s22LZykIRI2XzQL6sZg/t81K+6qc86ldscaSWQSOT6KSnRcv31QJCMfBlFxMj22pZiGSVjQA==}
cpu: [x64]
os: [win32]
deprecated: This package has been replaced by @agentclientprotocol/codex-acp. Please migrate to continue receiving updates.
hasBin: true
'@zed-industries/codex-acp@0.16.0':
resolution: {integrity: sha512-XKzqztT5R8Wg1BVFnk6/U4JVx5GNUaZgxpf9gP2Cw6BsknvJWh3aefcAGZQljgdMivRqczjNKYL4F6H65dc5vA==}
deprecated: This package has been replaced by @agentclientprotocol/codex-acp. Please migrate to continue receiving updates.
hasBin: true
abort-controller@3.0.0:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
@@ -6179,6 +6144,10 @@ packages:
is-hexadecimal@2.0.1:
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
is-in-ssh@1.0.0:
resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==}
engines: {node: '>=20'}
is-inside-container@1.0.0:
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
engines: {node: '>=14.16'}
@@ -6978,6 +6947,10 @@ packages:
resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==}
engines: {node: '>=18'}
open@11.0.0:
resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==}
engines: {node: '>=20'}
openai@6.45.0:
resolution: {integrity: sha512-5DQVNErssk0afNpTTHUm/qZPU4iKR9OYdNid8Ib4puq4gHNNvGWZht2zY4h9a8JMF949Ik6m8gQutllVPbjdnw==}
hasBin: true
@@ -7186,6 +7159,10 @@ packages:
resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==}
engines: {node: ^10 || ^12 || >=14}
powershell-utils@0.1.0:
resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
engines: {node: '>=20'}
pretty-bytes@6.1.1:
resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
engines: {node: ^14.13.1 || >=16.0.0}
@@ -8164,6 +8141,10 @@ packages:
resolution: {integrity: sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ==}
engines: {node: '>=14.0.0'}
vscode-jsonrpc@9.0.1:
resolution: {integrity: sha512-rfuA6T75H6m5EkbhtEPzre9pT0HPcDI2MMy4+nPFIBks5J8JBAUHD4tRYSgaBOijIEC7SRkC1kKyXTLqbmh9jw==}
engines: {node: '>=14.0.0'}
w3c-keyname@2.2.8:
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
@@ -8260,6 +8241,10 @@ packages:
resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==}
engines: {node: '>=18'}
wsl-utils@0.3.1:
resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==}
engines: {node: '>=20'}
xml-name-validator@5.0.0:
resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
engines: {node: '>=18'}
@@ -8357,6 +8342,15 @@ snapshots:
- '@anthropic-ai/sdk'
- '@modelcontextprotocol/sdk'
'@agentclientprotocol/codex-acp@1.1.2':
dependencies:
'@agentclientprotocol/sdk': 1.2.1(zod@4.4.3)
'@openai/codex': 0.144.4
diff: 9.0.0
open: 11.0.0
vscode-jsonrpc: 9.0.1
zod: 4.4.3
'@agentclientprotocol/sdk@0.28.1(zod@4.4.3)':
dependencies:
zod: 4.4.3
@@ -8365,6 +8359,10 @@ snapshots:
dependencies:
zod: 4.4.3
'@agentclientprotocol/sdk@1.2.1(zod@4.4.3)':
dependencies:
zod: 4.4.3
'@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.198':
optional: true
@@ -11324,33 +11322,6 @@ snapshots:
dependencies:
'@wasm-audio-decoders/common': 9.0.7
'@zed-industries/codex-acp-darwin-arm64@0.16.0':
optional: true
'@zed-industries/codex-acp-darwin-x64@0.16.0':
optional: true
'@zed-industries/codex-acp-linux-arm64@0.16.0':
optional: true
'@zed-industries/codex-acp-linux-x64@0.16.0':
optional: true
'@zed-industries/codex-acp-win32-arm64@0.16.0':
optional: true
'@zed-industries/codex-acp-win32-x64@0.16.0':
optional: true
'@zed-industries/codex-acp@0.16.0':
optionalDependencies:
'@zed-industries/codex-acp-darwin-arm64': 0.16.0
'@zed-industries/codex-acp-darwin-x64': 0.16.0
'@zed-industries/codex-acp-linux-arm64': 0.16.0
'@zed-industries/codex-acp-linux-x64': 0.16.0
'@zed-industries/codex-acp-win32-arm64': 0.16.0
'@zed-industries/codex-acp-win32-x64': 0.16.0
abort-controller@3.0.0:
dependencies:
event-target-shim: 5.0.1
@@ -12621,6 +12592,8 @@ snapshots:
is-hexadecimal@2.0.1: {}
is-in-ssh@1.0.0: {}
is-inside-container@1.0.0:
dependencies:
is-docker: 3.0.0
@@ -13661,6 +13634,15 @@ snapshots:
is-inside-container: 1.0.0
wsl-utils: 0.1.0
open@11.0.0:
dependencies:
default-browser: 5.5.0
define-lazy-prop: 3.0.0
is-in-ssh: 1.0.0
is-inside-container: 1.0.0
powershell-utils: 0.1.0
wsl-utils: 0.3.1
openai@6.45.0(@aws-sdk/credential-provider-node@3.972.61)(@smithy/hash-node@4.4.5)(@smithy/signature-v4@5.6.1)(ws@8.21.0)(zod@4.4.3):
optionalDependencies:
'@aws-sdk/credential-provider-node': 3.972.61
@@ -13878,6 +13860,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
powershell-utils@0.1.0: {}
pretty-bytes@6.1.1:
optional: true
@@ -14941,6 +14925,8 @@ snapshots:
vscode-jsonrpc@8.2.1: {}
vscode-jsonrpc@9.0.1: {}
w3c-keyname@2.2.8: {}
w3c-xmlserializer@5.0.0:
@@ -15029,6 +15015,11 @@ snapshots:
dependencies:
is-wsl: 3.1.1
wsl-utils@0.3.1:
dependencies:
is-wsl: 3.1.1
powershell-utils: 0.1.0
xml-name-validator@5.0.0: {}
xmlchars@2.2.0: {}