





















@@ -26,6 +26,7 @@ import {
2626createSafeNpmInstallArgs,
2727createSafeNpmInstallEnv,
2828} from "../infra/safe-package-install.js";
29+import { compareComparableSemver, parseComparableSemver } from "../infra/semver-compare.js";
2930import { runCommandWithTimeout } from "../process/exec.js";
3031import { createLazyImportLoader } from "../shared/lazy-promise.js";
3132import { normalizeOptionalString } from "../shared/string-coerce.js";
@@ -160,18 +161,13 @@ function isNpmPackageNotFoundMessage(error: string): boolean {
160161return /E404|404 not found|not in this registry/i.test(normalized);
161162}
162163163-function compareStableSemver(a: string, b: string): number {
164-const parse = (value: string): [number, number, number] => {
165-const match = /^v?(\d+)\.(\d+)\.(\d+)/.exec(value.trim());
166-return [Number(match?.[1] ?? 0), Number(match?.[2] ?? 0), Number(match?.[3] ?? 0)];
167-};
168-const left = parse(a);
169-const right = parse(b);
170-return left[0] - right[0] || left[1] - right[1] || left[2] - right[2];
164+function compareNpmSemver(a: string, b: string): number {
165+return compareComparableSemver(parseComparableSemver(a), parseComparableSemver(b)) ?? 0;
171166}
172167173168type TrustedOfficialPrereleaseResolution =
174169| { kind: "stable"; resolution: NpmSpecResolution }
170+| { kind: "prerelease-only"; resolution: NpmSpecResolution }
175171| { kind: "allow-prerelease-only" };
176172177173async function resolveTrustedOfficialPrereleaseResolution(params: {
@@ -208,10 +204,28 @@ async function resolveTrustedOfficialPrereleaseResolution(params: {
208204);
209205const stableVersion = semverVersions
210206.filter((value) => !isPrereleaseSemverVersion(value))
211-.toSorted(compareStableSemver)
207+.toSorted(compareNpmSemver)
212208.at(-1);
213209if (!stableVersion) {
214-if (semverVersions.length > 0 && semverVersions.every(isPrereleaseSemverVersion)) {
210+const prereleaseVersion = semverVersions
211+.filter(isPrereleaseSemverVersion)
212+.toSorted(compareNpmSemver)
213+.at(-1);
214+if (prereleaseVersion && semverVersions.every(isPrereleaseSemverVersion)) {
215+if (prereleaseVersion !== params.resolvedPrereleaseVersion) {
216+const prereleaseSpec = `${params.spec.name}@${prereleaseVersion}`;
217+const metadataResult = await resolveNpmSpecMetadata({
218+spec: prereleaseSpec,
219+timeoutMs: params.timeoutMs,
220+});
221+if (!metadataResult.ok) {
222+return null;
223+}
224+params.logger.warn?.(
225+`Resolved ${params.spec.raw} to prerelease version ${params.resolvedPrereleaseVersion}; using newest prerelease ${prereleaseSpec} because this trusted official OpenClaw package has no stable npm versions yet.`,
226+);
227+return { kind: "prerelease-only", resolution: metadataResult.metadata };
228+}
215229params.logger.warn?.(
216230`Resolved ${params.spec.raw} to prerelease version ${params.resolvedPrereleaseVersion}; allowing it because this trusted official OpenClaw package has no stable npm versions yet.`,
217231);
@@ -1265,7 +1279,7 @@ export async function installPluginFromNpmSpec(
12651279 logger,
12661280})
12671281 : null;
1268-if (trustedResolution?.kind === "stable") {
1282+if (trustedResolution?.kind === "stable" || trustedResolution?.kind === "prerelease-only") {
12691283Object.assign(npmResolution, trustedResolution.resolution, {
12701284resolvedAt: npmResolution.resolvedAt,
12711285});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。