99 normalizeOptionalString ,
1010} from "@openclaw/normalization-core/string-coerce" ;
1111import { normalizeStringEntries } from "@openclaw/normalization-core/string-normalization" ;
12- import { parse as parseSemverVersion , prerelease as parseSemverPrerelease } from "semver" ;
12+ import { prerelease as parseSemverPrerelease , satisfies as satisfiesSemver } from "semver" ;
1313import { retryClawHubRead } from "./clawhub-retry.js" ;
1414import { sha256Base64 , sha256Hex as digestSha256Hex } from "./crypto-digest.js" ;
1515import { readResponseTextSnippet , readResponseWithLimit } from "./http-body.js" ;
@@ -19,7 +19,6 @@ import {
1919 parseStrictPositiveInteger ,
2020} from "./parse-finite-number.js" ;
2121import { isAtLeast , parseSemver } from "./runtime-guard.js" ;
22- import { compareValidSemver } from "./semver.js" ;
2322import { createTempDownloadTarget } from "./temp-download.js" ;
2423export { parseClawHubPluginSpec } from "./clawhub-spec.js" ;
2524
@@ -546,35 +545,6 @@ function normalizePartialComparableVersion(version: string): {
546545 : { version : trimmed , isPartial : false } ;
547546}
548547
549- function compareSemver ( left : string , right : string ) : number | null {
550- const normalizedLeft = normalizePartialComparableVersion ( left ) . version ;
551- const normalizedRight = normalizePartialComparableVersion ( right ) . version ;
552- return compareValidSemver ( normalizedLeft , normalizedRight ) ;
553- }
554-
555- function upperBoundForCaret ( version : string ) : string | null {
556- const parsed = parseSemverVersion ( normalizePartialComparableVersion ( version ) . version ) ;
557- if ( ! parsed ) {
558- return null ;
559- }
560- if ( parsed . major > 0 ) {
561- return `${ parsed . major + 1 } .0.0` ;
562- }
563- if ( parsed . minor > 0 ) {
564- return `0.${ parsed . minor + 1 } .0` ;
565- }
566- return `0.0.${ parsed . patch + 1 } ` ;
567- }
568-
569- function matchWildcardComparator ( token : string ) : "any" | "none" | null {
570- const match = / ^ ( > = | < = | > | < | = | \^ | ~ ) ? \s * ( [ * x X ] ) $ / . exec ( token ) ;
571- if ( ! match ) {
572- return null ;
573- }
574- const operator = match [ 1 ] ;
575- return operator === ">" || operator === "<" ? "none" : "any" ;
576- }
577-
578548function shouldPreservePluginApiPrereleaseFloor ( target : string ) : boolean {
579549 return Boolean ( parseSemverPrerelease ( normalizePartialComparableVersion ( target ) . version ) ) ;
580550}
@@ -594,49 +564,28 @@ function satisfiesComparator(version: string, token: string): boolean {
594564 if ( ! trimmed ) {
595565 return true ;
596566 }
597- const wildcard = matchWildcardComparator ( trimmed ) ;
598- if ( wildcard ) {
599- return wildcard === "any" && parseSemverVersion ( version ) != null ;
600- }
601- if ( trimmed . startsWith ( "^" ) ) {
602- const base = trimmed . slice ( 1 ) . trim ( ) ;
603- const upperBound = upperBoundForCaret ( base ) ;
604- const comparableVersion = normalizePluginApiVersionForComparator ( version , base ) ;
605- const lowerCmp = compareSemver ( comparableVersion , base ) ;
606- const upperCmp = upperBound ? compareSemver ( comparableVersion , upperBound ) : null ;
607- return lowerCmp != null && upperCmp != null && lowerCmp >= 0 && upperCmp < 0 ;
608- }
609-
610- const match = / ^ ( > = | < = | > | < | = ) ? \s * ( .+ ) $ / . exec ( trimmed ) ;
567+ const match = / ^ ( > = | < = | > | < | = | \^ | ~ ) ? \s * ( .+ ) $ / . exec ( trimmed ) ;
611568 if ( ! match ) {
612569 return false ;
613570 }
614- const operator = match [ 1 ] ;
571+ const operator = match [ 1 ] ?? "" ;
615572 const target = match [ 2 ] ?. trim ( ) ;
616- if ( ! target ) {
573+ if ( ! target || / ^ [ < > = ^ ~ ] / . test ( target ) ) {
617574 return false ;
618575 }
619576 const comparableVersion = normalizePluginApiVersionForComparator ( version , target ) ;
620577 const normalizedTarget = normalizePartialComparableVersion ( target ) ;
621- const cmp = compareSemver ( comparableVersion , normalizedTarget . version ) ;
622- if ( cmp == null ) {
623- return false ;
624- }
625- switch ( operator ) {
626- case ">=" :
627- return cmp >= 0 ;
628- case "<=" :
629- return cmp <= 0 ;
630- case ">" :
631- return cmp > 0 ;
632- case "<" :
633- return cmp < 0 ;
634- default :
635- return normalizedTarget . isPartial && ! operator ? cmp >= 0 : cmp === 0 ;
636- }
578+ const comparator =
579+ normalizedTarget . isPartial && ! operator
580+ ? `>=${ normalizedTarget . version } `
581+ : `${ operator } ${ normalizedTarget . version } ` ;
582+ return satisfiesSemver ( comparableVersion , comparator , { includePrerelease : true } ) ;
637583}
638584
639585function satisfiesSemverRange ( version : string , range : string ) : boolean {
586+ if ( range . includes ( "||" ) ) {
587+ return false ;
588+ }
640589 const tokens = normalizeStringEntries ( range . trim ( ) . split ( / \s + / ) ) ;
641590 if ( tokens . length === 0 ) {
642591 return false ;
0 commit comments