mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-09 00:45:47 +00:00
chore: update dependencies and migrate major contracts (#112963)
* build(deps): complete latest dependency migrations * fix(deps): satisfy updated dependency types * fix(deps): hold incompatible build tooling * fix(deps): preserve portable tooling contracts * build(deps): allow reviewed fresh transitive releases * fix(deps): repair major upgrade validation * build(deps): regenerate current dependency graph * fix(logging): keep tslog adapter type private * fix(agents): narrow grep subprocess handle * fix(codex): prefer pinned managed binary * fix(codex): fence managed native provenance * build(deps): align codex ACP with managed harness * fix(slack): use socket-mode Undici runtime * fix(slack): detect cross-runtime responses * fix(slack): bridge package-owned fetch types * fix(deps): retain tslog v4 JSON contract * build(plugin-sdk): refresh logging API manifest
This commit is contained in:
parent
9fc1f0b96b
commit
3b7b2a2a1f
64 changed files with 1563 additions and 948 deletions
13
.github/workflows/crabbox-hydrate.yml
vendored
13
.github/workflows/crabbox-hydrate.yml
vendored
|
|
@ -272,11 +272,17 @@ jobs:
|
|||
if ! docker buildx version >/dev/null 2>&1; then
|
||||
arch="$(uname -m)"
|
||||
case "$arch" in
|
||||
aarch64|arm64) buildx_arch=arm64 ;;
|
||||
x86_64|amd64) buildx_arch=amd64 ;;
|
||||
aarch64|arm64)
|
||||
buildx_arch=arm64
|
||||
buildx_sha256=c4248d6cbc4a619a7e0b4609c11e509ad4ac0b475e1c64817c0ac20c5d90c766
|
||||
;;
|
||||
x86_64|amd64)
|
||||
buildx_arch=amd64
|
||||
buildx_sha256=d41ece72044243b4f58b343441ae37446d9c29a7d6b5e11c61847bbcf8f7dfda
|
||||
;;
|
||||
*) echo "unsupported buildx arch: $arch" >&2; exit 2 ;;
|
||||
esac
|
||||
buildx_version="${DOCKER_BUILDX_VERSION:-v0.15.1}"
|
||||
buildx_version="v0.35.0"
|
||||
mkdir -p "$HOME/.docker/cli-plugins"
|
||||
curl --fail --show-error --location \
|
||||
--connect-timeout "${OPENCLAW_CRABBOX_HYDRATE_DOWNLOAD_CONNECT_TIMEOUT_SECONDS:-15}" \
|
||||
|
|
@ -286,6 +292,7 @@ jobs:
|
|||
--retry-all-errors \
|
||||
"https://github.com/docker/buildx/releases/download/${buildx_version}/buildx-${buildx_version}.linux-${buildx_arch}" \
|
||||
-o "$HOME/.docker/cli-plugins/docker-buildx"
|
||||
echo "${buildx_sha256} $HOME/.docker/cli-plugins/docker-buildx" | sha256sum -c -
|
||||
chmod 0755 "$HOME/.docker/cli-plugins/docker-buildx"
|
||||
fi
|
||||
|
||||
|
|
|
|||
4
.github/workflows/openclaw-performance.yml
vendored
4
.github/workflows/openclaw-performance.yml
vendored
|
|
@ -67,8 +67,8 @@ concurrency:
|
|||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
OCM_VERSION: v0.2.25
|
||||
OCM_LINUX_X64_SHA256: 57530199d21eb5bfa29695749928b40fd2869484c7edff69b7c65bfc84f2f1aa
|
||||
OCM_VERSION: v0.2.29
|
||||
OCM_LINUX_X64_SHA256: d966098d6ba2bc10891be3c76e162a37b07f28c4f51da75d2eb509886eb7e1cf
|
||||
KOVA_REPOSITORY: openclaw/Kova
|
||||
PERFORMANCE_MODEL_ID: gpt-5.6-luna
|
||||
# Release matrices cold-build the candidate runtime before measurement.
|
||||
|
|
|
|||
6
.github/workflows/opengrep-precise-full.yml
vendored
6
.github/workflows/opengrep-precise-full.yml
vendored
|
|
@ -32,11 +32,11 @@ jobs:
|
|||
- name: Install opengrep
|
||||
env:
|
||||
# Pin both the install script (by commit SHA) and the binary version.
|
||||
# The script SHA must match the v1.22.0 release tag in opengrep/opengrep
|
||||
# The script SHA must match the v1.25.0 release tag in opengrep/opengrep
|
||||
# so a compromised or force-pushed `main` cannot RCE in our CI runner.
|
||||
# Bump both together when upgrading.
|
||||
OPENGREP_VERSION: v1.22.0
|
||||
OPENGREP_INSTALL_SHA: f458d7f0d52cc58eae1ca3cf3d5caf101e637519
|
||||
OPENGREP_VERSION: v1.25.0
|
||||
OPENGREP_INSTALL_SHA: 27b5fba1b315fbc63d0fd474d01f5d8235cc86e2
|
||||
run: |
|
||||
# Download first so a timed-out transfer cannot execute a partial installer.
|
||||
installer="$(mktemp "${RUNNER_TEMP}/opengrep-install.XXXXXX")"
|
||||
|
|
|
|||
6
.github/workflows/opengrep-precise.yml
vendored
6
.github/workflows/opengrep-precise.yml
vendored
|
|
@ -58,11 +58,11 @@ jobs:
|
|||
- name: Install opengrep
|
||||
env:
|
||||
# Pin both the install script (by commit SHA) and the binary version.
|
||||
# The script SHA must match the v1.22.0 release tag in opengrep/opengrep
|
||||
# The script SHA must match the v1.25.0 release tag in opengrep/opengrep
|
||||
# so a compromised or force-pushed `main` cannot RCE in our CI runner.
|
||||
# Bump both together when upgrading.
|
||||
OPENGREP_VERSION: v1.22.0
|
||||
OPENGREP_INSTALL_SHA: f458d7f0d52cc58eae1ca3cf3d5caf101e637519
|
||||
OPENGREP_VERSION: v1.25.0
|
||||
OPENGREP_INSTALL_SHA: 27b5fba1b315fbc63d0fd474d01f5d8235cc86e2
|
||||
run: |
|
||||
# Download first so a timed-out transfer cannot execute a partial installer.
|
||||
installer="$(mktemp "${RUNNER_TEMP}/opengrep-install.XXXXXX")"
|
||||
|
|
|
|||
2
.github/workflows/workflow-sanity.yml
vendored
2
.github/workflows/workflow-sanity.yml
vendored
|
|
@ -180,7 +180,7 @@ jobs:
|
|||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
ACTIONLINT_VERSION="1.7.11"
|
||||
ACTIONLINT_VERSION="1.7.12"
|
||||
archive="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
|
||||
base_url="https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}"
|
||||
# GitHub release downloads occasionally return transient 5xx responses.
|
||||
|
|
|
|||
|
|
@ -31,13 +31,13 @@ repos:
|
|||
|
||||
# GitHub Actions linting
|
||||
- repo: https://github.com/rhysd/actionlint
|
||||
rev: v1.7.10
|
||||
rev: v1.7.12
|
||||
hooks:
|
||||
- id: actionlint
|
||||
|
||||
# GitHub Actions security audit
|
||||
- repo: https://github.com/zizmorcore/zizmor-pre-commit
|
||||
rev: v1.22.0
|
||||
rev: v1.28.0
|
||||
hooks:
|
||||
- id: zizmor
|
||||
args:
|
||||
|
|
@ -52,7 +52,7 @@ repos:
|
|||
|
||||
# Python checks for skills scripts
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.14.1
|
||||
rev: v0.15.22
|
||||
hooks:
|
||||
- id: ruff
|
||||
files: "^skills/.*\\.py$"
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ flags, and plugin allow/deny references into this block. Explicit canonical
|
|||
## App-server transport
|
||||
|
||||
For ordinary harness turns, OpenClaw starts the managed Codex binary shipped
|
||||
with the official plugin (currently `@openai/codex` `0.144.6`):
|
||||
with the official plugin (currently `@openai/codex` `0.145.0`):
|
||||
|
||||
```bash
|
||||
codex app-server --listen stdio://
|
||||
|
|
@ -255,7 +255,7 @@ networking, so a full-access profile would not protect outbound traffic.
|
|||
|
||||
The plugin blocks older, newer-unvalidated, prerelease, build-suffixed, or
|
||||
unversioned app-server handshakes. Codex app-server must report a stable version
|
||||
from `0.143.0` through the bundled `0.144.6`.
|
||||
from `0.143.0` through the bundled `0.145.0`.
|
||||
|
||||
OpenClaw treats non-loopback WebSocket app-server URLs as remote and requires
|
||||
identity-bearing WebSocket auth through `appServer.authToken` or an
|
||||
|
|
@ -605,7 +605,7 @@ If discovery fails or times out, OpenClaw uses a bundled fallback catalog:
|
|||
| `gpt-5.4-mini` | GPT-5.4-Mini | low, medium, high, xhigh |
|
||||
|
||||
<Note>
|
||||
The current bundled harness is `@openai/codex` `0.144.6`. A `model/list` probe
|
||||
The current bundled harness is `@openai/codex` `0.145.0`. A `model/list` probe
|
||||
against that bundled app-server returned these public picker rows:
|
||||
|
||||
| Model id | Input modalities | Reasoning efforts |
|
||||
|
|
@ -614,8 +614,6 @@ against that bundled app-server returned these public picker rows:
|
|||
| `gpt-5.6-terra` | text, image | low, medium, high, xhigh, max, ultra |
|
||||
| `gpt-5.6-luna` | text, image | low, medium, high, xhigh, max |
|
||||
| `gpt-5.5` | text, image | low, medium, high, xhigh |
|
||||
| `gpt-5.4` | text, image | low, medium, high, xhigh |
|
||||
| `gpt-5.4-mini` | text, image | low, medium, high, xhigh |
|
||||
| `gpt-5.2` | text, image | low, medium, high, xhigh |
|
||||
|
||||
The app-server catalog can report `ultra`; OpenClaw reasoning controls currently
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ channel is the communication surface.
|
|||
|
||||
- The official `@openclaw/codex` plugin installed. Include `codex` in
|
||||
`plugins.allow` if your config uses an allowlist.
|
||||
- A stable Codex app-server from `0.143.0` through `0.144.6`. The plugin manages a compatible
|
||||
- A stable Codex app-server from `0.143.0` through `0.145.0`. The plugin manages a compatible
|
||||
binary by default, so a `codex` command on `PATH` does not affect normal
|
||||
startup.
|
||||
- Codex auth through `openclaw models auth login --provider openai`, an
|
||||
|
|
@ -1108,7 +1108,7 @@ Doctor rewrites legacy model refs to `openai/*`, removes stale session and
|
|||
whole-agent runtime pins, and preserves existing auth-profile overrides.
|
||||
|
||||
**The app-server is rejected:** use a stable Codex app-server from `0.143.0`
|
||||
through the bundled `0.144.6`. Prereleases, build-suffixed versions, and newer
|
||||
through the bundled `0.145.0`. Prereleases, build-suffixed versions, and newer
|
||||
unvalidated releases are rejected because OpenClaw validates generated schemas
|
||||
against the bundled app-server version.
|
||||
|
||||
|
|
|
|||
75
extensions/acpx/npm-shrinkwrap.json
generated
75
extensions/acpx/npm-shrinkwrap.json
generated
|
|
@ -9,7 +9,7 @@
|
|||
"version": "2026.7.2",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/claude-agent-acp": "0.59.0",
|
||||
"@agentclientprotocol/codex-acp": "1.1.4",
|
||||
"@agentclientprotocol/codex-acp": "1.1.7",
|
||||
"acpx": "0.12.0",
|
||||
"smol-toml": "1.7.0",
|
||||
"zod": "4.4.3"
|
||||
|
|
@ -33,13 +33,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@agentclientprotocol/codex-acp": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@agentclientprotocol/codex-acp/-/codex-acp-1.1.4.tgz",
|
||||
"integrity": "sha512-DzusIpGwlQwMWuHgJhU8FWMsyQvzjenB93IEzQATkdbNulo5Rd9GKOz8+B+/C9iWWxmyXgtgmjzaL+iRFyDryQ==",
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@agentclientprotocol/codex-acp/-/codex-acp-1.1.7.tgz",
|
||||
"integrity": "sha512-bhFLbGtOMEw6+PAp33vNERb6dXlULOfV3mWbRdps4v7sY7PHha/C2T1dnlG0yVcvBu9W+NYPzL0CAupnVoFTiQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "^1.2.1",
|
||||
"@openai/codex": "^0.144.4",
|
||||
"@agentclientprotocol/sdk": "^1.3.0",
|
||||
"@openai/codex": "^0.145.0",
|
||||
"diff": "^9.0.0",
|
||||
"open": "^11.0.0",
|
||||
"vscode-jsonrpc": "^9.0.1",
|
||||
|
|
@ -49,6 +49,15 @@
|
|||
"codex-acp": "dist/index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@agentclientprotocol/codex-acp/node_modules/@agentclientprotocol/sdk": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-1.3.0.tgz",
|
||||
"integrity": "sha512-i3h/efaeuMUFAO1HSfo97QZQnnvMd7wWBYtBsdL6UMZg3a78sk3Ffya5Xu7C7tYsXomXoDXJBAzQF2PcFKAhIQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@agentclientprotocol/sdk": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-1.2.1.tgz",
|
||||
|
|
@ -713,9 +722,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@openai/codex": {
|
||||
"version": "0.144.6",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6.tgz",
|
||||
"integrity": "sha512-wk+2CWiBNXiJLBoN2D08N9RceWkSBnlgk5g2K1a4CXrP/C0gdlHyRUG7RFzm9y41DCK/7tvCct233JVxyFmznw==",
|
||||
"version": "0.145.0",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0.tgz",
|
||||
"integrity": "sha512-/PSPSFujjjmiyVFvG2yu/grOFhsWdokTH8t2KGWhXSo/M5n/dIDsnbsnO82/7bLtIoDuzQf7ATBUMWqPWQINlQ==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"codex": "bin/codex.js"
|
||||
|
|
@ -724,19 +733,19 @@
|
|||
"node": ">=16"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@openai/codex-darwin-arm64": "npm:@openai/codex@0.144.6-darwin-arm64",
|
||||
"@openai/codex-darwin-x64": "npm:@openai/codex@0.144.6-darwin-x64",
|
||||
"@openai/codex-linux-arm64": "npm:@openai/codex@0.144.6-linux-arm64",
|
||||
"@openai/codex-linux-x64": "npm:@openai/codex@0.144.6-linux-x64",
|
||||
"@openai/codex-win32-arm64": "npm:@openai/codex@0.144.6-win32-arm64",
|
||||
"@openai/codex-win32-x64": "npm:@openai/codex@0.144.6-win32-x64"
|
||||
"@openai/codex-darwin-arm64": "npm:@openai/codex@0.145.0-darwin-arm64",
|
||||
"@openai/codex-darwin-x64": "npm:@openai/codex@0.145.0-darwin-x64",
|
||||
"@openai/codex-linux-arm64": "npm:@openai/codex@0.145.0-linux-arm64",
|
||||
"@openai/codex-linux-x64": "npm:@openai/codex@0.145.0-linux-x64",
|
||||
"@openai/codex-win32-arm64": "npm:@openai/codex@0.145.0-win32-arm64",
|
||||
"@openai/codex-win32-x64": "npm:@openai/codex@0.145.0-win32-x64"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-darwin-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-darwin-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-darwin-arm64.tgz",
|
||||
"integrity": "sha512-6zgvh70MzBNSeT17HEhSOrmmGGZGAKzSC7x6JAq+edkJkdPYA9P0I1tG7aJ49GlBkBxuC+MKBH1qm6+2Cghcww==",
|
||||
"version": "0.145.0-darwin-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-darwin-arm64.tgz",
|
||||
"integrity": "sha512-h6aQ0UxnaP8mIM/9/qPAH9MNkRliJo88toq1T36IxNM2L5JSU0TFamu+MZn7YkFgDsrp0RfiI+97Tm8AVVxqtA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -751,9 +760,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-darwin-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-darwin-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-darwin-x64.tgz",
|
||||
"integrity": "sha512-THRyPG0zSU6M8NQAge1LHEHsJDnoH4BpKsfJHB/qe3Fm+Wf6zqAmWJFlOKzBm27m0K2Hq3za4Ac2I5p5i4yp/A==",
|
||||
"version": "0.145.0-darwin-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-darwin-x64.tgz",
|
||||
"integrity": "sha512-FCYzVKCa9VoLtg9gVyzKpqylonfgZrfcWZN6HsXAZPeuo8CukdMqdgTUOhDn2V6h3MbqS0z6VqQVKUllN/yKhA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -768,9 +777,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-linux-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-linux-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-linux-arm64.tgz",
|
||||
"integrity": "sha512-PGiLXMN+2IQRkf7tOLi64dMInjU1pRLbz0Rwfj/yt2Y97SZQqAjFQoi2wmswmqtqMDnfwCPTC1DRXVQkvU6T6Q==",
|
||||
"version": "0.145.0-linux-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-linux-arm64.tgz",
|
||||
"integrity": "sha512-8OLcPXaAol/FOrRoDxWhIiHIFa73KRsM41EKocjRZOwiT4TcelzJWn3dHyiuSb7teWF25rrslvSPyvhULYRRCQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -785,9 +794,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-linux-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-linux-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-linux-x64.tgz",
|
||||
"integrity": "sha512-4E7EnzCg0OnBxCyYnwJ+qnZwWHYe0YScr5ucKWbngE9u4+0XrpWELqq2Kn9jl5GZK8MDjU7PrJwFIwusHOHjuw==",
|
||||
"version": "0.145.0-linux-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-linux-x64.tgz",
|
||||
"integrity": "sha512-u8w8LLv3DvsfrDCoswLIemZ0SoNEXyi511WsfFsSiYUazk9qMsB/NtU8N9vhAfN7mZAxLFoMex4v66JjHuZWwA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -802,9 +811,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-win32-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-win32-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-win32-arm64.tgz",
|
||||
"integrity": "sha512-SpMjXJLW43JzMP0K62mVcYfmFcpk0BK4AOgYmWSfyZHs3iRtHMd0UYw7605n/9lwkT2EqbwQLT2omZFeKJFzwA==",
|
||||
"version": "0.145.0-win32-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-win32-arm64.tgz",
|
||||
"integrity": "sha512-sub61rjEFevi1i3Zx7nAd4JM5XxoNFqMqFc5LfTo2xSI8ixHjFvEYDFDXwXOftT04n3Ht1Wh271ioUZpDiEjEg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -819,9 +828,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-win32-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-win32-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-win32-x64.tgz",
|
||||
"integrity": "sha512-dN39VnjEthKz5io1RNWwZDtErdSn07nW3pGUgvlA6DMxgm/nuGaIAZO/sG/Hgxq/x5j9HteAENfrFgVkpZ0lFg==",
|
||||
"version": "0.145.0-win32-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-win32-x64.tgz",
|
||||
"integrity": "sha512-u0h9lk094CaXRSqE34SBW2dRaQTPa6fASXqehczWH9QdsU62mBsiAgAdp6tCG4i+YzPmmhjD8FdXNnYGNmwuMg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"type": "module",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/claude-agent-acp": "0.59.0",
|
||||
"@agentclientprotocol/codex-acp": "1.1.4",
|
||||
"@agentclientprotocol/codex-acp": "1.1.7",
|
||||
"acpx": "0.12.0",
|
||||
"smol-toml": "1.7.0",
|
||||
"zod": "4.4.3"
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ describe("prepareAcpxCodexAuthConfig", () => {
|
|||
});
|
||||
|
||||
const wrapper = await fs.readFile(generated.wrapperPath, "utf8");
|
||||
expect(wrapper).toContain('"@agentclientprotocol/codex-acp@1.1.4"');
|
||||
expect(wrapper).toContain('"@agentclientprotocol/codex-acp@1.1.7"');
|
||||
expect(wrapper).toContain('"--", "codex-acp"');
|
||||
expect(wrapper).not.toContain("@zed-industries/codex-acp");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ 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?.["@agentclientprotocol/codex-acp"]).toBe("1.1.4");
|
||||
expect(packageJson.dependencies?.["@agentclientprotocol/codex-acp"]).toBe("1.1.7");
|
||||
expect(packageJson.dependencies?.["@zed-industries/codex-acp"]).toBeUndefined();
|
||||
expect(packageJson.dependencies?.["@agentclientprotocol/claude-agent-acp"]).toBe("0.59.0");
|
||||
expect(packageJson.devDependencies?.["@agentclientprotocol/claude-agent-acp"]).toBeUndefined();
|
||||
|
|
|
|||
56
extensions/codex/npm-shrinkwrap.json
generated
56
extensions/codex/npm-shrinkwrap.json
generated
|
|
@ -8,7 +8,7 @@
|
|||
"name": "@openclaw/codex",
|
||||
"version": "2026.7.2",
|
||||
"dependencies": {
|
||||
"@openai/codex": "0.144.6",
|
||||
"@openai/codex": "0.145.0",
|
||||
"semver": "7.8.5",
|
||||
"smol-toml": "1.7.0",
|
||||
"typebox": "1.3.6",
|
||||
|
|
@ -17,9 +17,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@openai/codex": {
|
||||
"version": "0.144.6",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6.tgz",
|
||||
"integrity": "sha512-wk+2CWiBNXiJLBoN2D08N9RceWkSBnlgk5g2K1a4CXrP/C0gdlHyRUG7RFzm9y41DCK/7tvCct233JVxyFmznw==",
|
||||
"version": "0.145.0",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0.tgz",
|
||||
"integrity": "sha512-/PSPSFujjjmiyVFvG2yu/grOFhsWdokTH8t2KGWhXSo/M5n/dIDsnbsnO82/7bLtIoDuzQf7ATBUMWqPWQINlQ==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"codex": "bin/codex.js"
|
||||
|
|
@ -28,19 +28,19 @@
|
|||
"node": ">=16"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@openai/codex-darwin-arm64": "npm:@openai/codex@0.144.6-darwin-arm64",
|
||||
"@openai/codex-darwin-x64": "npm:@openai/codex@0.144.6-darwin-x64",
|
||||
"@openai/codex-linux-arm64": "npm:@openai/codex@0.144.6-linux-arm64",
|
||||
"@openai/codex-linux-x64": "npm:@openai/codex@0.144.6-linux-x64",
|
||||
"@openai/codex-win32-arm64": "npm:@openai/codex@0.144.6-win32-arm64",
|
||||
"@openai/codex-win32-x64": "npm:@openai/codex@0.144.6-win32-x64"
|
||||
"@openai/codex-darwin-arm64": "npm:@openai/codex@0.145.0-darwin-arm64",
|
||||
"@openai/codex-darwin-x64": "npm:@openai/codex@0.145.0-darwin-x64",
|
||||
"@openai/codex-linux-arm64": "npm:@openai/codex@0.145.0-linux-arm64",
|
||||
"@openai/codex-linux-x64": "npm:@openai/codex@0.145.0-linux-x64",
|
||||
"@openai/codex-win32-arm64": "npm:@openai/codex@0.145.0-win32-arm64",
|
||||
"@openai/codex-win32-x64": "npm:@openai/codex@0.145.0-win32-x64"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-darwin-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-darwin-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-darwin-arm64.tgz",
|
||||
"integrity": "sha512-6zgvh70MzBNSeT17HEhSOrmmGGZGAKzSC7x6JAq+edkJkdPYA9P0I1tG7aJ49GlBkBxuC+MKBH1qm6+2Cghcww==",
|
||||
"version": "0.145.0-darwin-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-darwin-arm64.tgz",
|
||||
"integrity": "sha512-h6aQ0UxnaP8mIM/9/qPAH9MNkRliJo88toq1T36IxNM2L5JSU0TFamu+MZn7YkFgDsrp0RfiI+97Tm8AVVxqtA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -55,9 +55,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-darwin-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-darwin-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-darwin-x64.tgz",
|
||||
"integrity": "sha512-THRyPG0zSU6M8NQAge1LHEHsJDnoH4BpKsfJHB/qe3Fm+Wf6zqAmWJFlOKzBm27m0K2Hq3za4Ac2I5p5i4yp/A==",
|
||||
"version": "0.145.0-darwin-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-darwin-x64.tgz",
|
||||
"integrity": "sha512-FCYzVKCa9VoLtg9gVyzKpqylonfgZrfcWZN6HsXAZPeuo8CukdMqdgTUOhDn2V6h3MbqS0z6VqQVKUllN/yKhA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -72,9 +72,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-linux-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-linux-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-linux-arm64.tgz",
|
||||
"integrity": "sha512-PGiLXMN+2IQRkf7tOLi64dMInjU1pRLbz0Rwfj/yt2Y97SZQqAjFQoi2wmswmqtqMDnfwCPTC1DRXVQkvU6T6Q==",
|
||||
"version": "0.145.0-linux-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-linux-arm64.tgz",
|
||||
"integrity": "sha512-8OLcPXaAol/FOrRoDxWhIiHIFa73KRsM41EKocjRZOwiT4TcelzJWn3dHyiuSb7teWF25rrslvSPyvhULYRRCQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -89,9 +89,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-linux-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-linux-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-linux-x64.tgz",
|
||||
"integrity": "sha512-4E7EnzCg0OnBxCyYnwJ+qnZwWHYe0YScr5ucKWbngE9u4+0XrpWELqq2Kn9jl5GZK8MDjU7PrJwFIwusHOHjuw==",
|
||||
"version": "0.145.0-linux-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-linux-x64.tgz",
|
||||
"integrity": "sha512-u8w8LLv3DvsfrDCoswLIemZ0SoNEXyi511WsfFsSiYUazk9qMsB/NtU8N9vhAfN7mZAxLFoMex4v66JjHuZWwA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -106,9 +106,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-win32-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-win32-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-win32-arm64.tgz",
|
||||
"integrity": "sha512-SpMjXJLW43JzMP0K62mVcYfmFcpk0BK4AOgYmWSfyZHs3iRtHMd0UYw7605n/9lwkT2EqbwQLT2omZFeKJFzwA==",
|
||||
"version": "0.145.0-win32-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-win32-arm64.tgz",
|
||||
"integrity": "sha512-sub61rjEFevi1i3Zx7nAd4JM5XxoNFqMqFc5LfTo2xSI8ixHjFvEYDFDXwXOftT04n3Ht1Wh271ioUZpDiEjEg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -123,9 +123,9 @@
|
|||
},
|
||||
"node_modules/@openai/codex-win32-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.144.6-win32-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.6-win32-x64.tgz",
|
||||
"integrity": "sha512-dN39VnjEthKz5io1RNWwZDtErdSn07nW3pGUgvlA6DMxgm/nuGaIAZO/sG/Hgxq/x5j9HteAENfrFgVkpZ0lFg==",
|
||||
"version": "0.145.0-win32-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.145.0-win32-x64.tgz",
|
||||
"integrity": "sha512-u0h9lk094CaXRSqE34SBW2dRaQTPa6fASXqehczWH9QdsU62mBsiAgAdp6tCG4i+YzPmmhjD8FdXNnYGNmwuMg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@openai/codex": "0.144.6",
|
||||
"@openai/codex": "0.145.0",
|
||||
"semver": "7.8.5",
|
||||
"smol-toml": "1.7.0",
|
||||
"typebox": "1.3.6",
|
||||
|
|
|
|||
|
|
@ -48,20 +48,16 @@
|
|||
},
|
||||
{
|
||||
"properties": {
|
||||
"credentialSource": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AmazonBedrockCredentialSource"
|
||||
}
|
||||
],
|
||||
"default": "awsManaged"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"amazonBedrock"
|
||||
],
|
||||
"title": "AmazonBedrockAccountType",
|
||||
"type": "string"
|
||||
},
|
||||
"usesCodexManagedCredentials": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
@ -72,13 +68,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"AmazonBedrockCredentialSource": {
|
||||
"enum": [
|
||||
"codexManaged",
|
||||
"awsManaged"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PlanType": {
|
||||
"enum": [
|
||||
"free",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@
|
|||
"image"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "Audio attachments included in user turns.",
|
||||
"enum": [
|
||||
"audio"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -459,6 +459,26 @@
|
|||
],
|
||||
"title": "InputImageDynamicToolCallOutputContentItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"audioUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"inputAudio"
|
||||
],
|
||||
"title": "InputAudioDynamicToolCallOutputContentItemType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"audioUrl",
|
||||
"type"
|
||||
],
|
||||
"title": "InputAudioDynamicToolCallOutputContentItem",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -567,12 +587,6 @@
|
|||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"templateId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
@ -1053,6 +1067,13 @@
|
|||
"null"
|
||||
]
|
||||
},
|
||||
"canAcceptDirectInput": {
|
||||
"description": "Whether the app server accepts direct turn input for this loaded thread. `None` means the capability is unavailable, such as for an unloaded stored thread.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"cliVersion": {
|
||||
"description": "Version of the CLI that created the thread.",
|
||||
"type": "string"
|
||||
|
|
@ -1795,6 +1816,15 @@
|
|||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"default": null,
|
||||
"description": "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.",
|
||||
"items": true,
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
|
|
@ -1836,6 +1866,7 @@
|
|||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Display item emitted by the interruptible `clock.sleep` tool.",
|
||||
"properties": {
|
||||
"durationMs": {
|
||||
"format": "uint64",
|
||||
|
|
@ -2301,6 +2332,46 @@
|
|||
"title": "LocalImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"audio"
|
||||
],
|
||||
"title": "AudioUserInputType",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"title": "AudioUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"localAudio"
|
||||
],
|
||||
"title": "LocalAudioUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "LocalAudioUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
|
|
@ -2500,6 +2571,14 @@
|
|||
},
|
||||
"type": "array"
|
||||
},
|
||||
"itemsBackwardsCursor": {
|
||||
"default": null,
|
||||
"description": "Opaque head cursor for hydrating paginated items backwards.\n\nPass this as `cursor` to `thread/items/list` with `sortDirection: \"desc\"`. The first page includes the cursor's head item.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -2549,6 +2628,14 @@
|
|||
},
|
||||
"thread": {
|
||||
"$ref": "#/definitions/Thread"
|
||||
},
|
||||
"turnsBackwardsCursor": {
|
||||
"default": null,
|
||||
"description": "Opaque head cursor for hydrating paginated turns backwards.\n\nPass this as `cursor` to `thread/turns/list` with `sortDirection: \"desc\"`. The first page includes the cursor's head turn.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
|
|||
|
|
@ -459,6 +459,26 @@
|
|||
],
|
||||
"title": "InputImageDynamicToolCallOutputContentItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"audioUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"inputAudio"
|
||||
],
|
||||
"title": "InputAudioDynamicToolCallOutputContentItemType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"audioUrl",
|
||||
"type"
|
||||
],
|
||||
"title": "InputAudioDynamicToolCallOutputContentItem",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -567,12 +587,6 @@
|
|||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"templateId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
@ -1053,6 +1067,13 @@
|
|||
"null"
|
||||
]
|
||||
},
|
||||
"canAcceptDirectInput": {
|
||||
"description": "Whether the app server accepts direct turn input for this loaded thread. `None` means the capability is unavailable, such as for an unloaded stored thread.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"cliVersion": {
|
||||
"description": "Version of the CLI that created the thread.",
|
||||
"type": "string"
|
||||
|
|
@ -1795,6 +1816,15 @@
|
|||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"default": null,
|
||||
"description": "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.",
|
||||
"items": true,
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
|
|
@ -1836,6 +1866,7 @@
|
|||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Display item emitted by the interruptible `clock.sleep` tool.",
|
||||
"properties": {
|
||||
"durationMs": {
|
||||
"format": "uint64",
|
||||
|
|
@ -2275,6 +2306,46 @@
|
|||
"title": "LocalImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"audio"
|
||||
],
|
||||
"title": "AudioUserInputType",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"title": "AudioUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"localAudio"
|
||||
],
|
||||
"title": "LocalAudioUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "LocalAudioUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
|
|
|
|||
|
|
@ -378,6 +378,26 @@
|
|||
],
|
||||
"title": "InputImageDynamicToolCallOutputContentItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"audioUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"inputAudio"
|
||||
],
|
||||
"title": "InputAudioDynamicToolCallOutputContentItemType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"audioUrl",
|
||||
"type"
|
||||
],
|
||||
"title": "InputAudioDynamicToolCallOutputContentItem",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -463,12 +483,6 @@
|
|||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"templateId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
@ -1247,6 +1261,15 @@
|
|||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"default": null,
|
||||
"description": "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.",
|
||||
"items": true,
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
|
|
@ -1288,6 +1311,7 @@
|
|||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Display item emitted by the interruptible `clock.sleep` tool.",
|
||||
"properties": {
|
||||
"durationMs": {
|
||||
"format": "uint64",
|
||||
|
|
@ -1649,6 +1673,46 @@
|
|||
"title": "LocalImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"audio"
|
||||
],
|
||||
"title": "AudioUserInputType",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"title": "AudioUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"localAudio"
|
||||
],
|
||||
"title": "LocalAudioUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "LocalAudioUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
|
|
|
|||
|
|
@ -378,6 +378,26 @@
|
|||
],
|
||||
"title": "InputImageDynamicToolCallOutputContentItem",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"audioUrl": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"inputAudio"
|
||||
],
|
||||
"title": "InputAudioDynamicToolCallOutputContentItemType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"audioUrl",
|
||||
"type"
|
||||
],
|
||||
"title": "InputAudioDynamicToolCallOutputContentItem",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -463,12 +483,6 @@
|
|||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"templateId": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
@ -1247,6 +1261,15 @@
|
|||
"query": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"default": null,
|
||||
"description": "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.",
|
||||
"items": true,
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"webSearch"
|
||||
|
|
@ -1288,6 +1311,7 @@
|
|||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Display item emitted by the interruptible `clock.sleep` tool.",
|
||||
"properties": {
|
||||
"durationMs": {
|
||||
"format": "uint64",
|
||||
|
|
@ -1649,6 +1673,46 @@
|
|||
"title": "LocalImageUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"audio"
|
||||
],
|
||||
"title": "AudioUserInputType",
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"url"
|
||||
],
|
||||
"title": "AudioUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"localAudio"
|
||||
],
|
||||
"title": "LocalAudioUserInputType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "LocalAudioUserInput",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ describe("shared Codex app-server client", () => {
|
|||
await sendInitializeResult(harness, "openclaw/0.117.9 (macOS; test)");
|
||||
|
||||
await expect(listPromise).rejects.toThrow(
|
||||
"A stable Codex app-server from 0.143.0 through 0.144.6 is required",
|
||||
"A stable Codex app-server from 0.143.0 through 0.145.0 is required",
|
||||
);
|
||||
expect(harness.process.stdin.destroyed).toBe(true);
|
||||
startSpy.mockRestore();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@
|
|||
/** Minimum Codex app-server version supported by the OpenClaw Codex bridge. */
|
||||
export const MIN_CODEX_APP_SERVER_VERSION = "0.143.0";
|
||||
/** Newest Codex app-server version validated by the OpenClaw Codex bridge. */
|
||||
export const MAX_CODEX_APP_SERVER_VERSION = "0.144.6";
|
||||
export const MAX_CODEX_APP_SERVER_VERSION = "0.145.0";
|
||||
/** npm package name for the managed Codex app-server binary. */
|
||||
export const MANAGED_CODEX_APP_SERVER_PACKAGE = "@openai/codex";
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
"@openclaw/slack": "workspace:*",
|
||||
"@openclaw/whatsapp": "workspace:*",
|
||||
"openclaw": "workspace:*",
|
||||
"vite": "8.1.3"
|
||||
"vite": "8.1.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"openclaw": ">=2026.7.2"
|
||||
|
|
|
|||
307
extensions/slack/npm-shrinkwrap.json
generated
307
extensions/slack/npm-shrinkwrap.json
generated
|
|
@ -8,11 +8,13 @@
|
|||
"name": "@openclaw/slack",
|
||||
"version": "2026.7.2",
|
||||
"dependencies": {
|
||||
"@slack/bolt": "4.7.3",
|
||||
"@slack/types": "2.21.1",
|
||||
"@slack/web-api": "7.18.0",
|
||||
"@slack/bolt": "5.0.0",
|
||||
"@slack/socket-mode": "3.0.0",
|
||||
"@slack/types": "3.0.0",
|
||||
"@slack/web-api": "8.0.0",
|
||||
"p-map": "7.0.5",
|
||||
"typebox": "1.3.6",
|
||||
"undici": "7.28.0",
|
||||
"ws": "8.21.1",
|
||||
"zod": "4.4.3"
|
||||
},
|
||||
|
|
@ -26,110 +28,106 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@slack/bolt": {
|
||||
"version": "4.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@slack/bolt/-/bolt-4.7.3.tgz",
|
||||
"integrity": "sha512-bODs8q/yNDWUPoxmQhFrRqLMA5vhB/PDizYWqb6CkQhLWEUo5JFtfJcmeU4ElGl6qSt++OKjSYNa4MPc77CleQ==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/bolt/-/bolt-5.0.0.tgz",
|
||||
"integrity": "sha512-L0FTzidrDKTu4Ph8sdv0bB3acafBTAC02TBcD+hojPTTNSMX3hSK+rkpkUKkqbbc0vGpSjd6A/g71Rjy7EbBhw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@slack/logger": "^4.0.1",
|
||||
"@slack/oauth": "^3.0.5",
|
||||
"@slack/socket-mode": "^2.0.7",
|
||||
"@slack/types": "^2.21.1",
|
||||
"@slack/web-api": "^7.16.0",
|
||||
"axios": "^1.12.0",
|
||||
"@slack/logger": "^5.0.0",
|
||||
"@slack/oauth": "^4.0.0",
|
||||
"@slack/socket-mode": "^3.0.0",
|
||||
"@slack/types": "^3.0.0",
|
||||
"@slack/web-api": "^8.0.0",
|
||||
"express": "^5.0.0",
|
||||
"path-to-regexp": "^8.1.0",
|
||||
"raw-body": "^3",
|
||||
"tsscmp": "^1.0.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
"npm": ">=8.6.0"
|
||||
"node": ">=20",
|
||||
"npm": ">=9.6.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/express": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@slack/logger": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@slack/logger/-/logger-4.0.1.tgz",
|
||||
"integrity": "sha512-6cmdPrV/RYfd2U0mDGiMK8S7OJqpCTm7enMLRR3edccsPX8j7zXTLnaEF4fhxxJJTAIOil6+qZrnUPTuaLvwrQ==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/logger/-/logger-5.0.0.tgz",
|
||||
"integrity": "sha512-VGXhmmgsAo9shdQYh4tFDndd+7nsgp0Y5h0UPDaUp8K359pBasI6YdkMqFW3mCOxLQkq09qj7o7cq6f3DuXcJQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": ">=18"
|
||||
"@types/node": ">=20"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18",
|
||||
"npm": ">= 8.6.0"
|
||||
"node": ">= 20",
|
||||
"npm": ">=9.6.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@slack/oauth": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@slack/oauth/-/oauth-3.0.5.tgz",
|
||||
"integrity": "sha512-exqFQySKhNDptWYSWhvRUJ4/+ndu2gayIy7vg/JfmJq3wGtGdHk531P96fAZyBm5c1Le3yaPYqv92rL4COlU3A==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/oauth/-/oauth-4.0.0.tgz",
|
||||
"integrity": "sha512-Aqs5bGghT+VtNcdwVOQy7CcyCfDNd9YYnZsCRukIF9p1Mxuq4uL+BjqlWQB0SeS4wzrLzePPgvj8JDuQil+ezA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@slack/logger": "^4.0.1",
|
||||
"@slack/web-api": "^7.15.0",
|
||||
"@slack/logger": "^5.0.0",
|
||||
"@slack/web-api": "^8.0.0",
|
||||
"@types/jsonwebtoken": "^9",
|
||||
"@types/node": ">=18",
|
||||
"@types/node": ">=20",
|
||||
"jsonwebtoken": "^9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
"npm": ">=8.6.0"
|
||||
"node": ">=20",
|
||||
"npm": ">=9.6.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@slack/socket-mode": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@slack/socket-mode/-/socket-mode-2.0.7.tgz",
|
||||
"integrity": "sha512-qYy07je71WnEHgRwmw12DlAnZLi5HXmdlI2WUzUK2LH/rYXQpP6uEg462S5CwfE8FoCKUdIigHtYnOOfzZH1lQ==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/socket-mode/-/socket-mode-3.0.0.tgz",
|
||||
"integrity": "sha512-QShO60SB0E+HH+TbcKj3CBEQbodToRyiXnxuSB4t1kvUlqEmuGA1nOOjrRDkDJbOECAZ13PLe4ek9SrntpfoYg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@slack/logger": "^4.0.1",
|
||||
"@slack/web-api": "^7.15.0",
|
||||
"@types/node": ">=18",
|
||||
"@types/ws": "^8",
|
||||
"eventemitter3": "^5",
|
||||
"ws": "^8"
|
||||
"@slack/logger": "^5.0.0",
|
||||
"@slack/web-api": "^8.0.0",
|
||||
"@types/node": ">=20",
|
||||
"eventemitter3": "^5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18",
|
||||
"npm": ">= 8.6.0"
|
||||
"node": ">=20",
|
||||
"npm": ">=9.6.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"undici": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@slack/types": {
|
||||
"version": "2.21.1",
|
||||
"resolved": "https://registry.npmjs.org/@slack/types/-/types-2.21.1.tgz",
|
||||
"integrity": "sha512-I8vmSjNYWsaxuWPx6dz4yeh0h7vRBWbgAMK14LEmblbZ404BtrPbXs6jDPx4cYgGf8msDGF4A9opLZBu21FViQ==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/types/-/types-3.0.0.tgz",
|
||||
"integrity": "sha512-KNOqpnNAlsFt5Jk9XBclslQ0lobRIg/0tnhpmvZJAglHJx9E8oceN8hC3gaBzkR6UzQ9Wzq4rLsJ98wUcxWPfw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12.13.0",
|
||||
"npm": ">= 6.12.0"
|
||||
"node": ">= 20",
|
||||
"npm": ">=9.6.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@slack/web-api": {
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-7.18.0.tgz",
|
||||
"integrity": "sha512-EWBsKUhOFFp87beQg/ToSC+asWB7BrGHuh7uPC1ZI9vr41GjS+3WmmyWIMqs+mF6U+mh4d6HhtFlv67TrJFsvw==",
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-8.0.0.tgz",
|
||||
"integrity": "sha512-ORx3XQryQPq2Jnxv5giSKXVoQRUeylrrymIR2S9fPzLjPcCts8RayMeBSZMcpfpAqp6fnBRuPW2UB6dUPUTEZA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@slack/logger": "^4.0.1",
|
||||
"@slack/types": "^2.21.0",
|
||||
"@types/node": ">=18",
|
||||
"@slack/logger": "^5.0.0",
|
||||
"@slack/types": "^3.0.0",
|
||||
"@types/node": ">=20",
|
||||
"@types/retry": "0.12.0",
|
||||
"axios": "^1.16.0",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"form-data": "^4.0.4",
|
||||
"is-electron": "2.2.2",
|
||||
"is-stream": "^2",
|
||||
"p-queue": "^6",
|
||||
"p-retry": "^4",
|
||||
"retry": "^0.13.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18",
|
||||
"npm": ">= 8.6.0"
|
||||
"node": ">= 20",
|
||||
"npm": ">=9.6.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/jsonwebtoken": {
|
||||
|
|
@ -163,15 +161,6 @@
|
|||
"integrity": "sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
|
||||
|
|
@ -185,36 +174,6 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.18.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz",
|
||||
"integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.16.0",
|
||||
"form-data": "^4.0.5",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
"proxy-from-env": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz",
|
||||
|
|
@ -296,18 +255,6 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
|
||||
|
|
@ -365,15 +312,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
|
|
@ -451,21 +389,6 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
|
|
@ -551,64 +474,6 @@
|
|||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
|
||||
"integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.6.tgz",
|
||||
"integrity": "sha512-Ogz/E85h9tlfJzpI6TuFpGcHZFhLrb9Gw8wq9v40CxSCPnv7ahKr6Xgtkn0KYCDQJ8DNn5VoMO8EXr9V5PadyA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.4",
|
||||
"mime-types": "^2.1.35",
|
||||
"safe-buffer": "^5.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data/node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data/node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
|
|
@ -697,21 +562,6 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
|
||||
|
|
@ -744,19 +594,6 @@
|
|||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz",
|
||||
|
|
@ -788,30 +625,12 @@
|
|||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/is-electron": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz",
|
||||
"integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"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-stream": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
|
||||
|
|
@ -1100,15 +919,6 @@
|
|||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.15.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
|
||||
|
|
@ -1403,6 +1213,15 @@
|
|||
"integrity": "sha512-Sc8RA0NCMEFmApHNU9ZMzqcpQj46She44J8ffpLM/bdhLNUZKq7DJumcLcsFx1gRmDfQPgCgOmFFJ7rcnfWNyA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.28.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz",
|
||||
"integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.18.1"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
|
||||
|
|
|
|||
|
|
@ -8,11 +8,13 @@
|
|||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@slack/bolt": "4.7.3",
|
||||
"@slack/types": "2.21.1",
|
||||
"@slack/web-api": "7.18.0",
|
||||
"@slack/bolt": "5.0.0",
|
||||
"@slack/socket-mode": "3.0.0",
|
||||
"@slack/types": "3.0.0",
|
||||
"@slack/web-api": "8.0.0",
|
||||
"p-map": "7.0.5",
|
||||
"typebox": "1.3.6",
|
||||
"undici": "7.28.0",
|
||||
"ws": "8.21.1",
|
||||
"zod": "4.4.3"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,24 @@
|
|||
// Slack plugin module implements client options behavior.
|
||||
import type { Agent } from "node:http";
|
||||
import { createRequire } from "node:module";
|
||||
import type { RetryOptions, WebClientOptions } from "@slack/web-api";
|
||||
import { createNodeProxyAgent } from "openclaw/plugin-sdk/fetch-runtime";
|
||||
import {
|
||||
addActiveManagedProxyTlsOptions,
|
||||
resolveEnvHttpProxyAgentOptions,
|
||||
} from "openclaw/plugin-sdk/fetch-runtime";
|
||||
import type { EnvHttpProxyAgent } from "undici";
|
||||
|
||||
export type SlackLookupClientOptions = Pick<WebClientOptions, "agent" | "slackApiUrl" | "timeout">;
|
||||
type SlackUndiciRuntime = Pick<typeof import("undici"), "EnvHttpProxyAgent" | "fetch">;
|
||||
type SlackProxyDispatcher = EnvHttpProxyAgent;
|
||||
|
||||
const requireFromSlackSocketMode = (() => {
|
||||
const require = createRequire(import.meta.url);
|
||||
return createRequire(require.resolve("@slack/socket-mode/package.json"));
|
||||
})();
|
||||
|
||||
function loadSlackUndiciRuntime(): SlackUndiciRuntime {
|
||||
return requireFromSlackSocketMode("undici") as SlackUndiciRuntime;
|
||||
}
|
||||
export type SlackLookupClientOptions = Pick<WebClientOptions, "fetch" | "slackApiUrl" | "timeout">;
|
||||
|
||||
export const SLACK_DEFAULT_RETRY_OPTIONS: RetryOptions = {
|
||||
retries: 2,
|
||||
|
|
@ -23,41 +38,46 @@ const SLACK_LOOKUP_RETRY_OPTIONS: RetryOptions = {
|
|||
retries: 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* Build an HTTPS proxy agent from env vars (HTTPS_PROXY, HTTP_PROXY, etc.)
|
||||
* for use as the `agent` option in Slack WebClient and Socket Mode connections.
|
||||
*
|
||||
* When set, this agent is forwarded through @slack/bolt -> @slack/socket-mode ->
|
||||
* SlackWebSocket as the `httpAgent`, which the `ws` library uses to tunnel the
|
||||
* WebSocket upgrade request through the proxy. This fixes Socket Mode in
|
||||
* environments where outbound traffic must go through an HTTP CONNECT proxy.
|
||||
*
|
||||
* Respects `NO_PROXY` / `no_proxy`; if `*.slack.com` (or a matching pattern)
|
||||
* appears in the exclusion list, returns `undefined` so the connection is direct.
|
||||
*
|
||||
* Returns `undefined` when no proxy env var is configured or when Slack hosts
|
||||
* are excluded by `NO_PROXY`.
|
||||
*/
|
||||
function resolveSlackProxyAgent(targetUrl: string): Agent | undefined {
|
||||
try {
|
||||
return createNodeProxyAgent({
|
||||
mode: "env",
|
||||
targetUrl,
|
||||
});
|
||||
} catch {
|
||||
// Malformed proxy URL; degrade gracefully to direct connection.
|
||||
/** Build the dispatcher shared by Slack Web API fetches and Socket Mode. */
|
||||
export function resolveSlackProxyDispatcher(): SlackProxyDispatcher | undefined {
|
||||
const options = resolveEnvHttpProxyAgentOptions();
|
||||
if (!options) {
|
||||
return undefined;
|
||||
}
|
||||
try {
|
||||
const { EnvHttpProxyAgent } = loadSlackUndiciRuntime();
|
||||
return new EnvHttpProxyAgent(addActiveManagedProxyTlsOptions(options));
|
||||
} catch {
|
||||
// Malformed proxy URL; degrade gracefully to direct connections.
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function createSlackDispatcherFetch(
|
||||
dispatcher: SlackProxyDispatcher,
|
||||
): NonNullable<WebClientOptions["fetch"]> {
|
||||
const { fetch: slackFetch } = loadSlackUndiciRuntime();
|
||||
return ((input: RequestInfo | URL, init?: RequestInit) => {
|
||||
// Slack Web API invokes this hook with URL/string inputs. The cast only bridges
|
||||
// duplicate Undici Request types while the package-owned fetch and dispatcher stay paired.
|
||||
const slackInput = input as Parameters<typeof slackFetch>[0];
|
||||
const slackInit = { ...init, dispatcher } as Parameters<typeof slackFetch>[1];
|
||||
return slackFetch(slackInput, slackInit);
|
||||
}) as NonNullable<WebClientOptions["fetch"]>;
|
||||
}
|
||||
|
||||
function resolveSlackApiUrlFromEnv(): string | undefined {
|
||||
return process.env.SLACK_API_URL?.trim() || undefined;
|
||||
}
|
||||
|
||||
function applySlackApiUrlAndProxyOptions(options: WebClientOptions): void {
|
||||
function applySlackApiUrlAndProxyOptions(
|
||||
options: WebClientOptions,
|
||||
dispatcher?: SlackProxyDispatcher,
|
||||
): void {
|
||||
const slackApiUrl = options.slackApiUrl ?? resolveSlackApiUrlFromEnv();
|
||||
const proxyTargetUrl = slackApiUrl ?? "https://slack.com/";
|
||||
options.agent ??= resolveSlackProxyAgent(proxyTargetUrl);
|
||||
if (dispatcher && !options.fetch) {
|
||||
options.fetch = createSlackDispatcherFetch(dispatcher);
|
||||
}
|
||||
if (slackApiUrl !== undefined) {
|
||||
options.slackApiUrl = slackApiUrl;
|
||||
} else {
|
||||
|
|
@ -65,25 +85,32 @@ function applySlackApiUrlAndProxyOptions(options: WebClientOptions): void {
|
|||
}
|
||||
}
|
||||
|
||||
export function resolveSlackWebClientOptions(options: WebClientOptions = {}): WebClientOptions {
|
||||
export function resolveSlackWebClientOptions(
|
||||
options: WebClientOptions = {},
|
||||
dispatcher = resolveSlackProxyDispatcher(),
|
||||
): WebClientOptions {
|
||||
const resolved: WebClientOptions = Object.assign({}, options);
|
||||
applySlackApiUrlAndProxyOptions(resolved);
|
||||
applySlackApiUrlAndProxyOptions(resolved, dispatcher);
|
||||
resolved.retryConfig ??= SLACK_DEFAULT_RETRY_OPTIONS;
|
||||
return resolved;
|
||||
}
|
||||
|
||||
export function resolveSlackWriteClientOptions(options: WebClientOptions = {}): WebClientOptions {
|
||||
export function resolveSlackWriteClientOptions(
|
||||
options: WebClientOptions = {},
|
||||
dispatcher = resolveSlackProxyDispatcher(),
|
||||
): WebClientOptions {
|
||||
const resolved: WebClientOptions = Object.assign({}, options);
|
||||
applySlackApiUrlAndProxyOptions(resolved);
|
||||
applySlackApiUrlAndProxyOptions(resolved, dispatcher);
|
||||
resolved.retryConfig ??= SLACK_WRITE_RETRY_OPTIONS;
|
||||
return resolved;
|
||||
}
|
||||
|
||||
export function resolveSlackLookupClientOptions(
|
||||
options: SlackLookupClientOptions = {},
|
||||
dispatcher = resolveSlackProxyDispatcher(),
|
||||
): WebClientOptions {
|
||||
const resolved: WebClientOptions = Object.assign({}, options);
|
||||
applySlackApiUrlAndProxyOptions(resolved);
|
||||
applySlackApiUrlAndProxyOptions(resolved, dispatcher);
|
||||
// Slack otherwise sleeps through the full Retry-After window after receiving 429,
|
||||
// outside the Axios request timeout.
|
||||
resolved.rejectRateLimitedCalls = true;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ let createSlackWriteClient: typeof import("./client.js").createSlackWriteClient;
|
|||
let createSlackTokenCacheKey: typeof import("./client.js").createSlackTokenCacheKey;
|
||||
let getSlackWriteClient: typeof import("./client.js").getSlackWriteClient;
|
||||
let clearSlackWriteClientCacheForTest: typeof import("./client.js").clearSlackWriteClientCacheForTest;
|
||||
let resolveSlackProxyDispatcher: typeof import("./client-options.js").resolveSlackProxyDispatcher;
|
||||
let resolveSlackWebClientOptions: typeof import("./client.js").resolveSlackWebClientOptions;
|
||||
let resolveSlackWriteClientOptions: typeof import("./client.js").resolveSlackWriteClientOptions;
|
||||
let SLACK_DEFAULT_RETRY_OPTIONS: typeof import("./client.js").SLACK_DEFAULT_RETRY_OPTIONS;
|
||||
|
|
@ -78,11 +79,11 @@ function restoreSlackApiUrlEnvForTest() {
|
|||
}
|
||||
}
|
||||
|
||||
function requireAgent<T extends { agent?: unknown }>(options: T): NonNullable<T["agent"]> {
|
||||
if (!options.agent) {
|
||||
throw new Error("expected proxy agent");
|
||||
function requireFetch(options: WebClientOptions): NonNullable<WebClientOptions["fetch"]> {
|
||||
if (!options.fetch) {
|
||||
throw new Error("expected dispatcher-backed fetch");
|
||||
}
|
||||
return options.agent as NonNullable<T["agent"]>;
|
||||
return options.fetch;
|
||||
}
|
||||
|
||||
function writeTempCa(contents: string): string {
|
||||
|
|
@ -95,6 +96,7 @@ function writeTempCa(contents: string): string {
|
|||
|
||||
beforeAll(async () => {
|
||||
const slackWebApi = await import("@slack/web-api");
|
||||
({ resolveSlackProxyDispatcher } = await import("./client-options.js"));
|
||||
({
|
||||
createSlackWebClient,
|
||||
createSlackStartupAuthClient,
|
||||
|
|
@ -179,27 +181,27 @@ describe("slack web client config", () => {
|
|||
});
|
||||
|
||||
it("passes merged options into WebClient", () => {
|
||||
const customAgent = {} as never;
|
||||
const customFetch = vi.fn() as never;
|
||||
|
||||
createSlackWebClient("xoxb-test", { timeout: 1234, agent: customAgent });
|
||||
createSlackWebClient("xoxb-test", { timeout: 1234, fetch: customFetch });
|
||||
|
||||
expect(WebClient).toHaveBeenCalledWith("xoxb-test", {
|
||||
agent: customAgent,
|
||||
fetch: customFetch,
|
||||
retryConfig: SLACK_DEFAULT_RETRY_OPTIONS,
|
||||
timeout: 1234,
|
||||
});
|
||||
});
|
||||
|
||||
it("bounds startup auth while preserving listener transport options", () => {
|
||||
const customAgent = {} as never;
|
||||
const customFetch = vi.fn() as never;
|
||||
|
||||
createSlackStartupAuthClient("xoxb-startup", {
|
||||
agent: customAgent,
|
||||
fetch: customFetch,
|
||||
slackApiUrl: "https://slack.test/api/",
|
||||
});
|
||||
|
||||
expect(WebClient).toHaveBeenCalledWith("xoxb-startup", {
|
||||
agent: customAgent,
|
||||
fetch: customFetch,
|
||||
rejectRateLimitedCalls: true,
|
||||
retryConfig: { retries: 0 },
|
||||
slackApiUrl: "https://slack.test/api/",
|
||||
|
|
@ -213,7 +215,6 @@ describe("slack web client config", () => {
|
|||
createSlackWebClient("xoxb-test", { timeout: 1234 });
|
||||
|
||||
expect(WebClient).toHaveBeenCalledWith("xoxb-test", {
|
||||
agent: undefined,
|
||||
retryConfig: SLACK_DEFAULT_RETRY_OPTIONS,
|
||||
timeout: 1234,
|
||||
});
|
||||
|
|
@ -229,12 +230,12 @@ describe("slack web client config", () => {
|
|||
});
|
||||
|
||||
it("passes the bounded lookup policy into WebClient", () => {
|
||||
const customAgent = {} as never;
|
||||
const customFetch = vi.fn() as never;
|
||||
|
||||
createSlackLookupClient("lookup-fixture", { agent: customAgent });
|
||||
createSlackLookupClient("lookup-fixture", { fetch: customFetch });
|
||||
|
||||
expect(WebClient).toHaveBeenCalledWith("lookup-fixture", {
|
||||
agent: customAgent,
|
||||
fetch: customFetch,
|
||||
rejectRateLimitedCalls: true,
|
||||
retryConfig: { retries: 0 },
|
||||
timeout: 30_000,
|
||||
|
|
@ -248,12 +249,12 @@ describe("slack web client config", () => {
|
|||
});
|
||||
|
||||
it("passes no-retry config into the write client by default", () => {
|
||||
const customAgent = {} as never;
|
||||
const customFetch = vi.fn() as never;
|
||||
|
||||
createSlackWriteClient("xoxb-test", { timeout: 4321, agent: customAgent });
|
||||
createSlackWriteClient("xoxb-test", { timeout: 4321, fetch: customFetch });
|
||||
|
||||
expect(WebClient).toHaveBeenCalledWith("xoxb-test", {
|
||||
agent: customAgent,
|
||||
fetch: customFetch,
|
||||
retryConfig: SLACK_WRITE_RETRY_OPTIONS,
|
||||
timeout: 4321,
|
||||
});
|
||||
|
|
@ -268,7 +269,6 @@ describe("slack web client config", () => {
|
|||
expect(second).toBe(first);
|
||||
expect(WebClient).toHaveBeenCalledTimes(1);
|
||||
expect(WebClient).toHaveBeenCalledWith("xoxb-test", {
|
||||
agent: undefined,
|
||||
retryConfig: SLACK_WRITE_RETRY_OPTIONS,
|
||||
});
|
||||
} finally {
|
||||
|
|
@ -336,7 +336,7 @@ describe("slack web client config", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("slack proxy agent", () => {
|
||||
describe("slack proxy dispatcher", () => {
|
||||
beforeEach(() => {
|
||||
clearProxyEnvForTest();
|
||||
});
|
||||
|
|
@ -348,122 +348,86 @@ describe("slack proxy agent", () => {
|
|||
restoreProxyEnvForTest();
|
||||
});
|
||||
|
||||
it("sets agent from HTTPS_PROXY env var", () => {
|
||||
it("attaches one dispatcher-backed fetch for HTTPS_PROXY", async () => {
|
||||
process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
const agent = requireAgent(options);
|
||||
const dispatcher = resolveSlackProxyDispatcher();
|
||||
const options = resolveSlackWebClientOptions({}, dispatcher);
|
||||
|
||||
expect(agent.constructor.name).toBe("ProxylineNodeProxyAgent");
|
||||
expect(dispatcher?.constructor.name).toBe("EnvHttpProxyAgent");
|
||||
expect(requireFetch(options)).toBeTypeOf("function");
|
||||
await dispatcher?.close();
|
||||
});
|
||||
|
||||
it("creates Slack env proxy agents while managed proxy CA trust is active", () => {
|
||||
it("creates the dispatcher while managed proxy CA trust is active", async () => {
|
||||
const caFile = writeTempCa("slack-managed-proxy-ca");
|
||||
process.env.HTTPS_PROXY = "https://proxy.example.com:8443";
|
||||
process.env.OPENCLAW_PROXY_ACTIVE = "1";
|
||||
process.env.OPENCLAW_PROXY_CA_FILE = caFile;
|
||||
|
||||
const options = resolveSlackWebClientOptions();
|
||||
const agent = requireAgent(options);
|
||||
|
||||
expect(agent.constructor.name).toBe("ProxylineNodeProxyAgent");
|
||||
const dispatcher = resolveSlackProxyDispatcher();
|
||||
expect(dispatcher?.constructor.name).toBe("EnvHttpProxyAgent");
|
||||
await dispatcher?.close();
|
||||
});
|
||||
|
||||
it("falls back to HTTP_PROXY when HTTPS_PROXY is not set", () => {
|
||||
it("falls back to HTTP_PROXY when HTTPS_PROXY is not set", async () => {
|
||||
process.env.HTTP_PROXY = "http://proxy.example.com:3128";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
const dispatcher = resolveSlackProxyDispatcher();
|
||||
|
||||
expect(requireAgent(options).constructor.name).toBe("ProxylineNodeProxyAgent");
|
||||
expect(dispatcher?.constructor.name).toBe("EnvHttpProxyAgent");
|
||||
await dispatcher?.close();
|
||||
});
|
||||
|
||||
it("does not set agent when no proxy env var is configured", () => {
|
||||
const options = resolveSlackWebClientOptions();
|
||||
|
||||
expect(options.agent).toBeUndefined();
|
||||
it("does not attach a fetch when no proxy env var is configured", () => {
|
||||
expect(resolveSlackProxyDispatcher()).toBeUndefined();
|
||||
expect(resolveSlackWebClientOptions().fetch).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not override an explicitly provided agent", () => {
|
||||
it("preserves an explicitly provided fetch", async () => {
|
||||
process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
|
||||
const customAgent = {} as never;
|
||||
const options = resolveSlackWebClientOptions({ agent: customAgent });
|
||||
const customFetch = vi.fn() as never;
|
||||
const dispatcher = resolveSlackProxyDispatcher();
|
||||
const options = resolveSlackWebClientOptions({ fetch: customFetch }, dispatcher);
|
||||
|
||||
expect(options.agent).toBe(customAgent);
|
||||
});
|
||||
|
||||
it("prefers lowercase https_proxy over uppercase", () => {
|
||||
process.env.https_proxy = "http://lower.example.com:3128";
|
||||
process.env.HTTPS_PROXY = "http://upper.example.com:3128";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
const agent = requireAgent(options);
|
||||
|
||||
// Proxyline stores the effective proxy URL in its resolver.
|
||||
expect(
|
||||
(agent as unknown as { getProxyForUrl: (url: string) => string }).getProxyForUrl(
|
||||
"https://slack.com/",
|
||||
),
|
||||
).toContain("lower.example.com");
|
||||
expect(options.fetch).toBe(customFetch);
|
||||
await dispatcher?.close();
|
||||
});
|
||||
|
||||
it("treats empty lowercase https_proxy as authoritative over uppercase", () => {
|
||||
process.env.https_proxy = "";
|
||||
process.env.HTTPS_PROXY = "http://upper.example.com:3128";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
|
||||
expect(options.agent).toBeUndefined();
|
||||
expect(resolveSlackProxyDispatcher()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("also applies proxy agent to write client options", () => {
|
||||
it("also applies the dispatcher-backed fetch to write clients", async () => {
|
||||
process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
|
||||
const options = resolveSlackWriteClientOptions();
|
||||
const agent = requireAgent(options);
|
||||
const dispatcher = resolveSlackProxyDispatcher();
|
||||
const options = resolveSlackWriteClientOptions({}, dispatcher);
|
||||
|
||||
expect(agent.constructor.name).toBe("ProxylineNodeProxyAgent");
|
||||
expect(requireFetch(options)).toBeTypeOf("function");
|
||||
await dispatcher?.close();
|
||||
});
|
||||
|
||||
it("respects NO_PROXY excluding slack.com", () => {
|
||||
it.each([
|
||||
"localhost,slack.com,.internal.corp",
|
||||
"localhost *.slack.com",
|
||||
"*",
|
||||
"localhost,.internal.corp",
|
||||
])("keeps NO_PROXY matching inside the shared env dispatcher: %s", async (noProxy) => {
|
||||
process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
|
||||
process.env.NO_PROXY = "localhost,slack.com,.internal.corp";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
process.env.NO_PROXY = noProxy;
|
||||
const dispatcher = resolveSlackProxyDispatcher();
|
||||
const options = resolveSlackWebClientOptions({}, dispatcher);
|
||||
|
||||
expect(options.agent).toBeUndefined();
|
||||
});
|
||||
|
||||
it("respects no_proxy (lowercase) excluding .slack.com", () => {
|
||||
process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
|
||||
process.env.no_proxy = ".slack.com";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
|
||||
expect(options.agent).toBeUndefined();
|
||||
});
|
||||
|
||||
it("respects space-separated no_proxy entries", () => {
|
||||
process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
|
||||
process.env.no_proxy = "localhost *.slack.com";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
|
||||
expect(options.agent).toBeUndefined();
|
||||
});
|
||||
|
||||
it("respects NO_PROXY wildcard", () => {
|
||||
process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
|
||||
process.env.NO_PROXY = "*";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
|
||||
expect(options.agent).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not skip proxy when NO_PROXY excludes unrelated hosts", () => {
|
||||
process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
|
||||
process.env.NO_PROXY = "localhost,.internal.corp";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
|
||||
expect(requireAgent(options).constructor.name).toBe("ProxylineNodeProxyAgent");
|
||||
expect(dispatcher?.constructor.name).toBe("EnvHttpProxyAgent");
|
||||
expect(requireFetch(options)).toBeTypeOf("function");
|
||||
await dispatcher?.close();
|
||||
});
|
||||
|
||||
it("degrades gracefully on malformed proxy URL", () => {
|
||||
process.env.HTTPS_PROXY = "not-a-valid-url://:::bad";
|
||||
const options = resolveSlackWebClientOptions();
|
||||
|
||||
// Should not throw; falls back to no agent
|
||||
expect(options.agent).toBeUndefined();
|
||||
expect(resolveSlackProxyDispatcher()).toBeUndefined();
|
||||
expect(resolveSlackWebClientOptions().fetch).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -53,16 +53,14 @@ describe("resolveSlackEventScope", () => {
|
|||
const teamScopedClient = new WebClient("xoxb-test", {
|
||||
teamId: "T111",
|
||||
retryConfig: { retries: 0 },
|
||||
adapter: async (config) => {
|
||||
encodedRequestBody = String(config.data);
|
||||
return {
|
||||
data: { ok: true, ts: "123.456", channel: "C123" },
|
||||
status: 200,
|
||||
statusText: "OK",
|
||||
headers: {},
|
||||
config,
|
||||
request: {},
|
||||
};
|
||||
fetch: (_input, init) => {
|
||||
encodedRequestBody = typeof init?.body === "string" ? init.body : "";
|
||||
return Promise.resolve(
|
||||
new Response(JSON.stringify({ ok: true, ts: "123.456", channel: "C123" }), {
|
||||
status: 200,
|
||||
headers: { "content-type": "application/json" },
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
const methodPayload = { channel: "C123", text: "hello" };
|
||||
|
|
|
|||
|
|
@ -309,6 +309,7 @@ export function createSlackBoltApp(params: {
|
|||
signingSecret?: string;
|
||||
slackWebhookPath: string;
|
||||
clientOptions: Record<string, unknown>;
|
||||
dispatcher?: SlackSocketModeReceiverOptions["dispatcher"];
|
||||
wrapReceiver?: (receiver: SlackReceiver) => SlackReceiver;
|
||||
}) {
|
||||
const socketModeLogger = createSlackSocketModeLogger();
|
||||
|
|
@ -317,6 +318,7 @@ export function createSlackBoltApp(params: {
|
|||
autoReconnectEnabled: true,
|
||||
clientPingTimeout: OPENCLAW_SLACK_CLIENT_PING_TIMEOUT_MS,
|
||||
logger: socketModeLogger,
|
||||
...(params.dispatcher ? { dispatcher: params.dispatcher } : {}),
|
||||
installerOptions: {
|
||||
clientOptions: params.clientOptions,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -185,14 +185,11 @@ describe("slack socket reconnect helpers", () => {
|
|||
);
|
||||
client.emit(
|
||||
"ws_message",
|
||||
Buffer.from(JSON.stringify({ type: "hello", num_connections: 2 })),
|
||||
false,
|
||||
);
|
||||
client.emit(
|
||||
"ws_message",
|
||||
Buffer.from(JSON.stringify({ type: "hello", num_connections: 3 })),
|
||||
false,
|
||||
Buffer.from(JSON.stringify({ type: "hello", num_connections: 4 })),
|
||||
true,
|
||||
);
|
||||
client.emit("ws_message", JSON.stringify({ type: "hello", num_connections: 2 }), false);
|
||||
client.emit("ws_message", JSON.stringify({ type: "hello", num_connections: 3 }), false);
|
||||
|
||||
expect(onSharedConnection).toHaveBeenCalledTimes(1);
|
||||
expect(onSharedConnection).toHaveBeenCalledWith(2);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import {
|
|||
resolveSlackAccountDmPolicy,
|
||||
} from "../accounts.js";
|
||||
import { isSlackAnyNativeApprovalClientEnabled } from "../approval-native-gates.js";
|
||||
import { resolveSlackWebClientOptions } from "../client-options.js";
|
||||
import { resolveSlackProxyDispatcher, resolveSlackWebClientOptions } from "../client-options.js";
|
||||
import { createSlackStartupAuthClient } from "../client.js";
|
||||
import { normalizeSlackWebhookPath, registerSlackHttpHandler } from "../http/index.js";
|
||||
import { SLACK_TEXT_LIMIT } from "../limits.js";
|
||||
|
|
@ -341,7 +341,8 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
|||
const ackReactionScope = cfg.messages?.ackReactionScope ?? "group-mentions";
|
||||
const typingReaction = slackCfg.typingReaction?.trim() ?? "";
|
||||
const mediaMaxBytes = (opts.mediaMaxMb ?? slackCfg.mediaMaxMb ?? 20) * 1024 * 1024;
|
||||
const clientOptions = resolveSlackWebClientOptions();
|
||||
const slackDispatcher = resolveSlackProxyDispatcher();
|
||||
const clientOptions = resolveSlackWebClientOptions({}, slackDispatcher);
|
||||
const durableIngress = createSlackDurableIngress({
|
||||
accountId: account.accountId,
|
||||
...(runtime.log ? { onLog: runtime.log } : {}),
|
||||
|
|
@ -355,6 +356,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
|||
signingSecret: slackMode === "http" ? (signingSecret ?? undefined) : undefined,
|
||||
slackWebhookPath,
|
||||
clientOptions: clientOptions as Record<string, unknown>,
|
||||
dispatcher: slackDispatcher,
|
||||
wrapReceiver: durableIngress.wrapReceiver,
|
||||
});
|
||||
|
||||
|
|
@ -853,6 +855,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
|
|||
unregisterHttpHandler?.();
|
||||
await durableIngress.stop();
|
||||
await gracefulStop();
|
||||
await slackDispatcher?.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,13 +55,16 @@ function isBufferArray(value: unknown): value is Buffer[] {
|
|||
}
|
||||
|
||||
function resolveSlackSocketModeConnectionCount(message: unknown): number | undefined {
|
||||
const buffer = Buffer.isBuffer(message)
|
||||
? message
|
||||
: message instanceof ArrayBuffer
|
||||
const buffer =
|
||||
typeof message === "string"
|
||||
? Buffer.from(message)
|
||||
: isBufferArray(message)
|
||||
? Buffer.concat(message)
|
||||
: undefined;
|
||||
: Buffer.isBuffer(message)
|
||||
? message
|
||||
: message instanceof ArrayBuffer
|
||||
? Buffer.from(message)
|
||||
: isBufferArray(message)
|
||||
? Buffer.concat(message)
|
||||
: undefined;
|
||||
if (!buffer?.includes(SLACK_SOCKET_HELLO_MARKER)) {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ import { emitSlackMessageSentHooks } from "../message-sent-hook.js";
|
|||
import {
|
||||
buildSlackNativeDataAccessibilityText,
|
||||
hasSlackNativeDataBlock,
|
||||
isSlackInvalidBlocksError,
|
||||
isSlackInvalidBlocksResponse,
|
||||
isSlackNativeResponseUrlRejection,
|
||||
} from "../native-data-blocks.js";
|
||||
import {
|
||||
buildSlackNativeDataDeliveryPlan,
|
||||
|
|
@ -565,7 +566,7 @@ export async function deliverSlackSlashReplies(params: {
|
|||
const deliverNativeFallback = async (messages: readonly SlackFormattingDisabledMessage[]) => {
|
||||
for (const message of messages) {
|
||||
const response = await respond(message);
|
||||
if (isSlackInvalidBlocksError(response)) {
|
||||
if (await isSlackInvalidBlocksResponse(response)) {
|
||||
throw new Error("Slack rejected the native-data fallback blocks with invalid_blocks.");
|
||||
}
|
||||
}
|
||||
|
|
@ -593,9 +594,9 @@ export async function deliverSlackSlashReplies(params: {
|
|||
let rejectedNativeBlocks = false;
|
||||
try {
|
||||
const response = await respond(planned.message);
|
||||
rejectedNativeBlocks = isSlackInvalidBlocksError(response);
|
||||
rejectedNativeBlocks = await isSlackInvalidBlocksResponse(response);
|
||||
} catch (error) {
|
||||
if (!isSlackInvalidBlocksError(error)) {
|
||||
if (!isSlackNativeResponseUrlRejection(error)) {
|
||||
throw error;
|
||||
}
|
||||
rejectedNativeBlocks = true;
|
||||
|
|
|
|||
|
|
@ -1038,7 +1038,7 @@ export async function registerSlackMonitorSlashCommands(params: {
|
|||
respond ??
|
||||
(async (message) => {
|
||||
if (!body.channel?.id || !body.user?.id) {
|
||||
return;
|
||||
return new Response(null, { status: 204 });
|
||||
}
|
||||
const payload =
|
||||
typeof message === "string"
|
||||
|
|
@ -1056,6 +1056,7 @@ export async function registerSlackMonitorSlashCommands(params: {
|
|||
...(payload.blocks ? { blocks: payload.blocks } : {}),
|
||||
...(typeof payload.mrkdwn === "boolean" ? { mrkdwn: payload.mrkdwn } : {}),
|
||||
});
|
||||
return new Response(null, { status: 200 });
|
||||
});
|
||||
const actionValue = action?.value ?? action?.selected_option?.value;
|
||||
const parsed = parseSlackCommandArgValue(actionValue);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { Response as UndiciResponse } from "undici";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
appendSlackNativeDataFallbackText,
|
||||
buildSlackNativeDataAccessibilityText,
|
||||
hasSlackNativeDataBlock,
|
||||
isSlackInvalidBlocksError,
|
||||
isSlackInvalidBlocksResponse,
|
||||
isSlackNativeResponseUrlRejection,
|
||||
} from "./native-data-blocks.js";
|
||||
|
||||
const chart = {
|
||||
|
|
@ -52,6 +55,29 @@ describe("Slack native data blocks", () => {
|
|||
expect(isSlackInvalidBlocksError(new Error("invalid_blocks"))).toBe(false);
|
||||
});
|
||||
|
||||
it("matches Bolt 5 response_url responses and contextual RespondError failures", async () => {
|
||||
const response = new Response(JSON.stringify({ error: "invalid_blocks" }), { status: 200 });
|
||||
await expect(isSlackInvalidBlocksResponse(response)).resolves.toBe(true);
|
||||
await expect(
|
||||
isSlackInvalidBlocksResponse(
|
||||
new UndiciResponse(JSON.stringify({ error: "invalid_blocks" }), { status: 200 }),
|
||||
),
|
||||
).resolves.toBe(true);
|
||||
await expect(isSlackInvalidBlocksResponse(new Response("ok"))).resolves.toBe(false);
|
||||
expect(
|
||||
isSlackNativeResponseUrlRejection({
|
||||
code: "slack_bolt_respond_error",
|
||||
statusCode: 400,
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isSlackNativeResponseUrlRejection({
|
||||
code: "slack_bolt_respond_error",
|
||||
statusCode: 500,
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("appends mixed native data in block order without collapsing repeated blocks", () => {
|
||||
const chartText = "Revenue mix (pie chart)\n- Product: 60\n- Services: 40";
|
||||
const tableText = "Pipeline report (table)\n- Account: Acme; ARR: $125k";
|
||||
|
|
|
|||
|
|
@ -49,6 +49,41 @@ export function isSlackInvalidBlocksError(error: unknown): boolean {
|
|||
return typeof code === "string" && code.trim().toLowerCase() === "invalid_blocks";
|
||||
}
|
||||
|
||||
type SlackResponseLike = {
|
||||
status: number;
|
||||
clone: () => { text: () => Promise<string> };
|
||||
};
|
||||
|
||||
function isSlackResponseLike(value: unknown): value is SlackResponseLike {
|
||||
const record = asRecord(value);
|
||||
return typeof record?.status === "number" && typeof record.clone === "function";
|
||||
}
|
||||
|
||||
/** Inspect Bolt 5's native response_url Response without consuming the caller's body. */
|
||||
export async function isSlackInvalidBlocksResponse(response: unknown): Promise<boolean> {
|
||||
if (!isSlackResponseLike(response)) {
|
||||
return isSlackInvalidBlocksError(response);
|
||||
}
|
||||
try {
|
||||
const body = await response.clone().text();
|
||||
if (body.trim().toLowerCase() === "invalid_blocks") {
|
||||
return true;
|
||||
}
|
||||
return isSlackInvalidBlocksError(JSON.parse(body));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Bolt 5 omits the response body from RespondError; 400 is contextual here. */
|
||||
export function isSlackNativeResponseUrlRejection(error: unknown): boolean {
|
||||
if (isSlackInvalidBlocksError(error)) {
|
||||
return true;
|
||||
}
|
||||
const record = asRecord(error);
|
||||
return record?.code === "slack_bolt_respond_error" && record.statusCode === 400;
|
||||
}
|
||||
|
||||
/** Extract a complete accessible summary from a supported native data block. */
|
||||
function renderSlackNativeDataFallbackText(value: unknown): string | undefined {
|
||||
const type = asRecord(value)?.type;
|
||||
|
|
|
|||
70
npm-shrinkwrap.json
generated
70
npm-shrinkwrap.json
generated
|
|
@ -10,11 +10,11 @@
|
|||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "1.2.1",
|
||||
"@agentclientprotocol/sdk": "1.3.0",
|
||||
"@anthropic-ai/sdk": "0.112.3",
|
||||
"@clack/core": "1.4.3",
|
||||
"@clack/prompts": "1.7.0",
|
||||
"@earendil-works/pi-tui": "0.80.10",
|
||||
"@earendil-works/pi-tui": "0.81.1",
|
||||
"@google/genai": "2.12.0",
|
||||
"@grammyjs/runner": "2.0.3",
|
||||
"@grammyjs/transformer-throttler": "1.2.1",
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
"diff": "9.0.0",
|
||||
"dotenv": "17.4.2",
|
||||
"entities": "8.0.0",
|
||||
"execa": "9.6.1",
|
||||
"execa": "10.0.0",
|
||||
"express": "5.2.1",
|
||||
"file-type": "22.0.1",
|
||||
"grammy": "1.45.1",
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
"semver": "7.8.5",
|
||||
"tar": "7.5.20",
|
||||
"tree-sitter-bash": "0.25.1",
|
||||
"tslog": "4.10.2",
|
||||
"tslog": "4.11.0",
|
||||
"typebox": "1.3.6",
|
||||
"typescript": "6.0.3",
|
||||
"undici": "8.6.0",
|
||||
|
|
@ -84,9 +84,9 @@
|
|||
}
|
||||
},
|
||||
"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==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@agentclientprotocol/sdk/-/sdk-1.3.0.tgz",
|
||||
"integrity": "sha512-i3h/efaeuMUFAO1HSfo97QZQnnvMd7wWBYtBsdL6UMZg3a78sk3Ffya5Xu7C7tYsXomXoDXJBAzQF2PcFKAhIQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
|
|
@ -161,9 +161,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@earendil-works/pi-tui": {
|
||||
"version": "0.80.10",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.80.10.tgz",
|
||||
"integrity": "sha512-c2JO29PbhKPEQ6fgHQKAl0WhwuFqzWfzspMmP+8B5tpDuP+0mvarRbKKg8gq4b+pQx/QX+6aVS4ko7deoyjQjg==",
|
||||
"version": "0.81.1",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.81.1.tgz",
|
||||
"integrity": "sha512-OMEe+Zt8oQYi/rCq3upxsTlIScWL0FPhXwQus34TbQb3EmTx88S7Uzx32JxvQiEeWOw8eDCdJf2PBUBE9r6wIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"get-east-asian-width": "1.6.0",
|
||||
|
|
@ -1369,31 +1369,44 @@
|
|||
}
|
||||
},
|
||||
"node_modules/execa": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz",
|
||||
"integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==",
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-10.0.0.tgz",
|
||||
"integrity": "sha512-Cxl6MKxB1dr1H0FHmiizJ+lavKF7pV+fcDZFyqMB8d5m7qUPm/OtZYcD5vPWePKxSnTQ57KuBd9mtdZ3oNCvyQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sindresorhus/merge-streams": "^4.0.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
"figures": "^6.1.0",
|
||||
"get-stream": "^9.0.0",
|
||||
"get-stream": "^9.0.1",
|
||||
"human-signals": "^8.0.1",
|
||||
"is-plain-obj": "^4.1.0",
|
||||
"is-stream": "^4.0.1",
|
||||
"npm-run-path": "^6.0.0",
|
||||
"pretty-ms": "^9.2.0",
|
||||
"path-key": "^4.0.0",
|
||||
"pretty-ms": "^9.3.0",
|
||||
"signal-exit": "^4.1.0",
|
||||
"strip-final-newline": "^4.0.0",
|
||||
"yoctocolors": "^2.1.1"
|
||||
"which-command": "^0.1.0",
|
||||
"yoctocolors": "^2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.19.0 || >=20.5.0"
|
||||
"node": ">=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/execa/node_modules/path-key": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
|
||||
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
|
||||
|
|
@ -3605,9 +3618,9 @@
|
|||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tslog": {
|
||||
"version": "4.10.2",
|
||||
"resolved": "https://registry.npmjs.org/tslog/-/tslog-4.10.2.tgz",
|
||||
"integrity": "sha512-XuELoRpMR+sq8fuWwX7P0bcj+PRNiicOKDEb3fGNURhxWVyykCi9BNq7c4uVz7h7P0sj8qgBsr5SWS6yBClq3g==",
|
||||
"version": "4.11.0",
|
||||
"resolved": "https://registry.npmjs.org/tslog/-/tslog-4.11.0.tgz",
|
||||
"integrity": "sha512-gBe0FTKkRpOv3DenGipjQWQe073jNd1cOLj3nYfVM0/NP29sQzAIx6kfyfTTsQOiWMC+B+tSr289lNXtu7HCmQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
|
|
@ -3800,6 +3813,21 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/which-command": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/which-command/-/which-command-0.1.0.tgz",
|
||||
"integrity": "sha512-XZyoF5/5hZtXitIwzrU4NKK+Wtbb9aB9CezUEw2Q0wlYK8NUYQxC1rRXgNueYLtBAJwXIb+/tFVk4dozciNJMA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"which-command": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/which-command?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/which-module": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
|
||||
|
|
|
|||
14
package.json
14
package.json
|
|
@ -1884,11 +1884,11 @@
|
|||
"verify": "node scripts/verify.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "1.2.1",
|
||||
"@agentclientprotocol/sdk": "1.3.0",
|
||||
"@anthropic-ai/sdk": "0.112.3",
|
||||
"@clack/core": "1.4.3",
|
||||
"@clack/prompts": "1.7.0",
|
||||
"@earendil-works/pi-tui": "0.80.10",
|
||||
"@earendil-works/pi-tui": "0.81.1",
|
||||
"@google/genai": "2.12.0",
|
||||
"@grammyjs/runner": "2.0.3",
|
||||
"@grammyjs/transformer-throttler": "1.2.1",
|
||||
|
|
@ -1909,7 +1909,7 @@
|
|||
"diff": "9.0.0",
|
||||
"dotenv": "17.4.2",
|
||||
"entities": "8.0.0",
|
||||
"execa": "9.6.1",
|
||||
"execa": "10.0.0",
|
||||
"express": "5.2.1",
|
||||
"file-type": "22.0.1",
|
||||
"grammy": "1.45.1",
|
||||
|
|
@ -1938,7 +1938,7 @@
|
|||
"semver": "7.8.5",
|
||||
"tar": "7.5.20",
|
||||
"tree-sitter-bash": "0.25.1",
|
||||
"tslog": "4.10.2",
|
||||
"tslog": "4.11.0",
|
||||
"typebox": "1.3.6",
|
||||
"typescript": "6.0.3",
|
||||
"undici": "8.6.0",
|
||||
|
|
@ -1972,10 +1972,10 @@
|
|||
"esbuild": "0.28.1",
|
||||
"fast-glob": "3.3.3",
|
||||
"ipaddr.js": "2.4.0",
|
||||
"jscpd": "5.0.12",
|
||||
"jscpd": "4.2.4",
|
||||
"jsdom": "29.1.1",
|
||||
"lit": "3.3.3",
|
||||
"oxfmt": "0.59.0",
|
||||
"oxfmt": "0.60.0",
|
||||
"oxlint": "1.74.0",
|
||||
"oxlint-tsgolint": "0.25.0",
|
||||
"playwright": "1.61.1",
|
||||
|
|
@ -1985,7 +1985,7 @@
|
|||
"tsdown": "0.22.1",
|
||||
"tsx": "4.23.1",
|
||||
"unrun": "0.3.1",
|
||||
"vite": "8.1.3",
|
||||
"vite": "8.1.5",
|
||||
"vitest": "4.1.10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
|
|
|||
1040
pnpm-lock.yaml
generated
1040
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -16,6 +16,7 @@ minimumReleaseAgeExclude:
|
|||
- "acpx"
|
||||
- "tokenjuice"
|
||||
- "@agentclientprotocol/sdk"
|
||||
- "@agentclientprotocol/codex-acp@1.1.7"
|
||||
- "axios"
|
||||
- "basic-ftp"
|
||||
- "baileys@7.0.0-rc13"
|
||||
|
|
@ -28,15 +29,27 @@ minimumReleaseAgeExclude:
|
|||
- "@cloudflare/workers-types"
|
||||
- "@hono/node-server"
|
||||
- "@mariozechner/*"
|
||||
- "@aws-sdk/checksums@3.1000.19"
|
||||
- "@aws-sdk/client-bedrock-runtime@3.1053.0"
|
||||
- "@aws-sdk/client-bedrock@3.1053.0"
|
||||
- "@aws-sdk/client-cognito-identity@3.1053.0"
|
||||
- "@aws-sdk/client-s3@3.1053.0"
|
||||
- "@aws-sdk/core"
|
||||
- "@aws-sdk/credential-provider-env@3.972.60"
|
||||
- "@aws-sdk/credential-provider-http@3.972.62"
|
||||
- "@aws-sdk/credential-provider-ini@3.973.5"
|
||||
- "@aws-sdk/credential-provider-login@3.972.67"
|
||||
- "@aws-sdk/credential-provider-process@3.972.60"
|
||||
- "@aws-sdk/credential-provider-sso@3.973.4"
|
||||
- "@aws-sdk/credential-provider-web-identity@3.972.66"
|
||||
- "@aws-sdk/credential-providers@3.1053.0"
|
||||
- "@aws-sdk/middleware-sdk-s3@3.972.65"
|
||||
- "@aws-sdk/middleware-websocket@3.972.42"
|
||||
- "@aws-sdk/nested-clients@3.997.34"
|
||||
- "@aws-sdk/s3-request-presigner@3.1053.0"
|
||||
- "@aws-sdk/token-providers@3.1052.0"
|
||||
- "@aws-sdk/token-providers@3.1053.0"
|
||||
- "@aws-sdk/token-providers@3.1092.0"
|
||||
- "@copilotkit/aimock@1.27.1"
|
||||
- "@microsoft/mxc-sdk@0.7.0"
|
||||
- "@earendil-works/pi-tui"
|
||||
|
|
@ -50,7 +63,12 @@ minimumReleaseAgeExclude:
|
|||
- "@openai/codex"
|
||||
- "@openai/codex-*"
|
||||
- "@pierre/diffs@1.2.3"
|
||||
- "@smithy/core@3.29.7"
|
||||
- "@smithy/credential-provider-imds@4.4.12"
|
||||
- "@smithy/fetch-http-handler@5.6.9"
|
||||
- "@smithy/shared-ini-file-loader@4.5.4"
|
||||
- "@smithy/signature-v4@5.6.8"
|
||||
- "postcss@8.5.22"
|
||||
- "@typescript/native-preview*"
|
||||
- "@types/node"
|
||||
- "@rolldown/*"
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ const checks: Array<{ file: string; snippets: string[] }> = [
|
|||
},
|
||||
{
|
||||
file: "ReviewDecision.ts",
|
||||
snippets: ['"approved"', '"approved_for_session"', '"denied"', '"abort"'],
|
||||
snippets: ['"approved"', '"approved_for_session"', "denied: { rejection: string }", '"abort"'],
|
||||
},
|
||||
{
|
||||
file: "v2/PlanDeltaNotification.ts",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { mkdtempSync, readdirSync, rmSync } from "node:fs";
|
|||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
const ACTIONLINT_VERSION = "1.7.11";
|
||||
const ACTIONLINT_VERSION = "1.7.12";
|
||||
const PRE_COMMIT_VERSION = "4.2.0";
|
||||
const WORKFLOW_DIR = ".github/workflows";
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ export async function prepareMinGitZip(tgzDir: string): Promise<string> {
|
|||
import urllib.request
|
||||
|
||||
preferred_names = [
|
||||
"MinGit-2.53.0.2-64-bit.zip",
|
||||
"MinGit-2.53.0.2-arm64.zip",
|
||||
"MinGit-2.55.0.3-64-bit.zip",
|
||||
"MinGit-2.55.0.3-arm64.zip",
|
||||
]
|
||||
fallback_urls = {
|
||||
"MinGit-2.53.0.2-arm64.zip": "https://github.com/git-for-windows/git/releases/download/v2.53.0.windows.2/MinGit-2.53.0.2-arm64.zip",
|
||||
"MinGit-2.53.0.2-64-bit.zip": "https://github.com/git-for-windows/git/releases/download/v2.53.0.windows.2/MinGit-2.53.0.2-64-bit.zip",
|
||||
"MinGit-2.55.0.3-arm64.zip": "https://github.com/git-for-windows/git/releases/download/v2.55.0.windows.3/MinGit-2.55.0.3-arm64.zip",
|
||||
"MinGit-2.55.0.3-64-bit.zip": "https://github.com/git-for-windows/git/releases/download/v2.55.0.windows.3/MinGit-2.55.0.3-64-bit.zip",
|
||||
}
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ if ! command -v opengrep >/dev/null 2>&1; then
|
|||
error: 'opengrep' not found on PATH.
|
||||
|
||||
Install with one of:
|
||||
curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/v1.22.0/install.sh | bash -s -- -v v1.22.0
|
||||
curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/v1.25.0/install.sh | bash -s -- -v v1.25.0
|
||||
brew install opengrep/tap/opengrep
|
||||
pipx install opengrep
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ write_empty_sarif() {
|
|||
"driver": {
|
||||
"name": "Opengrep OSS",
|
||||
"informationUri": "https://opengrep.dev",
|
||||
"semanticVersion": "1.22.0",
|
||||
"semanticVersion": "1.25.0",
|
||||
"rules": []
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ export async function execCommand(
|
|||
reject: false,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(proc);
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(proc.nodeChildProcess);
|
||||
|
||||
let stdout: OutputCapture = { text: "", truncatedChars: 0 };
|
||||
let stderr: OutputCapture = { text: "", truncatedChars: 0 };
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ export function createLocalBashOperations(options?: { shellPath?: string }): Bas
|
|||
reject: false,
|
||||
stdio: [invocation.stdin, "pipe", "pipe"],
|
||||
});
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(child);
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(child.nodeChildProcess);
|
||||
let timedOut = false;
|
||||
let timeoutHandle: NodeJS.Timeout | undefined;
|
||||
const timeoutMs = resolveBashTimeoutMs(timeout);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ vi.mock("../../utils/tools-manager.js", () => ({
|
|||
|
||||
const tempDirs = useAutoCleanupTempDirTracker(afterEach);
|
||||
type MockChild = ChildProcessWithoutNullStreams & {
|
||||
nodeChildProcess: ChildProcessWithoutNullStreams;
|
||||
stdout: PassThrough;
|
||||
stderr: PassThrough;
|
||||
killMock: ReturnType<typeof vi.fn>;
|
||||
|
|
@ -30,7 +31,7 @@ afterEach(() => {
|
|||
|
||||
function createChild(): MockChild {
|
||||
const kill = vi.fn(() => true);
|
||||
return Object.assign(new EventEmitter(), {
|
||||
const child = Object.assign(new EventEmitter(), {
|
||||
stdin: new PassThrough(),
|
||||
stdout: new PassThrough(),
|
||||
stderr: new PassThrough(),
|
||||
|
|
@ -38,6 +39,8 @@ function createChild(): MockChild {
|
|||
kill,
|
||||
killMock: kill,
|
||||
}) as unknown as MockChild;
|
||||
child.nodeChildProcess = child;
|
||||
return child;
|
||||
}
|
||||
|
||||
it("rejects partial fd output when fd exits with an error", async () => {
|
||||
|
|
|
|||
|
|
@ -279,13 +279,13 @@ export function createFindToolDefinition(
|
|||
reject: false,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
releaseChildProcessOutputAfterExit(child);
|
||||
releaseChildProcessOutputAfterExit(child.nodeChildProcess);
|
||||
const rl = createInterface({ input: child.stdout });
|
||||
let stderr = "";
|
||||
const lines: string[] = [];
|
||||
|
||||
stopChild = () => {
|
||||
if (!child.killed) {
|
||||
if (!child.nodeChildProcess.killed) {
|
||||
child.kill();
|
||||
}
|
||||
};
|
||||
|
|
@ -318,12 +318,12 @@ export function createFindToolDefinition(
|
|||
lines.push(line);
|
||||
});
|
||||
|
||||
child.on("error", (error) => {
|
||||
child.nodeChildProcess.on("error", (error) => {
|
||||
cleanup();
|
||||
settle(() => reject(new Error(`Failed to run fd: ${error.message}`)));
|
||||
});
|
||||
|
||||
child.on("close", (code) => {
|
||||
child.nodeChildProcess.on("close", (code) => {
|
||||
cleanup();
|
||||
if (signal?.aborted) {
|
||||
settle(() => reject(new Error("Operation aborted")));
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@ afterEach(() => {
|
|||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
type MockChild = ChildProcessWithoutNullStreams & { stdout: PassThrough; stderr: PassThrough };
|
||||
type MockChild = ChildProcessWithoutNullStreams & {
|
||||
nodeChildProcess: ChildProcessWithoutNullStreams;
|
||||
stdout: PassThrough;
|
||||
stderr: PassThrough;
|
||||
};
|
||||
|
||||
function createChild(): MockChild {
|
||||
let killed = false;
|
||||
|
|
@ -34,6 +38,7 @@ function createChild(): MockChild {
|
|||
killed = true;
|
||||
return true;
|
||||
});
|
||||
child.nodeChildProcess = child;
|
||||
return child;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
*
|
||||
* Searches files with ripgrep/local operations, optional context, and bounded output rendering.
|
||||
*/
|
||||
import type { ChildProcess } from "node:child_process";
|
||||
import { readFileSync, statSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { createInterface } from "node:readline";
|
||||
|
|
@ -160,7 +159,12 @@ export function createGrepToolDefinition(
|
|||
// Keep cancellation live from the first await through async result formatting.
|
||||
// Settlement owns listener cleanup; spawned children stop without waiting for close.
|
||||
let settled = false;
|
||||
let child: ChildProcess | undefined;
|
||||
let child:
|
||||
| {
|
||||
nodeChildProcess: { killed: boolean };
|
||||
kill: () => void;
|
||||
}
|
||||
| undefined;
|
||||
let childClosed = false;
|
||||
let rl: ReturnType<typeof createInterface> | undefined;
|
||||
let killedDueToLimit = false;
|
||||
|
|
@ -178,7 +182,7 @@ export function createGrepToolDefinition(
|
|||
return true;
|
||||
};
|
||||
const stopChild = (dueToLimit = false) => {
|
||||
if (child && !childClosed && !child.killed) {
|
||||
if (child && !childClosed && !child.nodeChildProcess.killed) {
|
||||
killedDueToLimit = dueToLimit;
|
||||
child.kill();
|
||||
}
|
||||
|
|
@ -267,7 +271,7 @@ export function createGrepToolDefinition(
|
|||
reject: false,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
releaseChildProcessOutputAfterExit(spawnedChild);
|
||||
releaseChildProcessOutputAfterExit(spawnedChild.nodeChildProcess);
|
||||
child = spawnedChild;
|
||||
rl = createInterface({ input: spawnedChild.stdout });
|
||||
let stderr = "";
|
||||
|
|
@ -358,11 +362,11 @@ export function createGrepToolDefinition(
|
|||
}
|
||||
});
|
||||
|
||||
spawnedChild.on("error", (error) => {
|
||||
spawnedChild.nodeChildProcess.on("error", (error) => {
|
||||
childClosed = true;
|
||||
settle(() => reject(new Error(`Failed to run ripgrep: ${error.message}`)));
|
||||
});
|
||||
spawnedChild.on("close", (code) => {
|
||||
spawnedChild.nodeChildProcess.on("close", (code) => {
|
||||
childClosed = true;
|
||||
void (async () => {
|
||||
if (settled) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ function fakeChild(result: Promise<unknown>) {
|
|||
const kill = vi.fn();
|
||||
const stderr = new PassThrough();
|
||||
return {
|
||||
child: Object.assign(result, { kill, stderr, unref }),
|
||||
child: Object.assign(result, { kill, stderr, nodeChildProcess: { unref } }),
|
||||
kill,
|
||||
stderr,
|
||||
unref,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ async function observeXdgOpenStartup(command: OpenPathCommand): Promise<void> {
|
|||
reject: true,
|
||||
stdio: ["ignore", "ignore", "pipe"],
|
||||
});
|
||||
child.unref();
|
||||
child.nodeChildProcess.unref();
|
||||
let stderrText = "";
|
||||
const stderr = child.stderr;
|
||||
stderr?.setEncoding("utf8");
|
||||
|
|
|
|||
|
|
@ -584,7 +584,6 @@ export function isFileLogLevelEnabled(level: LogLevel): boolean {
|
|||
function buildLogger(settings: ResolvedRuntimeSettings): TsLogger<LogObj> {
|
||||
const logger = new TsLogger<LogObj>({
|
||||
name: "openclaw",
|
||||
// Custom structured redaction runs at each transport boundary; avoid tslog pre-masking divergent records.
|
||||
maskValuesOfKeys: [],
|
||||
minLevel: levelToMinLevel(settings.level),
|
||||
type: "hidden", // no ansi formatting
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ describe.skipIf(process.platform === "win32")("releaseChildProcessOutputAfterExi
|
|||
reject: false,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(child);
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(child.nodeChildProcess);
|
||||
let output = "";
|
||||
child.stdout?.on("data", (chunk: Buffer) => {
|
||||
output += chunk.toString();
|
||||
|
|
@ -36,7 +36,7 @@ describe.skipIf(process.platform === "win32")("releaseChildProcessOutputAfterExi
|
|||
// writes while JS is parked, so its pipe data and the idle timer are both
|
||||
// ready when the event loop resumes.
|
||||
await new Promise<void>((resolve) => {
|
||||
child?.once("exit", () => {
|
||||
child?.nodeChildProcess.once("exit", () => {
|
||||
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 250);
|
||||
resolve();
|
||||
});
|
||||
|
|
@ -53,7 +53,7 @@ describe.skipIf(process.platform === "win32")("releaseChildProcessOutputAfterExi
|
|||
reject: false,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(child);
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(child.nodeChildProcess);
|
||||
let output = "";
|
||||
child.stdout?.on("data", (chunk: Buffer) => {
|
||||
output += chunk.toString();
|
||||
|
|
|
|||
|
|
@ -170,13 +170,14 @@ async function runCommandWithOutputEncoding(
|
|||
stripFinalNewline: false,
|
||||
windowsVerbatimArguments: options.windowsVerbatimArguments,
|
||||
});
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(child);
|
||||
child.once("exit", (code, signalValue) => {
|
||||
const nodeChild = child.nodeChildProcess;
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(nodeChild);
|
||||
nodeChild.once("exit", (code, signalValue) => {
|
||||
childExited = true;
|
||||
childExitState = { code, signal: signalValue };
|
||||
});
|
||||
const terminationController = createCommandTerminationController({
|
||||
child,
|
||||
child: nodeChild,
|
||||
cancelController,
|
||||
baseEnv,
|
||||
env,
|
||||
|
|
@ -374,7 +375,7 @@ async function runCommandWithOutputEncoding(
|
|||
const isCauseLessWindowsShimResult =
|
||||
!termination &&
|
||||
invocation.usesWindowsExitCodeShim &&
|
||||
typeof child.pid === "number" &&
|
||||
typeof nodeChild.pid === "number" &&
|
||||
result.code === undefined &&
|
||||
result.cause === undefined &&
|
||||
!result.timedOut &&
|
||||
|
|
@ -392,8 +393,8 @@ async function runCommandWithOutputEncoding(
|
|||
if (
|
||||
childExitState?.code != null ||
|
||||
childExitState?.signal != null ||
|
||||
child.exitCode != null ||
|
||||
child.signalCode != null
|
||||
nodeChild.exitCode != null ||
|
||||
nodeChild.signalCode != null
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -421,10 +422,10 @@ async function runCommandWithOutputEncoding(
|
|||
throw error;
|
||||
}
|
||||
|
||||
const resolvedSignal = result.signal ?? childExitState?.signal ?? child.signalCode ?? null;
|
||||
const resolvedSignal = result.signal ?? childExitState?.signal ?? nodeChild.signalCode ?? null;
|
||||
const resolvedCode = resolveProcessExitCode({
|
||||
explicitCode: result.exitCode ?? childExitState?.code,
|
||||
childExitCode: child.exitCode,
|
||||
childExitCode: nodeChild.exitCode,
|
||||
resolvedSignal,
|
||||
usesWindowsExitCodeShim: invocation.usesWindowsExitCodeShim,
|
||||
timedOut: termination === "timeout",
|
||||
|
|
@ -474,7 +475,7 @@ async function runCommandWithOutputEncoding(
|
|||
};
|
||||
|
||||
return {
|
||||
pid: child.pid,
|
||||
pid: nodeChild.pid,
|
||||
stdout: decodeCapturedOutput(stdoutCapture, stdoutCaptureMode),
|
||||
stderr: decodeCapturedOutput(stderrCapture, stderrCaptureMode),
|
||||
stdoutTruncatedBytes: stdoutCapture.truncatedBytes || undefined,
|
||||
|
|
@ -485,7 +486,7 @@ async function runCommandWithOutputEncoding(
|
|||
stderrCapture.preservedLines.length > 0 ? stderrCapture.preservedLines : undefined,
|
||||
code: normalizedCode,
|
||||
signal: resolvedSignal,
|
||||
killed: child.killed,
|
||||
killed: nodeChild.killed,
|
||||
termination: termination === "output-limit" ? "signal" : termination,
|
||||
noOutputTimedOut: termination === "no-output-timeout",
|
||||
outputLimitExceeded: termination === "output-limit" || undefined,
|
||||
|
|
|
|||
|
|
@ -55,13 +55,8 @@ export function shouldSpawnWithShell(params: {
|
|||
return false;
|
||||
}
|
||||
|
||||
type SpawnCommandOptions = Omit<
|
||||
ExecaOptions,
|
||||
"env" | "extendEnv" | "shell" | "windowsHide" | "windowsVerbatimArguments"
|
||||
> & {
|
||||
type SpawnCommandOptions = ExecaOptions & {
|
||||
baseEnv?: NodeJS.ProcessEnv;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
windowsVerbatimArguments?: boolean;
|
||||
};
|
||||
|
||||
export function spawnCommandWithInvocation<
|
||||
|
|
@ -88,7 +83,7 @@ export function spawnCommandWithInvocation<
|
|||
shell: false,
|
||||
windowsHide: invocation.windowsHide,
|
||||
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
||||
}) as unknown as ResultPromise<OptionsType>;
|
||||
} as ExecaOptions) as unknown as ResultPromise<OptionsType>;
|
||||
return { child, invocation };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export async function runExec(
|
|||
stripFinalNewline: false,
|
||||
timeout,
|
||||
});
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(subprocess);
|
||||
const releaseOutput = releaseChildProcessOutputAfterExit(subprocess.nodeChildProcess);
|
||||
const { stdout, stderr } = await subprocess.finally(releaseOutput);
|
||||
const windowsEncoding = resolveWindowsConsoleEncoding();
|
||||
const decodedStdout = decodeWindowsOutputBuffer({
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ type MockResult = {
|
|||
};
|
||||
|
||||
type MockSubprocess = EventEmitter & {
|
||||
nodeChildProcess: MockSubprocess;
|
||||
exitCode: number | null;
|
||||
finish: (result?: Partial<MockResult>) => void;
|
||||
kill: ReturnType<typeof vi.fn>;
|
||||
|
|
@ -53,6 +54,7 @@ function createMockSubprocess(params?: {
|
|||
stdoutChunks?: Buffer[];
|
||||
}): MockSubprocess {
|
||||
const child = new EventEmitter() as MockSubprocess;
|
||||
child.nodeChildProcess = child;
|
||||
child.pid = 1234;
|
||||
child.exitCode = null;
|
||||
child.signalCode = null;
|
||||
|
|
@ -67,7 +69,7 @@ function createMockSubprocess(params?: {
|
|||
const completion = new Promise<MockResult>((resolvePromise) => {
|
||||
resolve = resolvePromise;
|
||||
});
|
||||
// oxlint-disable-next-line unicorn/no-thenable -- Stub matches Execa's event-emitting promise shape.
|
||||
// oxlint-disable-next-line unicorn/no-thenable -- Stub combines Execa's promise with its exposed Node child.
|
||||
child.then = completion.then.bind(completion);
|
||||
child.catch = completion.catch.bind(completion);
|
||||
child.finally = completion.finally.bind(completion);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ describe("check-workflows", () => {
|
|||
|
||||
expect(result.status).toBe(0);
|
||||
expect(readFileSync(markerPath, "utf8")).toContain(
|
||||
"github.com/rhysd/actionlint/cmd/actionlint@v1.7.11",
|
||||
"github.com/rhysd/actionlint/cmd/actionlint@v1.7.12",
|
||||
);
|
||||
const preCommitArgs = readFileSync(preCommitMarkerPath, "utf8");
|
||||
expect(preCommitArgs).toContain("run --config .pre-commit-config.yaml zizmor --files");
|
||||
|
|
|
|||
|
|
@ -112,9 +112,9 @@ describe("OpenClaw performance workflow", () => {
|
|||
const workflow = readFileSync(WORKFLOW, "utf8");
|
||||
const installRun = findStep("Install OCM and Kova").run ?? "";
|
||||
|
||||
expect(workflow).toContain("OCM_VERSION: v0.2.25");
|
||||
expect(workflow).toContain("OCM_VERSION: v0.2.29");
|
||||
expect(workflow).toContain(
|
||||
"OCM_LINUX_X64_SHA256: 57530199d21eb5bfa29695749928b40fd2869484c7edff69b7c65bfc84f2f1aa",
|
||||
"OCM_LINUX_X64_SHA256: d966098d6ba2bc10891be3c76e162a37b07f28c4f51da75d2eb509886eb7e1cf",
|
||||
);
|
||||
expect(installRun).toContain(
|
||||
'"https://github.com/shakkernerd/ocm/releases/download/${OCM_VERSION}/ocm-x86_64-unknown-linux-gnu.tar.gz"',
|
||||
|
|
|
|||
|
|
@ -1455,8 +1455,8 @@ exit 0
|
|||
expect(combined).toContain("MinGit-");
|
||||
expect(combined).toContain("portable-git");
|
||||
expect(combined).toContain("where.exe git.exe");
|
||||
expect(windowsGit.indexOf('"MinGit-2.53.0.2-64-bit.zip"')).toBeLessThan(
|
||||
windowsGit.indexOf('"MinGit-2.53.0.2-arm64.zip"'),
|
||||
expect(windowsGit.indexOf('"MinGit-2.55.0.3-64-bit.zip"')).toBeLessThan(
|
||||
windowsGit.indexOf('"MinGit-2.55.0.3-arm64.zip"'),
|
||||
);
|
||||
expect(
|
||||
combined.match(/curl\.exe -fsSL --connect-timeout 10 --max-time 120 --retry 2/g),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { prepareMinGitZip } from "../../scripts/e2e/parallels/windows-git.ts";
|
|||
|
||||
describe("Parallels Windows MinGit preparation", () => {
|
||||
it("bounds the host asset download across connections, transfers, and retries", async () => {
|
||||
const assetName = "MinGit-2.53.0.2-64-bit.zip";
|
||||
const assetName = "MinGit-2.55.0.3-64-bit.zip";
|
||||
const assetUrl = `https://example.test/${assetName}`;
|
||||
const targetDir = path.join("tmp", "windows-smoke");
|
||||
const targetPath = path.join(targetDir, assetName);
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ describe("run-opengrep.sh", () => {
|
|||
);
|
||||
expect(sarif.version).toBe("2.1.0");
|
||||
expect(sarif.runs[0].tool.driver.name).toBe("Opengrep OSS");
|
||||
expect(sarif.runs[0].tool.driver.semanticVersion).toBe("1.22.0");
|
||||
expect(sarif.runs[0].tool.driver.semanticVersion).toBe("1.25.0");
|
||||
expect(sarif.runs[0].results).toEqual([]);
|
||||
expect(fs.existsSync(argsPath)).toBe(false);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
"jsdom": "29.1.1",
|
||||
"openclaw": "workspace:*",
|
||||
"playwright": "1.61.1",
|
||||
"vite": "8.1.3",
|
||||
"vite": "8.1.5",
|
||||
"vitest": "4.1.10"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue