@@ -9,6 +9,13 @@ import { homedir } from "node:os"
99import { dirname , join } from "node:path"
1010import { fileURLToPath } from "node:url"
1111
12+ // Re-export semver utilities for backwards compatibility
13+ export {
14+ checkVersionCompatibility ,
15+ compareVersions ,
16+ parseVersion ,
17+ } from "./semver.mjs"
18+
1219/** Minimum character count for valid agent files */
1320export const MIN_CONTENT_LENGTH = 100
1421
@@ -303,146 +310,6 @@ export function validateAgentContent(content) {
303310 return { valid : true }
304311}
305312
306- /**
307- * Parses a semver version string into its numeric components.
308- *
309- * @param {string } version - The version string (e.g., "1.2.3")
310- * @returns {{ major: number, minor: number, patch: number } | null } Parsed version or null if invalid
311- */
312- function parseVersion ( version ) {
313- const match = version . match ( / ^ ( \d + ) \. ( \d + ) \. ( \d + ) $ / )
314- if ( ! match ) return null
315- return {
316- major : Number . parseInt ( match [ 1 ] , 10 ) ,
317- minor : Number . parseInt ( match [ 2 ] , 10 ) ,
318- patch : Number . parseInt ( match [ 3 ] , 10 ) ,
319- }
320- }
321-
322- /**
323- * Compares two parsed version objects.
324- *
325- * @param {{ major: number, minor: number, patch: number } } a - First version
326- * @param {{ major: number, minor: number, patch: number } } b - Second version
327- * @returns {number } -1 if a < b, 0 if a == b, 1 if a > b
328- */
329- function compareVersions ( a , b ) {
330- if ( a . major !== b . major ) return a . major < b . major ? - 1 : 1
331- if ( a . minor !== b . minor ) return a . minor < b . minor ? - 1 : 1
332- if ( a . patch !== b . patch ) return a . patch < b . patch ? - 1 : 1
333- return 0
334- }
335-
336- /**
337- * Checks if a version satisfies a semver range requirement.
338- *
339- * Supports common semver range patterns:
340- * - Exact version: "1.0.0" (must match exactly)
341- * - Greater than or equal: ">=1.0.0"
342- * - Greater than: ">1.0.0"
343- * - Less than or equal: "<=1.0.0"
344- * - Less than: "<1.0.0"
345- * - Caret (compatible with): "^1.0.0" (>=1.0.0 and <2.0.0)
346- * - Tilde (approximately): "~1.2.0" (>=1.2.0 and <1.3.0)
347- *
348- * @param {string } required - The required version range (e.g., ">=0.1.0", "^1.0.0")
349- * @param {string } current - The current version to check (e.g., "1.2.3")
350- * @returns {boolean } True if current version satisfies the required range
351- *
352- * @example
353- * checkVersionCompatibility(">=0.1.0", "0.2.0") // true
354- * checkVersionCompatibility("^1.0.0", "1.5.0") // true
355- * checkVersionCompatibility("^1.0.0", "2.0.0") // false
356- * checkVersionCompatibility("~1.2.0", "1.2.5") // true
357- * checkVersionCompatibility("~1.2.0", "1.3.0") // false
358- * @throws {TypeError } If required or current is not a non-empty string
359- */
360- export function checkVersionCompatibility ( required , current ) {
361- if ( typeof required !== "string" ) {
362- throw new TypeError (
363- `checkVersionCompatibility: required must be a string, got ${ required === null ? "null" : typeof required } ` ,
364- )
365- }
366- if ( required . trim ( ) === "" ) {
367- throw new TypeError ( "checkVersionCompatibility: required must not be empty" )
368- }
369- if ( typeof current !== "string" ) {
370- throw new TypeError (
371- `checkVersionCompatibility: current must be a string, got ${ current === null ? "null" : typeof current } ` ,
372- )
373- }
374- if ( current . trim ( ) === "" ) {
375- throw new TypeError ( "checkVersionCompatibility: current must not be empty" )
376- }
377- const currentVersion = parseVersion ( current )
378- if ( ! currentVersion ) return false
379-
380- // Handle caret range: ^1.0.0 means >=1.0.0 and <2.0.0 (for major >= 1)
381- // For ^0.x.y, it means >=0.x.y and <0.(x+1).0
382- if ( required . startsWith ( "^" ) ) {
383- const rangeVersion = parseVersion ( required . slice ( 1 ) )
384- if ( ! rangeVersion ) return false
385-
386- // Must be >= the specified version
387- if ( compareVersions ( currentVersion , rangeVersion ) < 0 ) return false
388-
389- // For major version 0, only minor version must match
390- if ( rangeVersion . major === 0 ) {
391- return currentVersion . major === 0 && currentVersion . minor === rangeVersion . minor
392- }
393-
394- // Major version must match
395- return currentVersion . major === rangeVersion . major
396- }
397-
398- // Handle tilde range: ~1.2.0 means >=1.2.0 and <1.3.0
399- if ( required . startsWith ( "~" ) ) {
400- const rangeVersion = parseVersion ( required . slice ( 1 ) )
401- if ( ! rangeVersion ) return false
402-
403- // Must be >= the specified version
404- if ( compareVersions ( currentVersion , rangeVersion ) < 0 ) return false
405-
406- // Major and minor must match
407- return (
408- currentVersion . major === rangeVersion . major && currentVersion . minor === rangeVersion . minor
409- )
410- }
411-
412- // Handle >= operator
413- if ( required . startsWith ( ">=" ) ) {
414- const rangeVersion = parseVersion ( required . slice ( 2 ) )
415- if ( ! rangeVersion ) return false
416- return compareVersions ( currentVersion , rangeVersion ) >= 0
417- }
418-
419- // Handle > operator
420- if ( required . startsWith ( ">" ) ) {
421- const rangeVersion = parseVersion ( required . slice ( 1 ) )
422- if ( ! rangeVersion ) return false
423- return compareVersions ( currentVersion , rangeVersion ) > 0
424- }
425-
426- // Handle <= operator
427- if ( required . startsWith ( "<=" ) ) {
428- const rangeVersion = parseVersion ( required . slice ( 2 ) )
429- if ( ! rangeVersion ) return false
430- return compareVersions ( currentVersion , rangeVersion ) <= 0
431- }
432-
433- // Handle < operator
434- if ( required . startsWith ( "<" ) ) {
435- const rangeVersion = parseVersion ( required . slice ( 1 ) )
436- if ( ! rangeVersion ) return false
437- return compareVersions ( currentVersion , rangeVersion ) < 0
438- }
439-
440- // Handle exact version match
441- const rangeVersion = parseVersion ( required )
442- if ( ! rangeVersion ) return false
443- return compareVersions ( currentVersion , rangeVersion ) === 0
444- }
445-
446313/**
447314 * Parses command line flags for install/uninstall scripts.
448315 *
0 commit comments