mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
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:
committed by
GitHub
parent
c46cc1e2d4
commit
0fa77124e9
@@ -200,7 +200,7 @@ const bundledPluginIgnoredRuntimeDependencies = [
|
||||
"@openai/codex",
|
||||
"@pierre/theme",
|
||||
"@tloncorp/tlon-skill",
|
||||
"@zed-industries/codex-acp",
|
||||
"@agentclientprotocol/codex-acp",
|
||||
"jiti",
|
||||
"json5",
|
||||
"lit",
|
||||
|
||||
Generated
+355
-114
@@ -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",
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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/",
|
||||
];
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Generated
+68
-77
@@ -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: {}
|
||||
|
||||
Reference in New Issue
Block a user