Skip to content

Commit b7e8f67

Browse files
committed
Merge origin/main into PR 73950
2 parents d3a58fb + c4b9f54 commit b7e8f67

133 files changed

Lines changed: 5497 additions & 2817 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/setup-pnpm-store-cache/ensure-node.sh

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ openclaw_node_version_matches() {
88
fi
99
case "$requested" in
1010
*x)
11-
[[ "${actual%%.*}" == "${requested%%.*}" ]]
11+
[[ "${actual%%.*}" == "${requested%%.*}" ]] || return 1
12+
if [[ "${requested%%.*}" == "22" ]]; then
13+
openclaw_node_version_at_least "$actual" "22.19.0"
14+
fi
1215
;;
1316
*.*.*)
1417
[[ "$actual" == "$requested" ]]
@@ -22,6 +25,28 @@ openclaw_node_version_matches() {
2225
esac
2326
}
2427

28+
openclaw_node_version_at_least() {
29+
local actual="$1"
30+
local minimum="$2"
31+
local actual_major actual_minor actual_patch minimum_major minimum_minor minimum_patch
32+
IFS=. read -r actual_major actual_minor actual_patch <<< "$actual"
33+
IFS=. read -r minimum_major minimum_minor minimum_patch <<< "$minimum"
34+
actual_minor="${actual_minor:-0}"
35+
actual_patch="${actual_patch:-0}"
36+
minimum_minor="${minimum_minor:-0}"
37+
minimum_patch="${minimum_patch:-0}"
38+
39+
if (( actual_major != minimum_major )); then
40+
(( actual_major > minimum_major ))
41+
return
42+
fi
43+
if (( actual_minor != minimum_minor )); then
44+
(( actual_minor > minimum_minor ))
45+
return
46+
fi
47+
(( actual_patch >= minimum_patch ))
48+
}
49+
2550
openclaw_active_node_version() {
2651
node -p 'process.versions.node' 2>/dev/null || true
2752
}
@@ -57,6 +82,9 @@ openclaw_find_toolcache_node() {
5782
"/Users/runner/hostedtoolcache" \
5883
"/c/hostedtoolcache/windows"
5984
do
85+
if [[ ! -d "$root" && "$root" == *\\* ]] && command -v cygpath >/dev/null 2>&1; then
86+
root="$(cygpath -u "$root" 2>/dev/null || printf '%s' "$root")"
87+
fi
6088
if [[ -d "$root/node" ]]; then
6189
roots+=("$root/node")
6290
elif [[ "$(basename "$root")" == "node" && -d "$root" ]]; then
@@ -108,6 +136,9 @@ openclaw_node_download_platform() {
108136
Linux:aarch64 | Linux:arm64) printf 'linux-arm64\n' ;;
109137
Darwin:x86_64) printf 'darwin-x64\n' ;;
110138
Darwin:arm64) printf 'darwin-arm64\n' ;;
139+
MINGW*:x86_64 | MSYS*:x86_64 | CYGWIN*:x86_64 | MINGW*:AMD64 | MSYS*:AMD64 | CYGWIN*:AMD64)
140+
printf 'win-x64\n'
141+
;;
111142
*)
112143
return 1
113144
;;
@@ -120,8 +151,24 @@ openclaw_download_node() {
120151
version="$(openclaw_resolve_node_download_version "$requested_node")"
121152
platform="$(openclaw_node_download_platform)" || return 1
122153
install_root="${RUNNER_TEMP:-/tmp}/openclaw-node-${version}-${platform}"
123-
archive_url="https://nodejs.org/dist/${version}/node-${version}-${platform}.tar.xz"
124154
mkdir -p "$install_root"
155+
if [[ "$platform" == win-* ]]; then
156+
local archive_path
157+
archive_url="https://nodejs.org/dist/${version}/node-${version}-${platform}.zip"
158+
archive_path="${RUNNER_TEMP:-/tmp}/node-${version}-${platform}.zip"
159+
echo "Downloading Node ${version} from ${archive_url}"
160+
curl -fsSL "$archive_url" -o "$archive_path"
161+
if command -v powershell.exe >/dev/null 2>&1 && command -v cygpath >/dev/null 2>&1; then
162+
powershell.exe -NoLogo -NoProfile -Command \
163+
"Expand-Archive -LiteralPath '$(cygpath -w "$archive_path")' -DestinationPath '$(cygpath -w "$install_root")' -Force"
164+
else
165+
unzip -q "$archive_path" -d "$install_root"
166+
fi
167+
openclaw_prepend_node_bin "$install_root/node-${version}-${platform}"
168+
return 0
169+
fi
170+
171+
archive_url="https://nodejs.org/dist/${version}/node-${version}-${platform}.tar.xz"
125172
echo "Downloading Node ${version} from ${archive_url}"
126173
curl -fsSL "$archive_url" | tar -xJ -C "$install_root" --strip-components=1
127174
openclaw_prepend_node_bin "$install_root/bin"

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,7 +1507,7 @@ jobs:
15071507
15081508
- name: Setup Node.js
15091509
env:
1510-
REQUESTED_NODE_VERSION: "24.x"
1510+
REQUESTED_NODE_VERSION: "22.x"
15111511
run: |
15121512
set -euo pipefail
15131513
source .github/actions/setup-pnpm-store-cache/ensure-node.sh
@@ -1516,7 +1516,7 @@ jobs:
15161516
- name: Setup pnpm
15171517
uses: ./.github/actions/setup-pnpm-store-cache
15181518
with:
1519-
node-version: 24.x
1519+
node-version: 22.x
15201520

15211521
- name: Runtime versions
15221522
run: |

CHANGELOG.md

Lines changed: 42 additions & 146 deletions
Large diffs are not rendered by default.

extensions/amazon-bedrock-mantle/npm-shrinkwrap.json

Lines changed: 3 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/amazon-bedrock/npm-shrinkwrap.json

Lines changed: 0 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/anthropic-vertex/npm-shrinkwrap.json

Lines changed: 0 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/browser/src/browser/screenshot.test.ts

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,6 @@ import { describe, expect, it } from "vitest";
55
import { normalizeBrowserScreenshot } from "./screenshot.js";
66

77
describe("browser screenshot normalization", () => {
8-
const unavailableImageBackend = process.platform === "win32" ? "sips" : "windows-native";
9-
10-
async function withUnavailableImageBackend<T>(fn: () => Promise<T>): Promise<T> {
11-
const previousBackend = process.env.OPENCLAW_IMAGE_BACKEND;
12-
process.env.OPENCLAW_IMAGE_BACKEND = unavailableImageBackend;
13-
try {
14-
return await fn();
15-
} finally {
16-
if (previousBackend === undefined) {
17-
delete process.env.OPENCLAW_IMAGE_BACKEND;
18-
} else {
19-
process.env.OPENCLAW_IMAGE_BACKEND = previousBackend;
20-
}
21-
}
22-
}
23-
248
it("shrinks oversized images to <=2000x2000 and <=5MB", async () => {
259
const bigPng = createSolidPngBuffer(2100, 2100, { r: 12, g: 34, b: 56 });
2610

@@ -47,18 +31,4 @@ describe("browser screenshot normalization", () => {
4731

4832
expect(normalized.buffer.equals(jpeg)).toBe(true);
4933
});
50-
51-
it("rejects screenshots above max side when no image processor is available", async () => {
52-
const png = createSolidPngBuffer(420, 120, { r: 12, g: 34, b: 56 });
53-
expect(png.byteLength).toBeLessThan(5 * 1024 * 1024);
54-
55-
await withUnavailableImageBackend(async () => {
56-
await expect(
57-
normalizeBrowserScreenshot(png, {
58-
maxSide: 120,
59-
maxBytes: 5 * 1024 * 1024,
60-
}),
61-
).rejects.toThrow(/image processor unavailable/i);
62-
});
63-
});
6434
});

extensions/codex/npm-shrinkwrap.json

Lines changed: 0 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/codex/src/app-server/client-factory.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,13 @@ export const defaultCodexAppServerClientFactory: CodexAppServerClientFactory = (
2222
import("./shared-client.js").then(({ getSharedCodexAppServerClient }) =>
2323
getSharedCodexAppServerClient({ startOptions, authProfileId, agentDir, config }),
2424
);
25+
26+
export const defaultLeasedCodexAppServerClientFactory: CodexAppServerClientFactory = (
27+
startOptions,
28+
authProfileId,
29+
agentDir,
30+
config,
31+
) =>
32+
import("./shared-client.js").then(({ getLeasedSharedCodexAppServerClient }) =>
33+
getLeasedSharedCodexAppServerClient({ startOptions, authProfileId, agentDir, config }),
34+
);

extensions/codex/src/app-server/models.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,13 @@ async function withCodexAppServerModelClient<T>(
7474
): Promise<T> {
7575
const timeoutMs = options.timeoutMs ?? 2500;
7676
const useSharedClient = options.sharedClient !== false;
77-
const { createIsolatedCodexAppServerClient, getSharedCodexAppServerClient } =
78-
await import("./shared-client.js");
77+
const {
78+
createIsolatedCodexAppServerClient,
79+
getLeasedSharedCodexAppServerClient,
80+
releaseLeasedSharedCodexAppServerClient,
81+
} = await import("./shared-client.js");
7982
const client = useSharedClient
80-
? await getSharedCodexAppServerClient({
83+
? await getLeasedSharedCodexAppServerClient({
8184
startOptions: options.startOptions,
8285
timeoutMs,
8386
authProfileId: options.authProfileId,
@@ -94,7 +97,9 @@ async function withCodexAppServerModelClient<T>(
9497
try {
9598
return await run({ client, timeoutMs });
9699
} finally {
97-
if (!useSharedClient) {
100+
if (useSharedClient) {
101+
releaseLeasedSharedCodexAppServerClient(client);
102+
} else {
98103
client.close();
99104
}
100105
}

0 commit comments

Comments
 (0)