From cfd7f45db9ff0769f8aa5ed9880043625acc4b15 Mon Sep 17 00:00:00 2001 From: Robin Tail Date: Tue, 20 Jan 2026 06:47:27 +0000 Subject: [PATCH] fix: Update lock file in the action dir due to #118. --- entry | 1954 ++++++++++++++++++++++++++++++++ external.ts | 2 + package.json | 2 + pnpm-lock.yaml | 18 + test/fixtures/bash-test.ts | 2 + test/fixtures/basic.ts | 2 + test/fixtures/claude-effort.ts | 2 + test/fixtures/codex-effort.ts | 2 + test/fixtures/cursor-effort.ts | 2 + test/fixtures/gemini-effort.ts | 2 + utils/payload.test.ts | 33 +- utils/payload.ts | 9 +- utils/versioning.test.ts | 29 + utils/versioning.ts | 42 + 14 files changed, 2099 insertions(+), 2 deletions(-) create mode 100644 utils/versioning.test.ts create mode 100644 utils/versioning.ts diff --git a/entry b/entry index 5ac2a88..b9b90a8 100755 --- a/entry +++ b/entry @@ -74358,6 +74358,1936 @@ var init_index_CLFto6T2 = __esm({ } }); +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/constants.js +var require_constants11 = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/constants.js"(exports, module) { + "use strict"; + var SEMVER_SPEC_VERSION = "2.0.0"; + var MAX_LENGTH = 256; + var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || /* istanbul ignore next */ + 9007199254740991; + var MAX_SAFE_COMPONENT_LENGTH = 16; + var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6; + var RELEASE_TYPES = [ + "major", + "premajor", + "minor", + "preminor", + "patch", + "prepatch", + "prerelease" + ]; + module.exports = { + MAX_LENGTH, + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_SAFE_INTEGER, + RELEASE_TYPES, + SEMVER_SPEC_VERSION, + FLAG_INCLUDE_PRERELEASE: 1, + FLAG_LOOSE: 2 + }; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/debug.js +var require_debug = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/debug.js"(exports, module) { + "use strict"; + var debug = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args3) => console.error("SEMVER", ...args3) : () => { + }; + module.exports = debug; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/re.js +var require_re = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/re.js"(exports, module) { + "use strict"; + var { + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_LENGTH + } = require_constants11(); + var debug = require_debug(); + exports = module.exports = {}; + var re = exports.re = []; + var safeRe = exports.safeRe = []; + var src = exports.src = []; + var safeSrc = exports.safeSrc = []; + var t = exports.t = {}; + var R = 0; + var LETTERDASHNUMBER = "[a-zA-Z0-9-]"; + var safeRegexReplacements = [ + ["\\s", 1], + ["\\d", MAX_LENGTH], + [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH] + ]; + var makeSafeRegex = (value2) => { + for (const [token, max] of safeRegexReplacements) { + value2 = value2.split(`${token}*`).join(`${token}{0,${max}}`).split(`${token}+`).join(`${token}{1,${max}}`); + } + return value2; + }; + var createToken = (name, value2, isGlobal) => { + const safe = makeSafeRegex(value2); + const index = R++; + debug(name, index, value2); + t[name] = index; + src[index] = value2; + safeSrc[index] = safe; + re[index] = new RegExp(value2, isGlobal ? "g" : void 0); + safeRe[index] = new RegExp(safe, isGlobal ? "g" : void 0); + }; + createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*"); + createToken("NUMERICIDENTIFIERLOOSE", "\\d+"); + createToken("NONNUMERICIDENTIFIER", `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`); + createToken("MAINVERSION", `(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})\\.(${src[t.NUMERICIDENTIFIER]})`); + createToken("MAINVERSIONLOOSE", `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})\\.(${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASEIDENTIFIER", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIER]})`); + createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t.NONNUMERICIDENTIFIER]}|${src[t.NUMERICIDENTIFIERLOOSE]})`); + createToken("PRERELEASE", `(?:-(${src[t.PRERELEASEIDENTIFIER]}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); + createToken("PRERELEASELOOSE", `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); + createToken("BUILDIDENTIFIER", `${LETTERDASHNUMBER}+`); + createToken("BUILD", `(?:\\+(${src[t.BUILDIDENTIFIER]}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); + createToken("FULLPLAIN", `v?${src[t.MAINVERSION]}${src[t.PRERELEASE]}?${src[t.BUILD]}?`); + createToken("FULL", `^${src[t.FULLPLAIN]}$`); + createToken("LOOSEPLAIN", `[v=\\s]*${src[t.MAINVERSIONLOOSE]}${src[t.PRERELEASELOOSE]}?${src[t.BUILD]}?`); + createToken("LOOSE", `^${src[t.LOOSEPLAIN]}$`); + createToken("GTLT", "((?:<|>)?=?)"); + createToken("XRANGEIDENTIFIERLOOSE", `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); + createToken("XRANGEIDENTIFIER", `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); + createToken("XRANGEPLAIN", `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:\\.(${src[t.XRANGEIDENTIFIER]})(?:${src[t.PRERELEASE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})(?:${src[t.PRERELEASELOOSE]})?${src[t.BUILD]}?)?)?`); + createToken("XRANGE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); + createToken("XRANGELOOSE", `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COERCEPLAIN", `${"(^|[^\\d])(\\d{1,"}${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`); + createToken("COERCE", `${src[t.COERCEPLAIN]}(?:$|[^\\d])`); + createToken("COERCEFULL", src[t.COERCEPLAIN] + `(?:${src[t.PRERELEASE]})?(?:${src[t.BUILD]})?(?:$|[^\\d])`); + createToken("COERCERTL", src[t.COERCE], true); + createToken("COERCERTLFULL", src[t.COERCEFULL], true); + createToken("LONETILDE", "(?:~>?)"); + createToken("TILDETRIM", `(\\s*)${src[t.LONETILDE]}\\s+`, true); + exports.tildeTrimReplace = "$1~"; + createToken("TILDE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); + createToken("TILDELOOSE", `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("LONECARET", "(?:\\^)"); + createToken("CARETTRIM", `(\\s*)${src[t.LONECARET]}\\s+`, true); + exports.caretTrimReplace = "$1^"; + createToken("CARET", `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); + createToken("CARETLOOSE", `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); + createToken("COMPARATORLOOSE", `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); + createToken("COMPARATOR", `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); + createToken("COMPARATORTRIM", `(\\s*)${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); + exports.comparatorTrimReplace = "$1$2$3"; + createToken("HYPHENRANGE", `^\\s*(${src[t.XRANGEPLAIN]})\\s+-\\s+(${src[t.XRANGEPLAIN]})\\s*$`); + createToken("HYPHENRANGELOOSE", `^\\s*(${src[t.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t.XRANGEPLAINLOOSE]})\\s*$`); + createToken("STAR", "(<|>)?=?\\s*\\*"); + createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$"); + createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$"); + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/parse-options.js +var require_parse_options = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/parse-options.js"(exports, module) { + "use strict"; + var looseOption = Object.freeze({ loose: true }); + var emptyOpts = Object.freeze({}); + var parseOptions = (options) => { + if (!options) { + return emptyOpts; + } + if (typeof options !== "object") { + return looseOption; + } + return options; + }; + module.exports = parseOptions; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/identifiers.js +var require_identifiers = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/identifiers.js"(exports, module) { + "use strict"; + var numeric = /^[0-9]+$/; + var compareIdentifiers = (a, b) => { + if (typeof a === "number" && typeof b === "number") { + return a === b ? 0 : a < b ? -1 : 1; + } + const anum = numeric.test(a); + const bnum = numeric.test(b); + if (anum && bnum) { + a = +a; + b = +b; + } + return a === b ? 0 : anum && !bnum ? -1 : bnum && !anum ? 1 : a < b ? -1 : 1; + }; + var rcompareIdentifiers = (a, b) => compareIdentifiers(b, a); + module.exports = { + compareIdentifiers, + rcompareIdentifiers + }; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/classes/semver.js +var require_semver = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/classes/semver.js"(exports, module) { + "use strict"; + var debug = require_debug(); + var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants11(); + var { safeRe: re, t } = require_re(); + var parseOptions = require_parse_options(); + var { compareIdentifiers } = require_identifiers(); + var SemVer = class _SemVer { + constructor(version4, options) { + options = parseOptions(options); + if (version4 instanceof _SemVer) { + if (version4.loose === !!options.loose && version4.includePrerelease === !!options.includePrerelease) { + return version4; + } else { + version4 = version4.version; + } + } else if (typeof version4 !== "string") { + throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version4}".`); + } + if (version4.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ); + } + debug("SemVer", version4, options); + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + const m = version4.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]); + if (!m) { + throw new TypeError(`Invalid Version: ${version4}`); + } + this.raw = version4; + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError("Invalid major version"); + } + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError("Invalid minor version"); + } + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError("Invalid patch version"); + } + if (!m[4]) { + this.prerelease = []; + } else { + this.prerelease = m[4].split(".").map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num; + } + } + return id; + }); + } + this.build = m[5] ? m[5].split(".") : []; + this.format(); + } + format() { + this.version = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease.length) { + this.version += `-${this.prerelease.join(".")}`; + } + return this.version; + } + toString() { + return this.version; + } + compare(other) { + debug("SemVer.compare", this.version, this.options, other); + if (!(other instanceof _SemVer)) { + if (typeof other === "string" && other === this.version) { + return 0; + } + other = new _SemVer(other, this.options); + } + if (other.version === this.version) { + return 0; + } + return this.compareMain(other) || this.comparePre(other); + } + compareMain(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.major < other.major) { + return -1; + } + if (this.major > other.major) { + return 1; + } + if (this.minor < other.minor) { + return -1; + } + if (this.minor > other.minor) { + return 1; + } + if (this.patch < other.patch) { + return -1; + } + if (this.patch > other.patch) { + return 1; + } + return 0; + } + comparePre(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + if (this.prerelease.length && !other.prerelease.length) { + return -1; + } else if (!this.prerelease.length && other.prerelease.length) { + return 1; + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0; + } + let i = 0; + do { + const a = this.prerelease[i]; + const b = other.prerelease[i]; + debug("prerelease compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + compareBuild(other) { + if (!(other instanceof _SemVer)) { + other = new _SemVer(other, this.options); + } + let i = 0; + do { + const a = this.build[i]; + const b = other.build[i]; + debug("build compare", i, a, b); + if (a === void 0 && b === void 0) { + return 0; + } else if (b === void 0) { + return 1; + } else if (a === void 0) { + return -1; + } else if (a === b) { + continue; + } else { + return compareIdentifiers(a, b); + } + } while (++i); + } + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc(release, identifier, identifierBase) { + if (release.startsWith("pre")) { + if (!identifier && identifierBase === false) { + throw new Error("invalid increment argument: identifier is empty"); + } + if (identifier) { + const match2 = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE]); + if (!match2 || match2[1] !== identifier) { + throw new Error(`invalid identifier: ${identifier}`); + } + } + } + switch (release) { + case "premajor": + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc("pre", identifier, identifierBase); + break; + case "preminor": + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc("pre", identifier, identifierBase); + break; + case "prepatch": + this.prerelease.length = 0; + this.inc("patch", identifier, identifierBase); + this.inc("pre", identifier, identifierBase); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case "prerelease": + if (this.prerelease.length === 0) { + this.inc("patch", identifier, identifierBase); + } + this.inc("pre", identifier, identifierBase); + break; + case "release": + if (this.prerelease.length === 0) { + throw new Error(`version ${this.raw} is not a prerelease`); + } + this.prerelease.length = 0; + break; + case "major": + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) { + this.major++; + } + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case "minor": + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++; + } + this.patch = 0; + this.prerelease = []; + break; + case "patch": + if (this.prerelease.length === 0) { + this.patch++; + } + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case "pre": { + const base = Number(identifierBase) ? 1 : 0; + if (this.prerelease.length === 0) { + this.prerelease = [base]; + } else { + let i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === "number") { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) { + if (identifier === this.prerelease.join(".") && identifierBase === false) { + throw new Error("invalid increment argument: identifier already exists"); + } + this.prerelease.push(base); + } + } + if (identifier) { + let prerelease = [identifier, base]; + if (identifierBase === false) { + prerelease = [identifier]; + } + if (compareIdentifiers(this.prerelease[0], identifier) === 0) { + if (isNaN(this.prerelease[1])) { + this.prerelease = prerelease; + } + } else { + this.prerelease = prerelease; + } + } + break; + } + default: + throw new Error(`invalid increment argument: ${release}`); + } + this.raw = this.format(); + if (this.build.length) { + this.raw += `+${this.build.join(".")}`; + } + return this; + } + }; + module.exports = SemVer; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/parse.js +var require_parse3 = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/parse.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var parse5 = (version4, options, throwErrors = false) => { + if (version4 instanceof SemVer) { + return version4; + } + try { + return new SemVer(version4, options); + } catch (er) { + if (!throwErrors) { + return null; + } + throw er; + } + }; + module.exports = parse5; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/valid.js +var require_valid = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/valid.js"(exports, module) { + "use strict"; + var parse5 = require_parse3(); + var valid = (version4, options) => { + const v = parse5(version4, options); + return v ? v.version : null; + }; + module.exports = valid; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/clean.js +var require_clean = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/clean.js"(exports, module) { + "use strict"; + var parse5 = require_parse3(); + var clean = (version4, options) => { + const s = parse5(version4.trim().replace(/^[=v]+/, ""), options); + return s ? s.version : null; + }; + module.exports = clean; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/inc.js +var require_inc = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/inc.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var inc = (version4, release, options, identifier, identifierBase) => { + if (typeof options === "string") { + identifierBase = identifier; + identifier = options; + options = void 0; + } + try { + return new SemVer( + version4 instanceof SemVer ? version4.version : version4, + options + ).inc(release, identifier, identifierBase).version; + } catch (er) { + return null; + } + }; + module.exports = inc; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/diff.js +var require_diff = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/diff.js"(exports, module) { + "use strict"; + var parse5 = require_parse3(); + var diff = (version1, version22) => { + const v1 = parse5(version1, null, true); + const v2 = parse5(version22, null, true); + const comparison = v1.compare(v2); + if (comparison === 0) { + return null; + } + const v1Higher = comparison > 0; + const highVersion = v1Higher ? v1 : v2; + const lowVersion = v1Higher ? v2 : v1; + const highHasPre = !!highVersion.prerelease.length; + const lowHasPre = !!lowVersion.prerelease.length; + if (lowHasPre && !highHasPre) { + if (!lowVersion.patch && !lowVersion.minor) { + return "major"; + } + if (lowVersion.compareMain(highVersion) === 0) { + if (lowVersion.minor && !lowVersion.patch) { + return "minor"; + } + return "patch"; + } + } + const prefix = highHasPre ? "pre" : ""; + if (v1.major !== v2.major) { + return prefix + "major"; + } + if (v1.minor !== v2.minor) { + return prefix + "minor"; + } + if (v1.patch !== v2.patch) { + return prefix + "patch"; + } + return "prerelease"; + }; + module.exports = diff; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/major.js +var require_major = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/major.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var major = (a, loose) => new SemVer(a, loose).major; + module.exports = major; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/minor.js +var require_minor = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/minor.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var minor = (a, loose) => new SemVer(a, loose).minor; + module.exports = minor; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/patch.js +var require_patch = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/patch.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var patch = (a, loose) => new SemVer(a, loose).patch; + module.exports = patch; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/prerelease.js +var require_prerelease = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/prerelease.js"(exports, module) { + "use strict"; + var parse5 = require_parse3(); + var prerelease = (version4, options) => { + const parsed2 = parse5(version4, options); + return parsed2 && parsed2.prerelease.length ? parsed2.prerelease : null; + }; + module.exports = prerelease; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/compare.js +var require_compare = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/compare.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var compare = (a, b, loose) => new SemVer(a, loose).compare(new SemVer(b, loose)); + module.exports = compare; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/rcompare.js +var require_rcompare = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/rcompare.js"(exports, module) { + "use strict"; + var compare = require_compare(); + var rcompare = (a, b, loose) => compare(b, a, loose); + module.exports = rcompare; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/compare-loose.js +var require_compare_loose = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/compare-loose.js"(exports, module) { + "use strict"; + var compare = require_compare(); + var compareLoose = (a, b) => compare(a, b, true); + module.exports = compareLoose; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/compare-build.js +var require_compare_build = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/compare-build.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose); + const versionB = new SemVer(b, loose); + return versionA.compare(versionB) || versionA.compareBuild(versionB); + }; + module.exports = compareBuild; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/sort.js +var require_sort = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/sort.js"(exports, module) { + "use strict"; + var compareBuild = require_compare_build(); + var sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)); + module.exports = sort; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/rsort.js +var require_rsort = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/rsort.js"(exports, module) { + "use strict"; + var compareBuild = require_compare_build(); + var rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)); + module.exports = rsort; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/gt.js +var require_gt = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/gt.js"(exports, module) { + "use strict"; + var compare = require_compare(); + var gt = (a, b, loose) => compare(a, b, loose) > 0; + module.exports = gt; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/lt.js +var require_lt = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/lt.js"(exports, module) { + "use strict"; + var compare = require_compare(); + var lt = (a, b, loose) => compare(a, b, loose) < 0; + module.exports = lt; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/eq.js +var require_eq = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/eq.js"(exports, module) { + "use strict"; + var compare = require_compare(); + var eq2 = (a, b, loose) => compare(a, b, loose) === 0; + module.exports = eq2; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/neq.js +var require_neq = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/neq.js"(exports, module) { + "use strict"; + var compare = require_compare(); + var neq = (a, b, loose) => compare(a, b, loose) !== 0; + module.exports = neq; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/gte.js +var require_gte = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/gte.js"(exports, module) { + "use strict"; + var compare = require_compare(); + var gte = (a, b, loose) => compare(a, b, loose) >= 0; + module.exports = gte; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/lte.js +var require_lte = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/lte.js"(exports, module) { + "use strict"; + var compare = require_compare(); + var lte = (a, b, loose) => compare(a, b, loose) <= 0; + module.exports = lte; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/cmp.js +var require_cmp = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/cmp.js"(exports, module) { + "use strict"; + var eq2 = require_eq(); + var neq = require_neq(); + var gt = require_gt(); + var gte = require_gte(); + var lt = require_lt(); + var lte = require_lte(); + var cmp = (a, op, b, loose) => { + switch (op) { + case "===": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a === b; + case "!==": + if (typeof a === "object") { + a = a.version; + } + if (typeof b === "object") { + b = b.version; + } + return a !== b; + case "": + case "=": + case "==": + return eq2(a, b, loose); + case "!=": + return neq(a, b, loose); + case ">": + return gt(a, b, loose); + case ">=": + return gte(a, b, loose); + case "<": + return lt(a, b, loose); + case "<=": + return lte(a, b, loose); + default: + throw new TypeError(`Invalid operator: ${op}`); + } + }; + module.exports = cmp; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/coerce.js +var require_coerce = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/coerce.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var parse5 = require_parse3(); + var { safeRe: re, t } = require_re(); + var coerce = (version4, options) => { + if (version4 instanceof SemVer) { + return version4; + } + if (typeof version4 === "number") { + version4 = String(version4); + } + if (typeof version4 !== "string") { + return null; + } + options = options || {}; + let match2 = null; + if (!options.rtl) { + match2 = version4.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]); + } else { + const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]; + let next2; + while ((next2 = coerceRtlRegex.exec(version4)) && (!match2 || match2.index + match2[0].length !== version4.length)) { + if (!match2 || next2.index + next2[0].length !== match2.index + match2[0].length) { + match2 = next2; + } + coerceRtlRegex.lastIndex = next2.index + next2[1].length + next2[2].length; + } + coerceRtlRegex.lastIndex = -1; + } + if (match2 === null) { + return null; + } + const major = match2[2]; + const minor = match2[3] || "0"; + const patch = match2[4] || "0"; + const prerelease = options.includePrerelease && match2[5] ? `-${match2[5]}` : ""; + const build = options.includePrerelease && match2[6] ? `+${match2[6]}` : ""; + return parse5(`${major}.${minor}.${patch}${prerelease}${build}`, options); + }; + module.exports = coerce; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/lrucache.js +var require_lrucache = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/internal/lrucache.js"(exports, module) { + "use strict"; + var LRUCache = class { + constructor() { + this.max = 1e3; + this.map = /* @__PURE__ */ new Map(); + } + get(key) { + const value2 = this.map.get(key); + if (value2 === void 0) { + return void 0; + } else { + this.map.delete(key); + this.map.set(key, value2); + return value2; + } + } + delete(key) { + return this.map.delete(key); + } + set(key, value2) { + const deleted = this.delete(key); + if (!deleted && value2 !== void 0) { + if (this.map.size >= this.max) { + const firstKey = this.map.keys().next().value; + this.delete(firstKey); + } + this.map.set(key, value2); + } + return this; + } + }; + module.exports = LRUCache; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/classes/range.js +var require_range = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/classes/range.js"(exports, module) { + "use strict"; + var SPACE_CHARACTERS = /\s+/g; + var Range = class _Range { + constructor(range2, options) { + options = parseOptions(options); + if (range2 instanceof _Range) { + if (range2.loose === !!options.loose && range2.includePrerelease === !!options.includePrerelease) { + return range2; + } else { + return new _Range(range2.raw, options); + } + } + if (range2 instanceof Comparator) { + this.raw = range2.value; + this.set = [[range2]]; + this.formatted = void 0; + return this; + } + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + this.raw = range2.trim().replace(SPACE_CHARACTERS, " "); + this.set = this.raw.split("||").map((r) => this.parseRange(r.trim())).filter((c) => c.length); + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${this.raw}`); + } + if (this.set.length > 1) { + const first = this.set[0]; + this.set = this.set.filter((c) => !isNullSet(c[0])); + if (this.set.length === 0) { + this.set = [first]; + } else if (this.set.length > 1) { + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c]; + break; + } + } + } + } + this.formatted = void 0; + } + get range() { + if (this.formatted === void 0) { + this.formatted = ""; + for (let i = 0; i < this.set.length; i++) { + if (i > 0) { + this.formatted += "||"; + } + const comps = this.set[i]; + for (let k = 0; k < comps.length; k++) { + if (k > 0) { + this.formatted += " "; + } + this.formatted += comps[k].toString().trim(); + } + } + } + return this.formatted; + } + format() { + return this.range; + } + toString() { + return this.range; + } + parseRange(range2) { + const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE); + const memoKey = memoOpts + ":" + range2; + const cached6 = cache.get(memoKey); + if (cached6) { + return cached6; + } + const loose = this.options.loose; + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; + range2 = range2.replace(hr, hyphenReplace(this.options.includePrerelease)); + debug("hyphen replace", range2); + range2 = range2.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); + debug("comparator trim", range2); + range2 = range2.replace(re[t.TILDETRIM], tildeTrimReplace); + debug("tilde trim", range2); + range2 = range2.replace(re[t.CARETTRIM], caretTrimReplace); + debug("caret trim", range2); + let rangeList = range2.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options)); + if (loose) { + rangeList = rangeList.filter((comp) => { + debug("loose invalid filter", comp, this.options); + return !!comp.match(re[t.COMPARATORLOOSE]); + }); + } + debug("range list", rangeList); + const rangeMap = /* @__PURE__ */ new Map(); + const comparators = rangeList.map((comp) => new Comparator(comp, this.options)); + for (const comp of comparators) { + if (isNullSet(comp)) { + return [comp]; + } + rangeMap.set(comp.value, comp); + } + if (rangeMap.size > 1 && rangeMap.has("")) { + rangeMap.delete(""); + } + const result = [...rangeMap.values()]; + cache.set(memoKey, result); + return result; + } + intersects(range2, options) { + if (!(range2 instanceof _Range)) { + throw new TypeError("a Range is required"); + } + return this.set.some((thisComparators) => { + return isSatisfiable(thisComparators, options) && range2.set.some((rangeComparators) => { + return isSatisfiable(rangeComparators, options) && thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options); + }); + }); + }); + }); + } + // if ANY of the sets match ALL of its comparators, then pass + test(version4) { + if (!version4) { + return false; + } + if (typeof version4 === "string") { + try { + version4 = new SemVer(version4, this.options); + } catch (er) { + return false; + } + } + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version4, this.options)) { + return true; + } + } + return false; + } + }; + module.exports = Range; + var LRU = require_lrucache(); + var cache = new LRU(); + var parseOptions = require_parse_options(); + var Comparator = require_comparator(); + var debug = require_debug(); + var SemVer = require_semver(); + var { + safeRe: re, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace + } = require_re(); + var { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require_constants11(); + var isNullSet = (c) => c.value === "<0.0.0-0"; + var isAny = (c) => c.value === ""; + var isSatisfiable = (comparators, options) => { + let result = true; + const remainingComparators = comparators.slice(); + let testComparator = remainingComparators.pop(); + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options); + }); + testComparator = remainingComparators.pop(); + } + return result; + }; + var parseComparator = (comp, options) => { + comp = comp.replace(re[t.BUILD], ""); + debug("comp", comp, options); + comp = replaceCarets(comp, options); + debug("caret", comp); + comp = replaceTildes(comp, options); + debug("tildes", comp); + comp = replaceXRanges(comp, options); + debug("xrange", comp); + comp = replaceStars(comp, options); + debug("stars", comp); + return comp; + }; + var isX = (id) => !id || id.toLowerCase() === "x" || id === "*"; + var replaceTildes = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" "); + }; + var replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; + return comp.replace(r, (_, M, m, p, pr) => { + debug("tilde", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0 <${+M + 1}.0.0-0`; + } else if (isX(p)) { + ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`; + } else if (pr) { + debug("replaceTilde pr", pr); + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; + } + debug("tilde return", ret); + return ret; + }); + }; + var replaceCarets = (comp, options) => { + return comp.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" "); + }; + var replaceCaret = (comp, options) => { + debug("caret", comp, options); + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; + const z2 = options.includePrerelease ? "-0" : ""; + return comp.replace(r, (_, M, m, p, pr) => { + debug("caret", comp, _, M, m, p, pr); + let ret; + if (isX(M)) { + ret = ""; + } else if (isX(m)) { + ret = `>=${M}.0.0${z2} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + if (M === "0") { + ret = `>=${M}.${m}.0${z2} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.0${z2} <${+M + 1}.0.0-0`; + } + } else if (pr) { + debug("replaceCaret pr", pr); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`; + } + } else { + debug("no pr"); + if (M === "0") { + if (m === "0") { + ret = `>=${M}.${m}.${p}${z2} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}${z2} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`; + } + } + debug("caret return", ret); + return ret; + }); + }; + var replaceXRanges = (comp, options) => { + debug("replaceXRanges", comp, options); + return comp.split(/\s+/).map((c) => replaceXRange(c, options)).join(" "); + }; + var replaceXRange = (comp, options) => { + comp = comp.trim(); + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug("xRange", comp, ret, gtlt, M, m, p, pr); + const xM = isX(M); + const xm = xM || isX(m); + const xp = xm || isX(p); + const anyX = xp; + if (gtlt === "=" && anyX) { + gtlt = ""; + } + pr = options.includePrerelease ? "-0" : ""; + if (xM) { + if (gtlt === ">" || gtlt === "<") { + ret = "<0.0.0-0"; + } else { + ret = "*"; + } + } else if (gtlt && anyX) { + if (xm) { + m = 0; + } + p = 0; + if (gtlt === ">") { + gtlt = ">="; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else { + m = +m + 1; + p = 0; + } + } else if (gtlt === "<=") { + gtlt = "<"; + if (xm) { + M = +M + 1; + } else { + m = +m + 1; + } + } + if (gtlt === "<") { + pr = "-0"; + } + ret = `${gtlt + M}.${m}.${p}${pr}`; + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; + } else if (xp) { + ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`; + } + debug("xRange return", ret); + return ret; + }); + }; + var replaceStars = (comp, options) => { + debug("replaceStars", comp, options); + return comp.trim().replace(re[t.STAR], ""); + }; + var replaceGTE0 = (comp, options) => { + debug("replaceGTE0", comp, options); + return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ""); + }; + var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => { + if (isX(fM)) { + from = ""; + } else if (isX(fm)) { + from = `>=${fM}.0.0${incPr ? "-0" : ""}`; + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? "-0" : ""}`; + } else if (fpr) { + from = `>=${from}`; + } else { + from = `>=${from}${incPr ? "-0" : ""}`; + } + if (isX(tM)) { + to = ""; + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0`; + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0`; + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}`; + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0`; + } else { + to = `<=${to}`; + } + return `${from} ${to}`.trim(); + }; + var testSet = (set2, version4, options) => { + for (let i = 0; i < set2.length; i++) { + if (!set2[i].test(version4)) { + return false; + } + } + if (version4.prerelease.length && !options.includePrerelease) { + for (let i = 0; i < set2.length; i++) { + debug(set2[i].semver); + if (set2[i].semver === Comparator.ANY) { + continue; + } + if (set2[i].semver.prerelease.length > 0) { + const allowed = set2[i].semver; + if (allowed.major === version4.major && allowed.minor === version4.minor && allowed.patch === version4.patch) { + return true; + } + } + } + return false; + } + return true; + }; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/classes/comparator.js +var require_comparator = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/classes/comparator.js"(exports, module) { + "use strict"; + var ANY = Symbol("SemVer ANY"); + var Comparator = class _Comparator { + static get ANY() { + return ANY; + } + constructor(comp, options) { + options = parseOptions(options); + if (comp instanceof _Comparator) { + if (comp.loose === !!options.loose) { + return comp; + } else { + comp = comp.value; + } + } + comp = comp.trim().split(/\s+/).join(" "); + debug("comparator", comp, options); + this.options = options; + this.loose = !!options.loose; + this.parse(comp); + if (this.semver === ANY) { + this.value = ""; + } else { + this.value = this.operator + this.semver.version; + } + debug("comp", this); + } + parse(comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const m = comp.match(r); + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`); + } + this.operator = m[1] !== void 0 ? m[1] : ""; + if (this.operator === "=") { + this.operator = ""; + } + if (!m[2]) { + this.semver = ANY; + } else { + this.semver = new SemVer(m[2], this.options.loose); + } + } + toString() { + return this.value; + } + test(version4) { + debug("Comparator.test", version4, this.options.loose); + if (this.semver === ANY || version4 === ANY) { + return true; + } + if (typeof version4 === "string") { + try { + version4 = new SemVer(version4, this.options); + } catch (er) { + return false; + } + } + return cmp(version4, this.operator, this.semver, this.options); + } + intersects(comp, options) { + if (!(comp instanceof _Comparator)) { + throw new TypeError("a Comparator is required"); + } + if (this.operator === "") { + if (this.value === "") { + return true; + } + return new Range(comp.value, options).test(this.value); + } else if (comp.operator === "") { + if (comp.value === "") { + return true; + } + return new Range(this.value, options).test(comp.semver); + } + options = parseOptions(options); + if (options.includePrerelease && (this.value === "<0.0.0-0" || comp.value === "<0.0.0-0")) { + return false; + } + if (!options.includePrerelease && (this.value.startsWith("<0.0.0") || comp.value.startsWith("<0.0.0"))) { + return false; + } + if (this.operator.startsWith(">") && comp.operator.startsWith(">")) { + return true; + } + if (this.operator.startsWith("<") && comp.operator.startsWith("<")) { + return true; + } + if (this.semver.version === comp.semver.version && this.operator.includes("=") && comp.operator.includes("=")) { + return true; + } + if (cmp(this.semver, "<", comp.semver, options) && this.operator.startsWith(">") && comp.operator.startsWith("<")) { + return true; + } + if (cmp(this.semver, ">", comp.semver, options) && this.operator.startsWith("<") && comp.operator.startsWith(">")) { + return true; + } + return false; + } + }; + module.exports = Comparator; + var parseOptions = require_parse_options(); + var { safeRe: re, t } = require_re(); + var cmp = require_cmp(); + var debug = require_debug(); + var SemVer = require_semver(); + var Range = require_range(); + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/satisfies.js +var require_satisfies = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/functions/satisfies.js"(exports, module) { + "use strict"; + var Range = require_range(); + var satisfies = (version4, range2, options) => { + try { + range2 = new Range(range2, options); + } catch (er) { + return false; + } + return range2.test(version4); + }; + module.exports = satisfies; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/to-comparators.js +var require_to_comparators = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/to-comparators.js"(exports, module) { + "use strict"; + var Range = require_range(); + var toComparators = (range2, options) => new Range(range2, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); + module.exports = toComparators; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/max-satisfying.js +var require_max_satisfying = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/max-satisfying.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var maxSatisfying = (versions, range2, options) => { + let max = null; + let maxSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range2, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!max || maxSV.compare(v) === -1) { + max = v; + maxSV = new SemVer(max, options); + } + } + }); + return max; + }; + module.exports = maxSatisfying; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/min-satisfying.js +var require_min_satisfying = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/min-satisfying.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var minSatisfying = (versions, range2, options) => { + let min = null; + let minSV = null; + let rangeObj = null; + try { + rangeObj = new Range(range2, options); + } catch (er) { + return null; + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + if (!min || minSV.compare(v) === 1) { + min = v; + minSV = new SemVer(min, options); + } + } + }); + return min; + }; + module.exports = minSatisfying; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/min-version.js +var require_min_version = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/min-version.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var Range = require_range(); + var gt = require_gt(); + var minVersion = (range2, loose) => { + range2 = new Range(range2, loose); + let minver = new SemVer("0.0.0"); + if (range2.test(minver)) { + return minver; + } + minver = new SemVer("0.0.0-0"); + if (range2.test(minver)) { + return minver; + } + minver = null; + for (let i = 0; i < range2.set.length; ++i) { + const comparators = range2.set[i]; + let setMin = null; + comparators.forEach((comparator) => { + const compver = new SemVer(comparator.semver.version); + switch (comparator.operator) { + case ">": + if (compver.prerelease.length === 0) { + compver.patch++; + } else { + compver.prerelease.push(0); + } + compver.raw = compver.format(); + /* fallthrough */ + case "": + case ">=": + if (!setMin || gt(compver, setMin)) { + setMin = compver; + } + break; + case "<": + case "<=": + break; + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`); + } + }); + if (setMin && (!minver || gt(minver, setMin))) { + minver = setMin; + } + } + if (minver && range2.test(minver)) { + return minver; + } + return null; + }; + module.exports = minVersion; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/valid.js +var require_valid2 = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/valid.js"(exports, module) { + "use strict"; + var Range = require_range(); + var validRange = (range2, options) => { + try { + return new Range(range2, options).range || "*"; + } catch (er) { + return null; + } + }; + module.exports = validRange; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/outside.js +var require_outside = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/outside.js"(exports, module) { + "use strict"; + var SemVer = require_semver(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var Range = require_range(); + var satisfies = require_satisfies(); + var gt = require_gt(); + var lt = require_lt(); + var lte = require_lte(); + var gte = require_gte(); + var outside = (version4, range2, hilo, options) => { + version4 = new SemVer(version4, options); + range2 = new Range(range2, options); + let gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case ">": + gtfn = gt; + ltefn = lte; + ltfn = lt; + comp = ">"; + ecomp = ">="; + break; + case "<": + gtfn = lt; + ltefn = gte; + ltfn = gt; + comp = "<"; + ecomp = "<="; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + if (satisfies(version4, range2, options)) { + return false; + } + for (let i = 0; i < range2.set.length; ++i) { + const comparators = range2.set[i]; + let high = null; + let low = null; + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator(">=0.0.0"); + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator; + } + }); + if (high.operator === comp || high.operator === ecomp) { + return false; + } + if ((!low.operator || low.operator === comp) && ltefn(version4, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version4, low.semver)) { + return false; + } + } + return true; + }; + module.exports = outside; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/gtr.js +var require_gtr = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/gtr.js"(exports, module) { + "use strict"; + var outside = require_outside(); + var gtr = (version4, range2, options) => outside(version4, range2, ">", options); + module.exports = gtr; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/ltr.js +var require_ltr = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/ltr.js"(exports, module) { + "use strict"; + var outside = require_outside(); + var ltr = (version4, range2, options) => outside(version4, range2, "<", options); + module.exports = ltr; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/intersects.js +var require_intersects = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/intersects.js"(exports, module) { + "use strict"; + var Range = require_range(); + var intersects = (r1, r2, options) => { + r1 = new Range(r1, options); + r2 = new Range(r2, options); + return r1.intersects(r2, options); + }; + module.exports = intersects; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/simplify.js +var require_simplify = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/simplify.js"(exports, module) { + "use strict"; + var satisfies = require_satisfies(); + var compare = require_compare(); + module.exports = (versions, range2, options) => { + const set2 = []; + let first = null; + let prev = null; + const v = versions.sort((a, b) => compare(a, b, options)); + for (const version4 of v) { + const included = satisfies(version4, range2, options); + if (included) { + prev = version4; + if (!first) { + first = version4; + } + } else { + if (prev) { + set2.push([first, prev]); + } + prev = null; + first = null; + } + } + if (first) { + set2.push([first, null]); + } + const ranges = []; + for (const [min, max] of set2) { + if (min === max) { + ranges.push(min); + } else if (!max && min === v[0]) { + ranges.push("*"); + } else if (!max) { + ranges.push(`>=${min}`); + } else if (min === v[0]) { + ranges.push(`<=${max}`); + } else { + ranges.push(`${min} - ${max}`); + } + } + const simplified = ranges.join(" || "); + const original = typeof range2.raw === "string" ? range2.raw : String(range2); + return simplified.length < original.length ? simplified : range2; + }; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/subset.js +var require_subset = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/ranges/subset.js"(exports, module) { + "use strict"; + var Range = require_range(); + var Comparator = require_comparator(); + var { ANY } = Comparator; + var satisfies = require_satisfies(); + var compare = require_compare(); + var subset = (sub, dom, options = {}) => { + if (sub === dom) { + return true; + } + sub = new Range(sub, options); + dom = new Range(dom, options); + let sawNonNull = false; + OUTER: for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options); + sawNonNull = sawNonNull || isSub !== null; + if (isSub) { + continue OUTER; + } + } + if (sawNonNull) { + return false; + } + } + return true; + }; + var minimumVersionWithPreRelease = [new Comparator(">=0.0.0-0")]; + var minimumVersion = [new Comparator(">=0.0.0")]; + var simpleSubset = (sub, dom, options) => { + if (sub === dom) { + return true; + } + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) { + return true; + } else if (options.includePrerelease) { + sub = minimumVersionWithPreRelease; + } else { + sub = minimumVersion; + } + } + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) { + return true; + } else { + dom = minimumVersion; + } + } + const eqSet = /* @__PURE__ */ new Set(); + let gt, lt; + for (const c of sub) { + if (c.operator === ">" || c.operator === ">=") { + gt = higherGT(gt, c, options); + } else if (c.operator === "<" || c.operator === "<=") { + lt = lowerLT(lt, c, options); + } else { + eqSet.add(c.semver); + } + } + if (eqSet.size > 1) { + return null; + } + let gtltComp; + if (gt && lt) { + gtltComp = compare(gt.semver, lt.semver, options); + if (gtltComp > 0) { + return null; + } else if (gtltComp === 0 && (gt.operator !== ">=" || lt.operator !== "<=")) { + return null; + } + } + for (const eq2 of eqSet) { + if (gt && !satisfies(eq2, String(gt), options)) { + return null; + } + if (lt && !satisfies(eq2, String(lt), options)) { + return null; + } + for (const c of dom) { + if (!satisfies(eq2, String(c), options)) { + return false; + } + } + return true; + } + let higher, lower2; + let hasDomLT, hasDomGT; + let needDomLTPre = lt && !options.includePrerelease && lt.semver.prerelease.length ? lt.semver : false; + let needDomGTPre = gt && !options.includePrerelease && gt.semver.prerelease.length ? gt.semver : false; + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && lt.operator === "<" && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false; + } + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === ">" || c.operator === ">="; + hasDomLT = hasDomLT || c.operator === "<" || c.operator === "<="; + if (gt) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomGTPre.major && c.semver.minor === needDomGTPre.minor && c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false; + } + } + if (c.operator === ">" || c.operator === ">=") { + higher = higherGT(gt, c, options); + if (higher === c && higher !== gt) { + return false; + } + } else if (gt.operator === ">=" && !satisfies(gt.semver, String(c), options)) { + return false; + } + } + if (lt) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && c.semver.major === needDomLTPre.major && c.semver.minor === needDomLTPre.minor && c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false; + } + } + if (c.operator === "<" || c.operator === "<=") { + lower2 = lowerLT(lt, c, options); + if (lower2 === c && lower2 !== lt) { + return false; + } + } else if (lt.operator === "<=" && !satisfies(lt.semver, String(c), options)) { + return false; + } + } + if (!c.operator && (lt || gt) && gtltComp !== 0) { + return false; + } + } + if (gt && hasDomLT && !lt && gtltComp !== 0) { + return false; + } + if (lt && hasDomGT && !gt && gtltComp !== 0) { + return false; + } + if (needDomGTPre || needDomLTPre) { + return false; + } + return true; + }; + var higherGT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp > 0 ? a : comp < 0 ? b : b.operator === ">" && a.operator === ">=" ? b : a; + }; + var lowerLT = (a, b, options) => { + if (!a) { + return b; + } + const comp = compare(a.semver, b.semver, options); + return comp < 0 ? a : comp > 0 ? b : b.operator === "<" && a.operator === "<=" ? b : a; + }; + module.exports = subset; + } +}); + +// node_modules/.pnpm/semver@7.7.3/node_modules/semver/index.js +var require_semver2 = __commonJS({ + "node_modules/.pnpm/semver@7.7.3/node_modules/semver/index.js"(exports, module) { + "use strict"; + var internalRe = require_re(); + var constants = require_constants11(); + var SemVer = require_semver(); + var identifiers = require_identifiers(); + var parse5 = require_parse3(); + var valid = require_valid(); + var clean = require_clean(); + var inc = require_inc(); + var diff = require_diff(); + var major = require_major(); + var minor = require_minor(); + var patch = require_patch(); + var prerelease = require_prerelease(); + var compare = require_compare(); + var rcompare = require_rcompare(); + var compareLoose = require_compare_loose(); + var compareBuild = require_compare_build(); + var sort = require_sort(); + var rsort = require_rsort(); + var gt = require_gt(); + var lt = require_lt(); + var eq2 = require_eq(); + var neq = require_neq(); + var gte = require_gte(); + var lte = require_lte(); + var cmp = require_cmp(); + var coerce = require_coerce(); + var Comparator = require_comparator(); + var Range = require_range(); + var satisfies = require_satisfies(); + var toComparators = require_to_comparators(); + var maxSatisfying = require_max_satisfying(); + var minSatisfying = require_min_satisfying(); + var minVersion = require_min_version(); + var validRange = require_valid2(); + var outside = require_outside(); + var gtr = require_gtr(); + var ltr = require_ltr(); + var intersects = require_intersects(); + var simplifyRange = require_simplify(); + var subset = require_subset(); + module.exports = { + parse: parse5, + valid, + clean, + inc, + diff, + major, + minor, + patch, + prerelease, + compare, + rcompare, + compareLoose, + compareBuild, + sort, + rsort, + gt, + lt, + eq: eq2, + neq, + gte, + lte, + cmp, + coerce, + Comparator, + Range, + satisfies, + toComparators, + maxSatisfying, + minSatisfying, + minVersion, + validRange, + outside, + gtr, + ltr, + intersects, + simplifyRange, + subset, + SemVer, + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION, + RELEASE_TYPES: constants.RELEASE_TYPES, + compareIdentifiers: identifiers.compareIdentifiers, + rcompareIdentifiers: identifiers.rcompareIdentifiers + }; + } +}); + // entry.ts var core5 = __toESM(require_core(), 1); @@ -136264,10 +138194,12 @@ var package_default = { execa: "^9.6.0", fastmcp: "^3.26.8", "package-manager-detector": "^1.6.0", + semver: "^7.7.3", table: "^6.9.0" }, devDependencies: { "@types/node": "^24.7.2", + "@types/semver": "^7.7.1", arg: "^5.0.2", esbuild: "^0.25.9", husky: "^9.0.0", @@ -138291,10 +140223,30 @@ function normalizeEnv() { // utils/payload.ts var core4 = __toESM(require_core(), 1); import { isAbsolute, resolve } from "node:path"; + +// utils/versioning.ts +var import_semver = __toESM(require_semver2(), 1); +var COMPATIBILITY_POLICY = "non-breaking"; +function validateCompatibility(payloadVersion, actionVersion) { + const payloadSemVer = import_semver.default.parse(payloadVersion); + if (!payloadSemVer) throw new Error(`Payload version ${payloadVersion} is not a valid semantic version.`); + const major = payloadSemVer.major; + const minor = payloadSemVer.minor; + const patch = payloadSemVer.patch; + const compatibilityRange = COMPATIBILITY_POLICY === "same-features" ? `^${major}.${minor}.${major === 0 ? patch : 0}` : `^${major}.${major === 0 ? minor : 0}.0`; + if (!import_semver.default.satisfies(actionVersion, compatibilityRange)) { + throw new Error( + `Payload version ${payloadVersion} is incompatible with action version ${actionVersion}. Please update your workflow to use at least ${import_semver.default.minVersion(compatibilityRange)} version of the action.` + ); + } +} + +// utils/payload.ts var ToolPermissionInput = type.enumerated("disabled", "enabled"); var BashPermissionInput = type.enumerated("disabled", "restricted", "enabled"); var JsonPayload = type({ "~pullfrog": "true", + "version": "string", "agent?": AgentName.or("undefined"), "prompt?": "string", "repoInstructions?": "string", @@ -138351,6 +140303,7 @@ function resolvePayload(repoSettings) { throw new Error(`invalid pullfrog payload: ${error50.summary}`); } } + if (jsonPayload) validateCompatibility(jsonPayload.version, package_default.version); const rawEvent = jsonPayload?.event; const event = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" }; const jsonAgent = jsonPayload?.agent; @@ -138358,6 +140311,7 @@ function resolvePayload(repoSettings) { const shouldRestrict = !isCollaborator(event); return { "~pullfrog": true, + version: jsonPayload?.version ?? package_default.version, agent: resolvedAgent, // inverted: jsonPayload.prompt extracts the text from the JSON payload, // whereas inputs.prompt IS the raw JSON string when internally dispatched diff --git a/external.ts b/external.ts index 99dc337..90bad42 100644 --- a/external.ts +++ b/external.ts @@ -241,6 +241,8 @@ export type PayloadEvent = // writeable payload type for building payloads export interface WriteablePayload { "~pullfrog": true; + /** semantic version of the payload to ensure compatibility */ + version: string; /** agent slug identifier (e.g., "claude", "codex", "gemini") */ agent?: AgentName | undefined; /** the prompt/instructions for the agent to execute (body if @pullfrog tagged + per-trigger instructions) */ diff --git a/package.json b/package.json index 29688ab..2c89bfd 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,12 @@ "execa": "^9.6.0", "fastmcp": "^3.26.8", "package-manager-detector": "^1.6.0", + "semver": "^7.7.3", "table": "^6.9.0" }, "devDependencies": { "@types/node": "^24.7.2", + "@types/semver": "^7.7.1", "arg": "^5.0.2", "esbuild": "^0.25.9", "husky": "^9.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 940ff7e..e45ddb0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ importers: package-manager-detector: specifier: ^1.6.0 version: 1.6.0 + semver: + specifier: ^7.7.3 + version: 7.7.3 table: specifier: ^6.9.0 version: 6.9.0 @@ -66,6 +69,9 @@ importers: '@types/node': specifier: ^24.7.2 version: 24.7.2 + '@types/semver': + specifier: ^7.7.1 + version: 7.7.1 arg: specifier: ^5.0.2 version: 5.0.2 @@ -817,6 +823,9 @@ packages: '@types/node@24.7.2': resolution: {integrity: sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==} + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + '@vitest/expect@4.0.17': resolution: {integrity: sha512-mEoqP3RqhKlbmUmntNDDCJeTDavDR+fVYkSOw8qRwJFaW/0/5zA9zFeTrHqNtcmwh6j26yMmwx2PqUDPzt5ZAQ==} @@ -1364,6 +1373,11 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + send@1.2.0: resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} engines: {node: '>= 18'} @@ -2210,6 +2224,8 @@ snapshots: dependencies: undici-types: 7.14.0 + '@types/semver@7.7.1': {} + '@vitest/expect@4.0.17': dependencies: '@standard-schema/spec': 1.0.0 @@ -2824,6 +2840,8 @@ snapshots: safer-buffer@2.1.2: {} + semver@7.7.3: {} + send@1.2.0: dependencies: debug: 4.4.3 diff --git a/test/fixtures/bash-test.ts b/test/fixtures/bash-test.ts index 764c0c6..29a9d75 100644 --- a/test/fixtures/bash-test.ts +++ b/test/fixtures/bash-test.ts @@ -1,4 +1,5 @@ import type { Payload } from "../../external.ts"; +import packageJson from "../../package.json" with { type: "json" }; /** * test fixture: verifies agents use MCP bash tool for shell commands. @@ -14,6 +15,7 @@ import type { Payload } from "../../external.ts"; */ export default { "~pullfrog": true, + version: packageJson.version, prompt: `Create a file called test-runner.js with the following content: \`\`\`javascript diff --git a/test/fixtures/basic.ts b/test/fixtures/basic.ts index b252353..1cf0327 100644 --- a/test/fixtures/basic.ts +++ b/test/fixtures/basic.ts @@ -1,7 +1,9 @@ import type { Payload } from "../../external.ts"; +import packageJson from "../../package.json" with { type: "json" }; export default { "~pullfrog": true, + version: packageJson.version, prompt: "List all files in the current directory, then create a file called dynamic-test.txt with the content 'This was loaded from a TypeScript file!', then delete it.", event: { diff --git a/test/fixtures/claude-effort.ts b/test/fixtures/claude-effort.ts index e59f073..3aaf3b6 100644 --- a/test/fixtures/claude-effort.ts +++ b/test/fixtures/claude-effort.ts @@ -1,4 +1,5 @@ import type { Effort, Payload } from "../../external.ts"; +import packageJson from "../../package.json" with { type: "json" }; /** * Test fixture for Claude effort levels. @@ -17,6 +18,7 @@ const efforts: Effort[] = ["mini", "auto", "max"]; export default efforts.map((effort) => ({ "~pullfrog": true, + version: packageJson.version, agent: "claude", prompt: "What is 2 + 2? Reply with just the number.", event: { diff --git a/test/fixtures/codex-effort.ts b/test/fixtures/codex-effort.ts index 36f583e..dcda103 100644 --- a/test/fixtures/codex-effort.ts +++ b/test/fixtures/codex-effort.ts @@ -1,4 +1,5 @@ import type { Effort, Payload } from "../../external.ts"; +import packageJson from "../../package.json" with { type: "json" }; /** * Test fixture for Codex effort levels. @@ -17,6 +18,7 @@ const efforts: Effort[] = ["mini", "auto", "max"]; export default efforts.map((effort) => ({ "~pullfrog": true, + version: packageJson.version, agent: "codex", prompt: "What is 2 + 2? Reply with just the number.", event: { diff --git a/test/fixtures/cursor-effort.ts b/test/fixtures/cursor-effort.ts index 61337f1..755b3ed 100644 --- a/test/fixtures/cursor-effort.ts +++ b/test/fixtures/cursor-effort.ts @@ -1,4 +1,5 @@ import type { Effort, Payload } from "../../external.ts"; +import packageJson from "../../package.json" with { type: "json" }; /** * Test fixture for Cursor effort levels. @@ -20,6 +21,7 @@ const efforts: Effort[] = ["mini", "auto", "max"]; export default efforts.map((effort) => ({ "~pullfrog": true, + version: packageJson.version, agent: "cursor", prompt: "What is 2 + 2? Reply with just the number.", event: { diff --git a/test/fixtures/gemini-effort.ts b/test/fixtures/gemini-effort.ts index 3521623..82b8326 100644 --- a/test/fixtures/gemini-effort.ts +++ b/test/fixtures/gemini-effort.ts @@ -1,4 +1,5 @@ import type { Effort, Payload } from "../../external.ts"; +import packageJson from "../../package.json" with { type: "json" }; /** * Test fixture for Gemini effort levels. @@ -17,6 +18,7 @@ const efforts: Effort[] = ["mini", "auto", "max"]; export default efforts.map((effort) => ({ "~pullfrog": true, + version: packageJson.version, agent: "gemini", prompt: "What is 2 + 2? Reply with just the number.", event: { diff --git a/utils/payload.test.ts b/utils/payload.test.ts index f432716..12dc149 100644 --- a/utils/payload.test.ts +++ b/utils/payload.test.ts @@ -1,4 +1,4 @@ -import { Inputs } from "./payload.ts"; +import { Inputs, JsonPayload } from "./payload.ts"; describe("Inputs schema", () => { it("only prompt is required", () => { @@ -43,3 +43,34 @@ describe("Inputs schema", () => { } ); }); + +describe("JsonPayload schema", () => { + it("requires ~pullfrog and version", () => { + const result = JsonPayload.assert({ "~pullfrog": true, version: "1.2.3" }); + expect(result).toMatchObject({ "~pullfrog": true, version: "1.2.3" }); + expect(() => JsonPayload.assert({})).toThrow(); + expect(() => JsonPayload.assert({ "~pullfrog": true })).toThrow(); + expect(() => JsonPayload.assert({ version: "1.2.3" })).toThrow(); + }); + + it.each([ + ["prompt", "test prompt"], + ["agent", "claude"], + ["agent", "codex"], + ["agent", "cursor"], + ["agent", "gemini"], + ["agent", "opencode"], + ["effort", "mini"], + ["effort", "auto"], + ["effort", "max"], + ["event", { trigger: "unknown" }], + ] as const)("should accept optional %s with value %s", (prop, value) => { + const input = { "~pullfrog": true, version: "1.2.3", [prop]: value }; + expect(() => JsonPayload.assert(input)).not.toThrow(); + }); + + it.each([["agent"], ["effort"]] as const)("should reject invalid %s values", (prop) => { + const input = { "~pullfrog": true, version: "1.2.3", [prop]: "invalid" as any }; + expect(() => JsonPayload.assert(input)).toThrow(); + }); +}); diff --git a/utils/payload.ts b/utils/payload.ts index c590ed6..4513564 100644 --- a/utils/payload.ts +++ b/utils/payload.ts @@ -2,7 +2,9 @@ import { isAbsolute, resolve } from "node:path"; import * as core from "@actions/core"; import { type } from "arktype"; import { AgentName, type AuthorPermission, Effort, type PayloadEvent } from "../external.ts"; +import packageJson from "../package.json" with { type: "json" }; import type { RepoSettings } from "./repoSettings.ts"; +import { validateCompatibility } from "./versioning.ts"; // tool permission enum types for inputs const ToolPermissionInput = type.enumerated("disabled", "enabled"); @@ -11,8 +13,9 @@ const BashPermissionInput = type.enumerated("disabled", "restricted", "enabled") // schema for JSON payload passed via prompt (internal dispatch invocation) // note: permissions are intentionally NOT included here to prevent injection attacks // permissions are derived from event.authorPermission instead -const JsonPayload = type({ +export const JsonPayload = type({ "~pullfrog": "true", + "version": "string", "agent?": AgentName.or("undefined"), "prompt?": "string", "repoInstructions?": "string", @@ -94,6 +97,9 @@ export function resolvePayload(repoSettings: RepoSettings) { // not JSON, treat as plain string prompt } + // validate version compatibility from jsonPayload + if (jsonPayload) validateCompatibility(jsonPayload.version, packageJson.version); + // resolve event - use type guard for jsonPayload.event, fallback to unknown trigger const rawEvent = jsonPayload?.event; const event: PayloadEvent = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" }; @@ -111,6 +117,7 @@ export function resolvePayload(repoSettings: RepoSettings) { // note: modes are NOT in payload - they come from repoSettings in main() return { "~pullfrog": true as const, + version: jsonPayload?.version ?? packageJson.version, agent: resolvedAgent, // inverted: jsonPayload.prompt extracts the text from the JSON payload, // whereas inputs.prompt IS the raw JSON string when internally dispatched diff --git a/utils/versioning.test.ts b/utils/versioning.test.ts new file mode 100644 index 0000000..15e7f72 --- /dev/null +++ b/utils/versioning.test.ts @@ -0,0 +1,29 @@ +import { describe, it, expect } from 'vitest'; +import { validateCompatibility } from './versioning.ts'; + +describe('validateCompatibility', () => { + it('should throw if payload version is invalid', () => { + expect(() => validateCompatibility('invalid', '1.0.0')).toThrow(/not a valid semantic version/); + }); + + it.each([ + ["1.0.0", "1.0.0"], // same + ["1.0.0-alpha.1", "1.0.0"], // action is newer than pre-release + ["0.1.0", "0.1.1"], // action is newer during active development + ["1.0.0", "1.0.1"], // action patched + ["1.0.0", "1.1.0"], // action has a new feature (backward compatible) + ["1.0.1", "1.0.0"], // payload is newer (patch) + ["1.1.0", "1.0.0"], // payload is newer (feature is backward compatible) + ])('should accept compatible payload %#', (payloadVersion, actionVersion) => { + expect(() => validateCompatibility(payloadVersion, actionVersion)).not.toThrow(); + }); + + it.each([ + ["0.1.0", "0.2.0"], // action had breaking changes during active development + ["0.2.0", "0.1.0"], // payload had breaking changes during active development + ["2.0.0", "1.0.0"], // payload is majorly newer + ["1.0.0", "2.0.0"], // action had breaking changes + ])('should reject incompatible payload %#', (payloadVersion, actionVersion) => { + expect(() => validateCompatibility(payloadVersion, actionVersion)).toThrow(/is incompatible with action version/); + }); +}); diff --git a/utils/versioning.ts b/utils/versioning.ts new file mode 100644 index 0000000..9874141 --- /dev/null +++ b/utils/versioning.ts @@ -0,0 +1,42 @@ +import semver from 'semver'; + +type CompatibilityPolicy = + /** + * Strict policy: the action must support the same features as the payload version declares + * @example Payload version 1.2.3 => ^1.2.0 range of action versions supported + * @example Payload version 0.1.55 => ^0.1.55 range of action versions supported + */ + | 'same-features' + /** + * Loose policy: the action must have no breaking changes compared to the payload version + * @example Payload version 1.2.3 => ^1.0.0 range of action versions supported + * @example Payload version 0.1.55 => ^0.1.0 range of action versions supported + */ + | 'non-breaking'; + +const COMPATIBILITY_POLICY: CompatibilityPolicy = "non-breaking"; + +/** + * @throws Error if the action can't process payload + * The compatibility is determined according to the COMPATIBILITY_POLICY above. + * @param payloadVersion the version of the payload + * @param actionVersion the version of the action (recipient) + */ +export function validateCompatibility(payloadVersion: string, actionVersion: string): void { + const payloadSemVer = semver.parse(payloadVersion); + if (!payloadSemVer) throw new Error(`Payload version ${payloadVersion} is not a valid semantic version.`); + const major = payloadSemVer.major; + const minor = payloadSemVer.minor; + const patch = payloadSemVer.patch; + + const compatibilityRange = COMPATIBILITY_POLICY === 'same-features' + ? `^${major}.${minor}.${major === 0 ? patch : 0}` + : `^${major}.${major === 0 ? minor : 0}.0`; // non-breaking + + if (!semver.satisfies(actionVersion, compatibilityRange)) { + throw new Error( + `Payload version ${payloadVersion} is incompatible with action version ${actionVersion}. ` + + `Please update your workflow to use at least ${semver.minVersion(compatibilityRange)} version of the action.` + ); + } +}