diff --git a/src/plugins/min-host-version.test.ts b/src/plugins/min-host-version.test.ts index bdede68881b..2df69bbade2 100644 --- a/src/plugins/min-host-version.test.ts +++ b/src/plugins/min-host-version.test.ts @@ -62,6 +62,10 @@ describe("min-host-version", () => { it("parses semver floors", () => { expect(parseMinHostVersionRequirement(">=2026.3.22")).toEqual(MIN_HOST_REQUIREMENT); expect(parseMinHostVersionRequirement(">=2026.5.1-beta.1")).toEqual(BETA_MIN_HOST_REQUIREMENT); + expect(parseMinHostVersionRequirement(">=2026.5.1+20260501")).toEqual({ + raw: ">=2026.5.1+20260501", + minimumLabel: "2026.5.1+20260501", + }); }); it("can parse legacy bare semver floors for runtime upgrade compatibility", () => { diff --git a/src/plugins/min-host-version.ts b/src/plugins/min-host-version.ts index 255367eaf5e..29155c3330d 100644 --- a/src/plugins/min-host-version.ts +++ b/src/plugins/min-host-version.ts @@ -1,8 +1,9 @@ import { isAtLeast, parseSemver } from "../infra/runtime-guard.js"; export const MIN_HOST_VERSION_FORMAT = - 'openclaw.install.minHostVersion must use a semver floor in the form ">=x.y.z" or ">=x.y.z-prerelease"'; -const MIN_HOST_VERSION_RE = /^>=(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?$/; + 'openclaw.install.minHostVersion must use a semver floor in the form ">=x.y.z[-prerelease][+build]"'; +const SEMVER_LABEL_RE = String.raw`\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?`; +const MIN_HOST_VERSION_RE = new RegExp(`^>=(${SEMVER_LABEL_RE})$`); const LEGACY_MIN_HOST_VERSION_RE = /^(\d+)\.(\d+)\.(\d+)$/; export type MinHostVersionRequirement = { @@ -40,7 +41,7 @@ export function parseMinHostVersionRequirement( if (!match) { return null; } - const minimumLabel = `${match[1]}.${match[2]}.${match[3]}${match[4] ?? ""}`; + const minimumLabel = match.length >= 4 ? `${match[1]}.${match[2]}.${match[3]}` : (match[1] ?? ""); if (!parseSemver(minimumLabel)) { return null; } diff --git a/test/release-check.test.ts b/test/release-check.test.ts index 1838002e1cf..652d5ac2c93 100644 --- a/test/release-check.test.ts +++ b/test/release-check.test.ts @@ -211,7 +211,7 @@ describe("collectBundledExtensionManifestErrors", () => { }, ]), ).toEqual([ - "bundled extension 'broken' manifest invalid | openclaw.install.minHostVersion must use a semver floor in the form \">=x.y.z\"", + "bundled extension 'broken' manifest invalid | openclaw.install.minHostVersion must use a semver floor in the form \">=x.y.z[-prerelease][+build]\"", ]); });