diff --git a/config/knip.config.ts b/config/knip.config.ts index 3cd378a4ecca..a798831629fe 100644 --- a/config/knip.config.ts +++ b/config/knip.config.ts @@ -200,7 +200,7 @@ const bundledPluginIgnoredRuntimeDependencies = [ "@openai/codex", "@pierre/theme", "@tloncorp/tlon-skill", - "@zed-industries/codex-acp", + "@agentclientprotocol/codex-acp", "jiti", "json5", "lit", diff --git a/extensions/acpx/npm-shrinkwrap.json b/extensions/acpx/npm-shrinkwrap.json index 1fb2d847d70c..a3017484d370 100644 --- a/extensions/acpx/npm-shrinkwrap.json +++ b/extensions/acpx/npm-shrinkwrap.json @@ -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", diff --git a/extensions/acpx/package.json b/extensions/acpx/package.json index 38eb6365b263..c9e18f1fbb1e 100644 --- a/extensions/acpx/package.json +++ b/extensions/acpx/package.json @@ -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": { diff --git a/extensions/acpx/skills/acp-router/SKILL.md b/extensions/acpx/skills/acp-router/SKILL.md index 262d12953041..0d04625afd5f 100644 --- a/extensions/acpx/skills/acp-router/SKILL.md +++ b/extensions/acpx/skills/acp-router/SKILL.md @@ -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` diff --git a/extensions/acpx/src/codex-adapter.ts b/extensions/acpx/src/codex-adapter.ts new file mode 100644 index 000000000000..d831c0665aef --- /dev/null +++ b/extensions/acpx/src/codex-adapter.ts @@ -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"; diff --git a/extensions/acpx/src/codex-auth-bridge.migration.test.ts b/extensions/acpx/src/codex-auth-bridge.migration.test.ts new file mode 100644 index 000000000000..5e16f3ce3945 --- /dev/null +++ b/extensions/acpx/src/codex-auth-bridge.migration.test.ts @@ -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 { + 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"); + }); +}); diff --git a/extensions/acpx/src/codex-auth-bridge.test.ts b/extensions/acpx/src/codex-auth-bridge.test.ts index 244e84dd4493..e982610274ac 100644 --- a/extensions/acpx/src/codex-auth-bridge.test.ts +++ b/extensions/acpx/src/codex-auth-bridge.test.ts @@ -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 = [ diff --git a/extensions/acpx/src/codex-auth-bridge.ts b/extensions/acpx/src/codex-auth-bridge.ts index 3d1682f03d0a..84706e2bff6d 100644 --- a/extensions/acpx/src/codex-auth-bridge.ts +++ b/extensions/acpx/src/codex-auth-bridge.ts @@ -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 { + return Boolean(value) && typeof value === "object" && !Array.isArray(value); +} + +function mergeConfigRecords( + base: Record, + override: Record, +): Record { + const merged: Record = { ...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 { + 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; + } catch { + const literal = rawValue.replace(/^["']+|["']+$/g, ""); + return parseToml(`${key} = ${JSON.stringify(literal)}`) as Record; + } +} + +type LegacyCodexArgsMigration = { + config: Record; + forwardedArgs: string[]; + hadOverrides: boolean; +}; + +function migrateLegacyCodexArgs(args: string[]): LegacyCodexArgsMigration { + let config: Record = {}; + 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; +}; + +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 | undefined; +}): Promise { + 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; + 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 { 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, diff --git a/extensions/acpx/src/manifest.test.ts b/extensions/acpx/src/manifest.test.ts index ffbc64cfe324..a1a771245cf5 100644 --- a/extensions/acpx/src/manifest.test.ts +++ b/extensions/acpx/src/manifest.test.ts @@ -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(); }); diff --git a/extensions/acpx/src/process-reaper.test.ts b/extensions/acpx/src/process-reaper.test.ts index a022cfb8d29d..345b2f6b3880 100644 --- a/extensions/acpx/src/process-reaper.test.ts +++ b/extensions/acpx/src/process-reaper.test.ts @@ -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, diff --git a/extensions/acpx/src/process-reaper.ts b/extensions/acpx/src/process-reaper.ts index d5cd55279e97..d7f915641c12 100644 --- a/extensions/acpx/src/process-reaper.ts +++ b/extensions/acpx/src/process-reaper.ts @@ -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/", ]; diff --git a/extensions/acpx/src/runtime.test.ts b/extensions/acpx/src/runtime.test.ts index 96b2e9496057..6f0fb6204eaf 100644 --- a/extensions/acpx/src/runtime.test.ts +++ b/extensions/acpx/src/runtime.test.ts @@ -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) => { diff --git a/extensions/acpx/src/runtime.ts b/extensions/acpx/src/runtime.ts index 007688f0d25c..45fa648078c3 100644 --- a/extensions/acpx/src/runtime.ts +++ b/extensions/acpx/src/runtime.ts @@ -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: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 712b97c402ef..0a928f556422 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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: {}