universal-plugin 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/dist/cli.mjs +108 -78
- package/package.json +2 -2
- package/plugin.json +1 -1
- package/readme.md +1 -1
- package/references/plugin-design.md +1 -1
- package/references/universal-plugin.md +1 -1
- package/skills/build-plugin/SKILL.md +1 -1
- package/skills/init-universal-plugin/SKILL.md +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-plugin",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Research and design toolkit for building universal AI coding agent plugins that work across Claude Code, Cursor, Codex, and GitHub Copilot CLI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "unional"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-plugin",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Research and design toolkit for building universal AI coding agent plugins that work across Claude Code, Cursor, Codex, and GitHub Copilot CLI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "unional"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-plugin",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Research and design toolkit for building universal AI coding agent plugins that work across Claude Code, Cursor, Codex, and GitHub Copilot CLI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "unional"
|
package/dist/cli.mjs
CHANGED
|
@@ -26,11 +26,11 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
26
26
|
}
|
|
27
27
|
return to;
|
|
28
28
|
};
|
|
29
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
29
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
30
30
|
value: mod,
|
|
31
31
|
enumerable: true
|
|
32
32
|
}) : target, mod));
|
|
33
|
-
var __require = /*
|
|
33
|
+
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
|
|
34
34
|
//#endregion
|
|
35
35
|
//#region ../../node_modules/.pnpm/commander@14.0.3/node_modules/commander/lib/error.js
|
|
36
36
|
var require_error = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
@@ -102,7 +102,6 @@ var require_argument = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
102
102
|
default:
|
|
103
103
|
this.required = true;
|
|
104
104
|
this._name = name;
|
|
105
|
-
break;
|
|
106
105
|
}
|
|
107
106
|
if (this._name.endsWith("...")) {
|
|
108
107
|
this.variadic = true;
|
|
@@ -1597,16 +1596,20 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1597
1596
|
const oldValue = this.getOptionValue(name);
|
|
1598
1597
|
if (val !== null && option.parseArg) val = this._callParseArg(option, val, oldValue, invalidValueMessage);
|
|
1599
1598
|
else if (val !== null && option.variadic) val = option._collectValue(val, oldValue);
|
|
1600
|
-
if (val == null)
|
|
1601
|
-
|
|
1602
|
-
|
|
1599
|
+
if (val == null) {
|
|
1600
|
+
if (option.negate) val = false;
|
|
1601
|
+
else if (option.isBoolean() || option.optional) val = true;
|
|
1602
|
+
else val = "";
|
|
1603
|
+
}
|
|
1603
1604
|
this.setOptionValueWithSource(name, val, valueSource);
|
|
1604
1605
|
};
|
|
1605
1606
|
this.on("option:" + oname, (val) => {
|
|
1606
|
-
|
|
1607
|
+
const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;
|
|
1608
|
+
handleOptionValue(val, invalidValueMessage, "cli");
|
|
1607
1609
|
});
|
|
1608
1610
|
if (option.envVar) this.on("optionEnv:" + oname, (val) => {
|
|
1609
|
-
|
|
1611
|
+
const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;
|
|
1612
|
+
handleOptionValue(val, invalidValueMessage, "env");
|
|
1610
1613
|
});
|
|
1611
1614
|
return this;
|
|
1612
1615
|
}
|
|
@@ -1997,12 +2000,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1997
2000
|
}
|
|
1998
2001
|
launchWithNode = sourceExt.includes(path$1.extname(executableFile));
|
|
1999
2002
|
let proc;
|
|
2000
|
-
if (process$1.platform !== "win32")
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2003
|
+
if (process$1.platform !== "win32") {
|
|
2004
|
+
if (launchWithNode) {
|
|
2005
|
+
args.unshift(executableFile);
|
|
2006
|
+
args = incrementNodeInspectorPort(process$1.execArgv).concat(args);
|
|
2007
|
+
proc = childProcess$1.spawn(process$1.argv[0], args, { stdio: "inherit" });
|
|
2008
|
+
} else proc = childProcess$1.spawn(executableFile, args, { stdio: "inherit" });
|
|
2009
|
+
} else {
|
|
2006
2010
|
this._checkForMissingExecutable(executableFile, executableDir, subcommand._name);
|
|
2007
2011
|
args.unshift(executableFile);
|
|
2008
2012
|
args = incrementNodeInspectorPort(process$1.execArgv).concat(args);
|
|
@@ -2446,8 +2450,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2446
2450
|
"default",
|
|
2447
2451
|
"config",
|
|
2448
2452
|
"env"
|
|
2449
|
-
].includes(this.getOptionValueSource(optionKey)))
|
|
2450
|
-
|
|
2453
|
+
].includes(this.getOptionValueSource(optionKey))) {
|
|
2454
|
+
if (option.required || option.optional) this.emit(`optionEnv:${option.name()}`, process$1.env[option.envVar]);
|
|
2455
|
+
else this.emit(`optionEnv:${option.name()}`);
|
|
2456
|
+
}
|
|
2451
2457
|
}
|
|
2452
2458
|
});
|
|
2453
2459
|
}
|
|
@@ -3071,7 +3077,7 @@ function resolveOwnVersion(packageJsonPath, deps = {}) {
|
|
|
3071
3077
|
}
|
|
3072
3078
|
//#endregion
|
|
3073
3079
|
//#region src/state/state.ts
|
|
3074
|
-
const KNOWN_ACTION_TYPES = new Set([
|
|
3080
|
+
const KNOWN_ACTION_TYPES = /* @__PURE__ */ new Set([
|
|
3075
3081
|
"install",
|
|
3076
3082
|
"upgrade",
|
|
3077
3083
|
"remove"
|
|
@@ -3784,14 +3790,12 @@ function output(data, view) {
|
|
|
3784
3790
|
//#endregion
|
|
3785
3791
|
//#region ../../node_modules/.pnpm/semver@7.8.1/node_modules/semver/internal/constants.js
|
|
3786
3792
|
var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
3787
|
-
const SEMVER_SPEC_VERSION = "2.0.0";
|
|
3788
|
-
const MAX_LENGTH = 256;
|
|
3789
|
-
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;
|
|
3790
3793
|
module.exports = {
|
|
3791
|
-
MAX_LENGTH,
|
|
3794
|
+
MAX_LENGTH: 256,
|
|
3792
3795
|
MAX_SAFE_COMPONENT_LENGTH: 16,
|
|
3793
|
-
MAX_SAFE_BUILD_LENGTH:
|
|
3794
|
-
MAX_SAFE_INTEGER
|
|
3796
|
+
MAX_SAFE_BUILD_LENGTH: 250,
|
|
3797
|
+
MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER ||
|
|
3798
|
+
/* istanbul ignore next */ 9007199254740991,
|
|
3795
3799
|
RELEASE_TYPES: [
|
|
3796
3800
|
"major",
|
|
3797
3801
|
"premajor",
|
|
@@ -3801,7 +3805,7 @@ var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
3801
3805
|
"prepatch",
|
|
3802
3806
|
"prerelease"
|
|
3803
3807
|
],
|
|
3804
|
-
SEMVER_SPEC_VERSION,
|
|
3808
|
+
SEMVER_SPEC_VERSION: "2.0.0",
|
|
3805
3809
|
FLAG_INCLUDE_PRERELEASE: 1,
|
|
3806
3810
|
FLAG_LOOSE: 2
|
|
3807
3811
|
};
|
|
@@ -3933,9 +3937,10 @@ var require_semver$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
3933
3937
|
module.exports = class SemVer {
|
|
3934
3938
|
constructor(version, options) {
|
|
3935
3939
|
options = parseOptions(options);
|
|
3936
|
-
if (version instanceof SemVer)
|
|
3937
|
-
|
|
3938
|
-
|
|
3940
|
+
if (version instanceof SemVer) {
|
|
3941
|
+
if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) return version;
|
|
3942
|
+
else version = version.version;
|
|
3943
|
+
} else if (typeof version !== "string") throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`);
|
|
3939
3944
|
if (version.length > MAX_LENGTH) throw new TypeError(`version is longer than ${MAX_LENGTH} characters`);
|
|
3940
3945
|
debug("SemVer", version, options);
|
|
3941
3946
|
this.options = options;
|
|
@@ -4356,7 +4361,11 @@ var require_coerce = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4356
4361
|
}
|
|
4357
4362
|
if (match === null) return null;
|
|
4358
4363
|
const major = match[2];
|
|
4359
|
-
|
|
4364
|
+
const minor = match[3] || "0";
|
|
4365
|
+
const patch = match[4] || "0";
|
|
4366
|
+
const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : "";
|
|
4367
|
+
const build = options.includePrerelease && match[6] ? `+${match[6]}` : "";
|
|
4368
|
+
return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options);
|
|
4360
4369
|
};
|
|
4361
4370
|
module.exports = coerce;
|
|
4362
4371
|
}));
|
|
@@ -4372,7 +4381,8 @@ var require_truncate = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4372
4381
|
return clonedVersion && doTruncation(clonedVersion, truncation);
|
|
4373
4382
|
};
|
|
4374
4383
|
const cloneInputVersion = (version, options) => {
|
|
4375
|
-
|
|
4384
|
+
const versionStringToParse = version instanceof SemVer ? version.version : version;
|
|
4385
|
+
return parse(versionStringToParse, options);
|
|
4376
4386
|
};
|
|
4377
4387
|
const doTruncation = (version, truncation) => {
|
|
4378
4388
|
if (isPrerelease(truncation)) return version.version;
|
|
@@ -4382,9 +4392,7 @@ var require_truncate = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4382
4392
|
version.minor = 0;
|
|
4383
4393
|
version.patch = 0;
|
|
4384
4394
|
break;
|
|
4385
|
-
case "minor":
|
|
4386
|
-
version.patch = 0;
|
|
4387
|
-
break;
|
|
4395
|
+
case "minor": version.patch = 0;
|
|
4388
4396
|
}
|
|
4389
4397
|
return version.format();
|
|
4390
4398
|
};
|
|
@@ -4433,8 +4441,10 @@ var require_range = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4433
4441
|
module.exports = class Range {
|
|
4434
4442
|
constructor(range, options) {
|
|
4435
4443
|
options = parseOptions(options);
|
|
4436
|
-
if (range instanceof Range)
|
|
4437
|
-
|
|
4444
|
+
if (range instanceof Range) {
|
|
4445
|
+
if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) return range;
|
|
4446
|
+
else return new Range(range.raw, options);
|
|
4447
|
+
}
|
|
4438
4448
|
if (range instanceof Comparator) {
|
|
4439
4449
|
this.raw = range.value;
|
|
4440
4450
|
this.set = [[range]];
|
|
@@ -4602,18 +4612,21 @@ var require_range = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4602
4612
|
let ret;
|
|
4603
4613
|
if (isX(M)) ret = "";
|
|
4604
4614
|
else if (isX(m)) ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`;
|
|
4605
|
-
else if (isX(p))
|
|
4606
|
-
|
|
4607
|
-
|
|
4615
|
+
else if (isX(p)) {
|
|
4616
|
+
if (M === "0") ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`;
|
|
4617
|
+
else ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`;
|
|
4618
|
+
} else if (pr) {
|
|
4608
4619
|
debug("replaceCaret pr", pr);
|
|
4609
|
-
if (M === "0")
|
|
4610
|
-
|
|
4611
|
-
|
|
4620
|
+
if (M === "0") {
|
|
4621
|
+
if (m === "0") ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`;
|
|
4622
|
+
else ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`;
|
|
4623
|
+
} else ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`;
|
|
4612
4624
|
} else {
|
|
4613
4625
|
debug("no pr");
|
|
4614
|
-
if (M === "0")
|
|
4615
|
-
|
|
4616
|
-
|
|
4626
|
+
if (M === "0") {
|
|
4627
|
+
if (m === "0") ret = `>=${M}.${m}.${p}${z} <${M}.${m}.${+p + 1}-0`;
|
|
4628
|
+
else ret = `>=${M}.${m}.${p}${z} <${M}.${+m + 1}.0-0`;
|
|
4629
|
+
} else ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`;
|
|
4617
4630
|
}
|
|
4618
4631
|
debug("caret return", ret);
|
|
4619
4632
|
return ret;
|
|
@@ -4634,9 +4647,10 @@ var require_range = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4634
4647
|
const anyX = xp;
|
|
4635
4648
|
if (gtlt === "=" && anyX) gtlt = "";
|
|
4636
4649
|
pr = options.includePrerelease ? "-0" : "";
|
|
4637
|
-
if (xM)
|
|
4638
|
-
|
|
4639
|
-
|
|
4650
|
+
if (xM) {
|
|
4651
|
+
if (gtlt === ">" || gtlt === "<") ret = "<0.0.0-0";
|
|
4652
|
+
else ret = "*";
|
|
4653
|
+
} else if (gtlt && anyX) {
|
|
4640
4654
|
if (xm) m = 0;
|
|
4641
4655
|
p = 0;
|
|
4642
4656
|
if (gtlt === ">") {
|
|
@@ -4710,8 +4724,10 @@ var require_comparator = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4710
4724
|
}
|
|
4711
4725
|
constructor(comp, options) {
|
|
4712
4726
|
options = parseOptions(options);
|
|
4713
|
-
if (comp instanceof Comparator)
|
|
4714
|
-
|
|
4727
|
+
if (comp instanceof Comparator) {
|
|
4728
|
+
if (comp.loose === !!options.loose) return comp;
|
|
4729
|
+
else comp = comp.value;
|
|
4730
|
+
}
|
|
4715
4731
|
comp = comp.trim().split(/\s+/).join(" ");
|
|
4716
4732
|
debug("comparator", comp, options);
|
|
4717
4733
|
this.options = options;
|
|
@@ -5031,11 +5047,15 @@ var require_subset = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
5031
5047
|
const minimumVersion = [new Comparator(">=0.0.0")];
|
|
5032
5048
|
const simpleSubset = (sub, dom, options) => {
|
|
5033
5049
|
if (sub === dom) return true;
|
|
5034
|
-
if (sub.length === 1 && sub[0].semver === ANY)
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5050
|
+
if (sub.length === 1 && sub[0].semver === ANY) {
|
|
5051
|
+
if (dom.length === 1 && dom[0].semver === ANY) return true;
|
|
5052
|
+
else if (options.includePrerelease) sub = minimumVersionWithPreRelease;
|
|
5053
|
+
else sub = minimumVersion;
|
|
5054
|
+
}
|
|
5055
|
+
if (dom.length === 1 && dom[0].semver === ANY) {
|
|
5056
|
+
if (options.includePrerelease) return true;
|
|
5057
|
+
else dom = minimumVersion;
|
|
5058
|
+
}
|
|
5039
5059
|
const eqSet = /* @__PURE__ */ new Set();
|
|
5040
5060
|
let gt, lt;
|
|
5041
5061
|
for (const c of sub) if (c.operator === ">" || c.operator === ">=") gt = higherGT(gt, c, options);
|
|
@@ -5169,7 +5189,7 @@ const VENDOR_READS_DEPENDENCIES = {
|
|
|
5169
5189
|
};
|
|
5170
5190
|
/** Vendors the canonical root manifest serves as-is: nothing is derived for them, so a declaration
|
|
5171
5191
|
* they cannot read is ignored at runtime rather than dropped from a file. */
|
|
5172
|
-
const CANONICAL_SERVED$1 = new Set(["copilot-cli"]);
|
|
5192
|
+
const CANONICAL_SERVED$1 = /* @__PURE__ */ new Set(["copilot-cli"]);
|
|
5173
5193
|
/** What Claude Code accepts as a dependency string: a plugin name, an optional `@marketplace`, and an
|
|
5174
5194
|
* optional `@^…` range tail that the runtime strips before resolving. */
|
|
5175
5195
|
const DEPENDENCY_STRING = /^[A-Za-z0-9][-A-Za-z0-9._]*(@[A-Za-z0-9][-A-Za-z0-9._]*)?(@\^[^@]*)?$/;
|
|
@@ -6232,12 +6252,12 @@ const STRING_FIELDS = [
|
|
|
6232
6252
|
"repository",
|
|
6233
6253
|
"license"
|
|
6234
6254
|
];
|
|
6235
|
-
const AUTHOR_FIELDS = new Set([
|
|
6255
|
+
const AUTHOR_FIELDS = /* @__PURE__ */ new Set([
|
|
6236
6256
|
"name",
|
|
6237
6257
|
"email",
|
|
6238
6258
|
"url"
|
|
6239
6259
|
]);
|
|
6240
|
-
const TOP_LEVEL_FIELDS = new Set([
|
|
6260
|
+
const TOP_LEVEL_FIELDS = /* @__PURE__ */ new Set([
|
|
6241
6261
|
"$schema",
|
|
6242
6262
|
"name",
|
|
6243
6263
|
...STRING_FIELDS,
|
|
@@ -6258,7 +6278,7 @@ function validateCanonicalManifest(manifest, opts) {
|
|
|
6258
6278
|
const uext = isObject(manifest.extensions) ? manifest.extensions[UP_NAMESPACE$2] : void 0;
|
|
6259
6279
|
const extension = isObject(uext) ? uext : {};
|
|
6260
6280
|
const harnesses = isObject(extension.harnesses) ? extension.harnesses : {};
|
|
6261
|
-
const declared = [
|
|
6281
|
+
const declared = [.../* @__PURE__ */ new Set([...Array.isArray(extension.vendors) ? extension.vendors.filter((v) => typeof v === "string") : [], ...Object.keys(harnesses)])];
|
|
6262
6282
|
for (const vendor of declared.filter((v) => !opts.knownVendors.has(v))) {
|
|
6263
6283
|
const message = `Unknown vendor "${vendor}" in harnesses`;
|
|
6264
6284
|
warnings.push(message);
|
|
@@ -6315,18 +6335,22 @@ function schemaRuleViolations(manifest, warnings) {
|
|
|
6315
6335
|
else for (const [key, value] of Object.entries(manifest.author)) if (!AUTHOR_FIELDS.has(key)) push(`author.${key}`, "additionalProperties", "unknown author field");
|
|
6316
6336
|
else if (typeof value !== "string") push(`author.${key}`, "type", "must be a string");
|
|
6317
6337
|
}
|
|
6318
|
-
if (manifest.keywords !== void 0)
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
const
|
|
6328
|
-
|
|
6329
|
-
|
|
6338
|
+
if (manifest.keywords !== void 0) {
|
|
6339
|
+
if (!Array.isArray(manifest.keywords)) push("keywords", "type", "must be an array of strings");
|
|
6340
|
+
else manifest.keywords.forEach((keyword, index) => {
|
|
6341
|
+
if (typeof keyword !== "string") push(`keywords[${index}]`, "type", "must be a string");
|
|
6342
|
+
});
|
|
6343
|
+
}
|
|
6344
|
+
if (manifest.extensions !== void 0) {
|
|
6345
|
+
if (!isObject(manifest.extensions)) push("extensions", "type", "must be an object keyed by namespace");
|
|
6346
|
+
else {
|
|
6347
|
+
for (const [namespace, value] of Object.entries(manifest.extensions)) if (!isObject(value)) push(`extensions.${namespace}`, "type", "must be an object");
|
|
6348
|
+
const uext = manifest.extensions[UP_NAMESPACE$2];
|
|
6349
|
+
if (isObject(uext)) {
|
|
6350
|
+
const dependencies = validateDependencies(uext.dependencies);
|
|
6351
|
+
for (const error of dependencies.errors) push(`extensions.${UP_NAMESPACE$2}.dependencies`, "dependencies", error);
|
|
6352
|
+
warnings.push(...dependencies.warnings);
|
|
6353
|
+
}
|
|
6330
6354
|
}
|
|
6331
6355
|
}
|
|
6332
6356
|
for (const key of Object.keys(manifest)) if (!TOP_LEVEL_FIELDS.has(key)) push(key, "additionalProperties", "not an Agent Plugins 1.0.0 field; move tool-specific data under extensions");
|
|
@@ -6346,7 +6370,7 @@ const KNOWN_VENDORS$1 = new Set(Object.keys(VENDOR_OUTPUT));
|
|
|
6346
6370
|
/** Vendors the canonical root manifest serves as-is. The build derives no *manifest* for these —
|
|
6347
6371
|
* writing one would either be shadowed by root (a lower-precedence path) or clobber root itself.
|
|
6348
6372
|
* Their components are a separate question: see COPILOT_NAMESPACE. */
|
|
6349
|
-
const CANONICAL_SERVED = new Set(["copilot-cli"]);
|
|
6373
|
+
const CANONICAL_SERVED = /* @__PURE__ */ new Set(["copilot-cli"]);
|
|
6350
6374
|
/** The reverse-domain directory Copilot CLI reads its native components from once a plugin declares
|
|
6351
6375
|
* the canonical `$schema` (ADR-0015). It REPLACES the plugin root for these kinds — a spec-mode
|
|
6352
6376
|
* runtime does not read `agents/` at all — so the build derives the tree rather than relying on the
|
|
@@ -6506,11 +6530,15 @@ function buildPlugin(root, opts = {}) {
|
|
|
6506
6530
|
}
|
|
6507
6531
|
for (const drop of dedupeDrops(hooks?.drops ?? [])) warnings.push(`${vendor} cannot run the "${drop.type}" hook handler on ${drop.event} — dropped from the derived hooks file`);
|
|
6508
6532
|
const derivedHooksPath = path.join(outputDir, "hooks.json");
|
|
6509
|
-
if (hooks?.changed)
|
|
6510
|
-
|
|
6533
|
+
if (hooks?.changed) {
|
|
6534
|
+
if (hooks.hooks) vendorManifest["hooks"] = `./${path.dirname(relPath).split(path.sep).join("/")}/hooks.json`;
|
|
6535
|
+
else delete vendorManifest["hooks"];
|
|
6536
|
+
}
|
|
6511
6537
|
const derivedMcpPath = path.join(outputDir, "mcp.json");
|
|
6512
|
-
if (mcp?.changed && declaredMcp)
|
|
6513
|
-
|
|
6538
|
+
if (mcp?.changed && declaredMcp) {
|
|
6539
|
+
if (declaredMcp.inline) vendorManifest["mcpServers"] = mcp.servers;
|
|
6540
|
+
else vendorManifest["mcpServers"] = `./${path.dirname(relPath).split(path.sep).join("/")}/mcp.json`;
|
|
6541
|
+
}
|
|
6514
6542
|
if (opts.verbose) {
|
|
6515
6543
|
console.log(`[${vendor}] → ${outputPath}`);
|
|
6516
6544
|
for (const key of Object.keys(vendorFields)) console.log(` + ${key} (from harnesses.${vendor})`);
|
|
@@ -6948,7 +6976,7 @@ function buildCommand() {
|
|
|
6948
6976
|
}
|
|
6949
6977
|
//#endregion
|
|
6950
6978
|
//#region src/pin/fs.ts
|
|
6951
|
-
const TEXT_EXTENSIONS = new Set([
|
|
6979
|
+
const TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
6952
6980
|
".md",
|
|
6953
6981
|
".mdx",
|
|
6954
6982
|
".markdown",
|
|
@@ -7964,7 +7992,7 @@ function readPluginName(manifestPath) {
|
|
|
7964
7992
|
}
|
|
7965
7993
|
/** Entries a copy never carries: the working copy's history and its installed dependencies. Neither
|
|
7966
7994
|
* is part of the plugin, and both dwarf it. */
|
|
7967
|
-
const COPY_EXCLUDED = new Set([".git", "node_modules"]);
|
|
7995
|
+
const COPY_EXCLUDED = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
7968
7996
|
/** Applies one planned write. A replace removes the destination first, so a copy never merges into
|
|
7969
7997
|
* what was there before. A copy dereferences symlinks — a skill linked into the tree has to travel
|
|
7970
7998
|
* as its content, since the destination is read on its own. */
|
|
@@ -9302,8 +9330,10 @@ function runPrepare(opts) {
|
|
|
9302
9330
|
version
|
|
9303
9331
|
});
|
|
9304
9332
|
}
|
|
9305
|
-
if (!dryRun)
|
|
9306
|
-
|
|
9333
|
+
if (!dryRun) {
|
|
9334
|
+
if (scope === "global") prepareFs.writeGlobalState(updatedState);
|
|
9335
|
+
else prepareFs.writeProjectState(updatedState);
|
|
9336
|
+
}
|
|
9307
9337
|
return { newActionCount: actions.length };
|
|
9308
9338
|
}
|
|
9309
9339
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-plugin",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Universal AI agent plugin build tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-plugin",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@types/semver": "^7.7.1",
|
|
51
51
|
"ajv": "^8.20.0",
|
|
52
52
|
"knip": "^6.14.1",
|
|
53
|
-
"tsdown": "^0.
|
|
53
|
+
"tsdown": "^0.23.0",
|
|
54
54
|
"tsx": "^4.22.3",
|
|
55
55
|
"typescript": "^6.0.0",
|
|
56
56
|
"vitest": "^4.1.7"
|
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "universal-plugin",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.1",
|
|
5
5
|
"description": "Research and design toolkit for building universal AI coding agent plugins that work across Claude Code, Cursor, Codex, and GitHub Copilot CLI.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "unional"
|
package/readme.md
CHANGED
|
@@ -110,7 +110,7 @@ TOON by default; pass `--format json` for JSON.
|
|
|
110
110
|
|
|
111
111
|
This package ships its own documents (`plugin-design`, `slash-invocation`, `universal-plugin`) under
|
|
112
112
|
`references/`. Read one with `buddy-agent-harness reference show <name>` in any project that depends
|
|
113
|
-
on `universal-plugin`, or, from a skill, with the `
|
|
113
|
+
on `universal-plugin`, or, from a skill, with the `reference` skill in the `buddy-agent-harness`
|
|
114
114
|
plugin.
|
|
115
115
|
|
|
116
116
|
### Housekeeping
|
|
@@ -330,6 +330,6 @@ Portability rules for skill bodies: keep each `SKILL.md` body under 6,000 chars;
|
|
|
330
330
|
|
|
331
331
|
## References
|
|
332
332
|
|
|
333
|
-
Load `skill-design`, `skill-repo-structure`, and `agent-tool-output` with the `
|
|
333
|
+
Load `skill-design`, `skill-repo-structure`, and `agent-tool-output` with the `reference` skill in the `buddy-agent-harness` plugin.
|
|
334
334
|
|
|
335
335
|
Spec: https://github.com/cyberuni/universal-plugin/blob/main/packages/universal-plugin/.agents/spec/spec.md
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
# Universal Plugin Format
|
|
2
2
|
|
|
3
3
|
The rules for the universal plugin format live in `plugin-design`, which this package also ships.
|
|
4
|
-
Load `plugin-design` with the `
|
|
4
|
+
Load `plugin-design` with the `reference` skill in the `buddy-agent-harness` plugin.
|
|
@@ -117,7 +117,7 @@ Validation runs before the first write, so a failed build leaves the tree untouc
|
|
|
117
117
|
- **Expect a build to pin skill `npx` references.** That is the release-time `plugin bundle`, not
|
|
118
118
|
this step.
|
|
119
119
|
- **Expect a build to copy governances into skills.** A skill loads a reference through the
|
|
120
|
-
`
|
|
120
|
+
`reference` skill in the `buddy-agent-harness` plugin; the build no longer copies them, and
|
|
121
121
|
`--check` is gone.
|
|
122
122
|
|
|
123
123
|
## Related skills
|
|
@@ -38,7 +38,7 @@ This skill owns the **authoring** side: the plugin a project ships. Setting a re
|
|
|
38
38
|
|
|
39
39
|
## Prerequisites
|
|
40
40
|
|
|
41
|
-
Before any work that adds or removes components, load `plugin-design` with the `
|
|
41
|
+
Before any work that adds or removes components, load `plugin-design` with the `reference`
|
|
42
42
|
skill in the `buddy-agent-harness` plugin.
|
|
43
43
|
|
|
44
44
|
It is the authoritative source for which component to reach for and which anti-patterns to avoid.
|
|
@@ -233,7 +233,7 @@ This skill is not a formatter. If the project has one, run it over the written f
|
|
|
233
233
|
|
|
234
234
|
## References
|
|
235
235
|
|
|
236
|
-
- Reference: `plugin-design`, loaded with the `
|
|
236
|
+
- Reference: `plugin-design`, loaded with the `reference` skill in the `buddy-agent-harness` plugin
|
|
237
237
|
- Spec: https://github.com/cyberuni/universal-plugin/blob/main/packages/universal-plugin/.agents/spec/spec.md
|
|
238
238
|
- Manifest schema (Agent Plugins Specification v1.0.0): https://agent-plugins.org/schemas/1.0.0/plugin.schema.json
|
|
239
239
|
- Extension schema (the body of `extensions["org.cyberuni.universal-plugin"]`), shipped in the package at
|