@hasna/skills 0.10.22 → 0.10.23
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/bin/index.js +51 -7
- package/bin/mcp.js +4 -2
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +51 -7
- package/dist/lib/codex-plugin-skill-controls.d.ts +1 -0
- package/dist/sdk/index.js +51 -7
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -36868,7 +36868,7 @@ var package_default;
|
|
|
36868
36868
|
var init_package = __esm(() => {
|
|
36869
36869
|
package_default = {
|
|
36870
36870
|
name: "@hasna/skills",
|
|
36871
|
-
version: "0.10.
|
|
36871
|
+
version: "0.10.23",
|
|
36872
36872
|
description: "Skills library for AI coding agents",
|
|
36873
36873
|
type: "module",
|
|
36874
36874
|
bin: {
|
|
@@ -39931,7 +39931,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
39931
39931
|
}
|
|
39932
39932
|
if (bridge.codexPluginSkills !== undefined)
|
|
39933
39933
|
for (const control of array(bridge.codexPluginSkills, 4096)) {
|
|
39934
|
-
requireBound(object(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "remotePluginId"].includes(key)));
|
|
39934
|
+
requireBound(object(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "mcpSha256", "remotePluginId"].includes(key)));
|
|
39935
39935
|
text(control.name, 129);
|
|
39936
39936
|
text(control.pluginId, 1024);
|
|
39937
39937
|
text(control.namespace, 64);
|
|
@@ -39939,6 +39939,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
39939
39939
|
requireBound(isAbsolute2(control.pluginParent) && resolve3(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
|
|
39940
39940
|
if (control.remotePluginId !== undefined)
|
|
39941
39941
|
requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
|
|
39942
|
+
if (control.mcpSha256 !== undefined)
|
|
39943
|
+
requireBound(typeof control.mcpSha256 === "string" && /^[a-f0-9]{64}$/.test(control.mcpSha256));
|
|
39942
39944
|
if (control.appSha256 !== undefined)
|
|
39943
39945
|
requireBound(typeof control.appSha256 === "string" && /^[a-f0-9]{64}$/.test(control.appSha256));
|
|
39944
39946
|
}
|
|
@@ -51226,6 +51228,42 @@ function appControls(path, read2) {
|
|
|
51226
51228
|
}
|
|
51227
51229
|
return sha2562;
|
|
51228
51230
|
}
|
|
51231
|
+
function mcpControls(path, read2) {
|
|
51232
|
+
const text2 = read2(path);
|
|
51233
|
+
let value, sha2562;
|
|
51234
|
+
try {
|
|
51235
|
+
sha2562 = hashNativeJsonControls(text2);
|
|
51236
|
+
value = JSON.parse(text2);
|
|
51237
|
+
} catch {
|
|
51238
|
+
refuse2();
|
|
51239
|
+
}
|
|
51240
|
+
const object5 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
|
|
51241
|
+
const textField = (v, empty = false) => typeof v === "string" && (empty || Boolean(v.trim())) && Buffer.byteLength(v) <= 16384 && !/[\x00-\x1f\x7f]/.test(v);
|
|
51242
|
+
const envName = (v) => typeof v === "string" && /^[A-Za-z_][A-Za-z0-9_]{0,255}$/.test(v);
|
|
51243
|
+
if (!object5(value) || Object.keys(value).length !== 1 || !object5(value.mcpServers))
|
|
51244
|
+
refuse2();
|
|
51245
|
+
const servers = Object.entries(value.mcpServers);
|
|
51246
|
+
if (!servers.length || servers.length > 256)
|
|
51247
|
+
refuse2();
|
|
51248
|
+
for (const [name, server] of servers) {
|
|
51249
|
+
if (!identifier2(name) || !object5(server) || !Object.keys(server).every((key) => ["command", "args", "cwd", "env_vars"].includes(key)) || !textField(server.command) || server.args !== undefined && (!Array.isArray(server.args) || server.args.length > 256 || !server.args.every((arg) => textField(arg, true))) || server.cwd !== undefined && !textField(server.cwd))
|
|
51250
|
+
refuse2();
|
|
51251
|
+
if (server.env_vars !== undefined) {
|
|
51252
|
+
if (!Array.isArray(server.env_vars) || server.env_vars.length > 256)
|
|
51253
|
+
refuse2();
|
|
51254
|
+
const names = server.env_vars.map((entry) => {
|
|
51255
|
+
if (envName(entry))
|
|
51256
|
+
return entry;
|
|
51257
|
+
if (!object5(entry) || !Object.keys(entry).every((key) => ["name", "source"].includes(key)) || !envName(entry.name) || entry.source !== undefined && entry.source !== "local")
|
|
51258
|
+
refuse2();
|
|
51259
|
+
return entry.name;
|
|
51260
|
+
});
|
|
51261
|
+
if (new Set(names).size !== names.length)
|
|
51262
|
+
refuse2();
|
|
51263
|
+
}
|
|
51264
|
+
}
|
|
51265
|
+
return sha2562;
|
|
51266
|
+
}
|
|
51229
51267
|
function rootControls(root, read2) {
|
|
51230
51268
|
const manifestPath = join18(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync12(manifestPath, { throwIfNoEntry: false });
|
|
51231
51269
|
if (!lstatSync12(join18(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
|
|
@@ -51243,15 +51281,21 @@ function rootControls(root, read2) {
|
|
|
51243
51281
|
const cacheVersion = basename5(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
51244
51282
|
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
51245
51283
|
refuse2();
|
|
51246
|
-
if (manifest.hooks !== undefined || manifest.
|
|
51284
|
+
if (manifest.hooks !== undefined || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync12(join18(root, "hooks"), { throwIfNoEntry: false }))
|
|
51285
|
+
refuse2();
|
|
51286
|
+
const mcp = join18(root, ".mcp.json"), mcpPresent = lstatSync12(mcp, { throwIfNoEntry: false });
|
|
51287
|
+
if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync5(mcp) !== mcp))
|
|
51288
|
+
refuse2();
|
|
51289
|
+
if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
|
|
51247
51290
|
refuse2();
|
|
51291
|
+
const mcpSha256 = mcpPresent ? mcpControls(mcp, read2) : undefined;
|
|
51248
51292
|
const app = join18(root, ".app.json"), present = lstatSync12(app, { throwIfNoEntry: false });
|
|
51249
51293
|
if (present && (!present.isFile() || present.isSymbolicLink() || present.size > 1024 * 1024))
|
|
51250
51294
|
refuse2();
|
|
51251
51295
|
if (manifest.apps !== undefined && !present)
|
|
51252
51296
|
refuse2();
|
|
51253
51297
|
const appSha256 = present ? appControls(app, read2) : undefined;
|
|
51254
|
-
return { namespace: manifest.name, manifestSha256, ...appSha256 ? { appSha256 } : {} };
|
|
51298
|
+
return { namespace: manifest.name, manifestSha256, ...appSha256 ? { appSha256 } : {}, ...mcpSha256 ? { mcpSha256 } : {} };
|
|
51255
51299
|
}
|
|
51256
51300
|
function identity4(document3, cache3, read2) {
|
|
51257
51301
|
if (!document3.startsWith(cache3 + sep4) || !document3.endsWith(sep4 + "SKILL.md"))
|
|
@@ -51314,7 +51358,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache3, controls, read2) {
|
|
|
51314
51358
|
if (!stat.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync12(join18(root, path), { throwIfNoEntry: false })))
|
|
51315
51359
|
continue;
|
|
51316
51360
|
const parsed = rootControls(root, read2);
|
|
51317
|
-
if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256))
|
|
51361
|
+
if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256 && control.mcpSha256 === parsed.mcpSha256))
|
|
51318
51362
|
return false;
|
|
51319
51363
|
}
|
|
51320
51364
|
}
|
|
@@ -51374,7 +51418,7 @@ function reviewCodexPluginSkillControls(catalog, documents, cache3, cwd2, read2,
|
|
|
51374
51418
|
}
|
|
51375
51419
|
result2.push({ ...parsed, pluginId: expectedPluginId, ...remotePluginId ? { remotePluginId } : {} });
|
|
51376
51420
|
}
|
|
51377
|
-
if (!result2.length || new Set(result2.map((item) => item.name)).size !== result2.length)
|
|
51421
|
+
if (!result2.length && documents.some((document3) => document3.startsWith(cache3 + sep4)) || new Set(result2.map((item) => item.name)).size !== result2.length)
|
|
51378
51422
|
refuse2();
|
|
51379
51423
|
return result2;
|
|
51380
51424
|
}
|
|
@@ -51387,7 +51431,7 @@ function isReviewedCodexPluginSkillDisabled(document3, cache3, controls, rules,
|
|
|
51387
51431
|
} catch {
|
|
51388
51432
|
return false;
|
|
51389
51433
|
}
|
|
51390
|
-
const reviewed = controls.find((item) => item.name === parsed.name && item.namespace === parsed.namespace && item.pluginParent === parsed.pluginParent && item.manifestSha256 === parsed.manifestSha256 && item.appSha256 === parsed.appSha256);
|
|
51434
|
+
const reviewed = controls.find((item) => item.name === parsed.name && item.namespace === parsed.namespace && item.pluginParent === parsed.pluginParent && item.manifestSha256 === parsed.manifestSha256 && item.appSha256 === parsed.appSha256 && item.mcpSha256 === parsed.mcpSha256);
|
|
51391
51435
|
if (!reviewed || reviewed.remotePluginId !== undefined && !remoteInstallationMatches(reviewed.pluginParent, reviewed.remotePluginId, read2))
|
|
51392
51436
|
return false;
|
|
51393
51437
|
return isCodexNativeSkillDisabled({ name: parsed.name, path: document3, pluginId: reviewed.pluginId, enabled: true }, rules);
|
package/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.10.
|
|
20022
|
+
version: "0.10.23",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -38253,7 +38253,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38253
38253
|
}
|
|
38254
38254
|
if (bridge.codexPluginSkills !== undefined)
|
|
38255
38255
|
for (const control of array3(bridge.codexPluginSkills, 4096)) {
|
|
38256
|
-
requireBound(object4(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "remotePluginId"].includes(key)));
|
|
38256
|
+
requireBound(object4(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "mcpSha256", "remotePluginId"].includes(key)));
|
|
38257
38257
|
text(control.name, 129);
|
|
38258
38258
|
text(control.pluginId, 1024);
|
|
38259
38259
|
text(control.namespace, 64);
|
|
@@ -38261,6 +38261,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38261
38261
|
requireBound(isAbsolute3(control.pluginParent) && resolve2(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
|
|
38262
38262
|
if (control.remotePluginId !== undefined)
|
|
38263
38263
|
requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
|
|
38264
|
+
if (control.mcpSha256 !== undefined)
|
|
38265
|
+
requireBound(typeof control.mcpSha256 === "string" && /^[a-f0-9]{64}$/.test(control.mcpSha256));
|
|
38264
38266
|
if (control.appSha256 !== undefined)
|
|
38265
38267
|
requireBound(typeof control.appSha256 === "string" && /^[a-f0-9]{64}$/.test(control.appSha256));
|
|
38266
38268
|
}
|
package/bin/migrate.js
CHANGED
package/bin/server.js
CHANGED
|
@@ -24122,7 +24122,7 @@ var init_dist_es9 = __esm(() => {
|
|
|
24122
24122
|
// package.json
|
|
24123
24123
|
var package_default = {
|
|
24124
24124
|
name: "@hasna/skills",
|
|
24125
|
-
version: "0.10.
|
|
24125
|
+
version: "0.10.23",
|
|
24126
24126
|
description: "Skills library for AI coding agents",
|
|
24127
24127
|
type: "module",
|
|
24128
24128
|
bin: {
|
package/bin/worker.js
CHANGED
|
@@ -24125,7 +24125,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
24125
24125
|
// package.json
|
|
24126
24126
|
var package_default = {
|
|
24127
24127
|
name: "@hasna/skills",
|
|
24128
|
-
version: "0.10.
|
|
24128
|
+
version: "0.10.23",
|
|
24129
24129
|
description: "Skills library for AI coding agents",
|
|
24130
24130
|
type: "module",
|
|
24131
24131
|
bin: {
|
package/dist/index.js
CHANGED
|
@@ -9038,7 +9038,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
9038
9038
|
}
|
|
9039
9039
|
if (bridge.codexPluginSkills !== undefined)
|
|
9040
9040
|
for (const control of array(bridge.codexPluginSkills, 4096)) {
|
|
9041
|
-
requireBound(object(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "remotePluginId"].includes(key)));
|
|
9041
|
+
requireBound(object(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "mcpSha256", "remotePluginId"].includes(key)));
|
|
9042
9042
|
text(control.name, 129);
|
|
9043
9043
|
text(control.pluginId, 1024);
|
|
9044
9044
|
text(control.namespace, 64);
|
|
@@ -9046,6 +9046,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
9046
9046
|
requireBound(isAbsolute2(control.pluginParent) && resolve2(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
|
|
9047
9047
|
if (control.remotePluginId !== undefined)
|
|
9048
9048
|
requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
|
|
9049
|
+
if (control.mcpSha256 !== undefined)
|
|
9050
|
+
requireBound(typeof control.mcpSha256 === "string" && /^[a-f0-9]{64}$/.test(control.mcpSha256));
|
|
9049
9051
|
if (control.appSha256 !== undefined)
|
|
9050
9052
|
requireBound(typeof control.appSha256 === "string" && /^[a-f0-9]{64}$/.test(control.appSha256));
|
|
9051
9053
|
}
|
|
@@ -10879,7 +10881,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
|
|
|
10879
10881
|
// package.json
|
|
10880
10882
|
var package_default = {
|
|
10881
10883
|
name: "@hasna/skills",
|
|
10882
|
-
version: "0.10.
|
|
10884
|
+
version: "0.10.23",
|
|
10883
10885
|
description: "Skills library for AI coding agents",
|
|
10884
10886
|
type: "module",
|
|
10885
10887
|
bin: {
|
|
@@ -13367,6 +13369,42 @@ function appControls(path, read2) {
|
|
|
13367
13369
|
}
|
|
13368
13370
|
return sha2562;
|
|
13369
13371
|
}
|
|
13372
|
+
function mcpControls(path, read2) {
|
|
13373
|
+
const text2 = read2(path);
|
|
13374
|
+
let value, sha2562;
|
|
13375
|
+
try {
|
|
13376
|
+
sha2562 = hashNativeJsonControls(text2);
|
|
13377
|
+
value = JSON.parse(text2);
|
|
13378
|
+
} catch {
|
|
13379
|
+
refuse2();
|
|
13380
|
+
}
|
|
13381
|
+
const object5 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
|
|
13382
|
+
const textField = (v, empty = false) => typeof v === "string" && (empty || Boolean(v.trim())) && Buffer.byteLength(v) <= 16384 && !/[\x00-\x1f\x7f]/.test(v);
|
|
13383
|
+
const envName = (v) => typeof v === "string" && /^[A-Za-z_][A-Za-z0-9_]{0,255}$/.test(v);
|
|
13384
|
+
if (!object5(value) || Object.keys(value).length !== 1 || !object5(value.mcpServers))
|
|
13385
|
+
refuse2();
|
|
13386
|
+
const servers = Object.entries(value.mcpServers);
|
|
13387
|
+
if (!servers.length || servers.length > 256)
|
|
13388
|
+
refuse2();
|
|
13389
|
+
for (const [name, server] of servers) {
|
|
13390
|
+
if (!identifier2(name) || !object5(server) || !Object.keys(server).every((key) => ["command", "args", "cwd", "env_vars"].includes(key)) || !textField(server.command) || server.args !== undefined && (!Array.isArray(server.args) || server.args.length > 256 || !server.args.every((arg) => textField(arg, true))) || server.cwd !== undefined && !textField(server.cwd))
|
|
13391
|
+
refuse2();
|
|
13392
|
+
if (server.env_vars !== undefined) {
|
|
13393
|
+
if (!Array.isArray(server.env_vars) || server.env_vars.length > 256)
|
|
13394
|
+
refuse2();
|
|
13395
|
+
const names = server.env_vars.map((entry) => {
|
|
13396
|
+
if (envName(entry))
|
|
13397
|
+
return entry;
|
|
13398
|
+
if (!object5(entry) || !Object.keys(entry).every((key) => ["name", "source"].includes(key)) || !envName(entry.name) || entry.source !== undefined && entry.source !== "local")
|
|
13399
|
+
refuse2();
|
|
13400
|
+
return entry.name;
|
|
13401
|
+
});
|
|
13402
|
+
if (new Set(names).size !== names.length)
|
|
13403
|
+
refuse2();
|
|
13404
|
+
}
|
|
13405
|
+
}
|
|
13406
|
+
return sha2562;
|
|
13407
|
+
}
|
|
13370
13408
|
function rootControls(root, read2) {
|
|
13371
13409
|
const manifestPath = join14(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync12(manifestPath, { throwIfNoEntry: false });
|
|
13372
13410
|
if (!lstatSync12(join14(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
|
|
@@ -13384,15 +13422,21 @@ function rootControls(root, read2) {
|
|
|
13384
13422
|
const cacheVersion = basename5(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
13385
13423
|
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
13386
13424
|
refuse2();
|
|
13387
|
-
if (manifest.hooks !== undefined || manifest.
|
|
13425
|
+
if (manifest.hooks !== undefined || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync12(join14(root, "hooks"), { throwIfNoEntry: false }))
|
|
13426
|
+
refuse2();
|
|
13427
|
+
const mcp = join14(root, ".mcp.json"), mcpPresent = lstatSync12(mcp, { throwIfNoEntry: false });
|
|
13428
|
+
if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync5(mcp) !== mcp))
|
|
13429
|
+
refuse2();
|
|
13430
|
+
if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
|
|
13388
13431
|
refuse2();
|
|
13432
|
+
const mcpSha256 = mcpPresent ? mcpControls(mcp, read2) : undefined;
|
|
13389
13433
|
const app = join14(root, ".app.json"), present = lstatSync12(app, { throwIfNoEntry: false });
|
|
13390
13434
|
if (present && (!present.isFile() || present.isSymbolicLink() || present.size > 1024 * 1024))
|
|
13391
13435
|
refuse2();
|
|
13392
13436
|
if (manifest.apps !== undefined && !present)
|
|
13393
13437
|
refuse2();
|
|
13394
13438
|
const appSha256 = present ? appControls(app, read2) : undefined;
|
|
13395
|
-
return { namespace: manifest.name, manifestSha256, ...appSha256 ? { appSha256 } : {} };
|
|
13439
|
+
return { namespace: manifest.name, manifestSha256, ...appSha256 ? { appSha256 } : {}, ...mcpSha256 ? { mcpSha256 } : {} };
|
|
13396
13440
|
}
|
|
13397
13441
|
function identity3(document2, cache, read2) {
|
|
13398
13442
|
if (!document2.startsWith(cache + sep4) || !document2.endsWith(sep4 + "SKILL.md"))
|
|
@@ -13455,7 +13499,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read2) {
|
|
|
13455
13499
|
if (!stat.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync12(join14(root, path), { throwIfNoEntry: false })))
|
|
13456
13500
|
continue;
|
|
13457
13501
|
const parsed = rootControls(root, read2);
|
|
13458
|
-
if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256))
|
|
13502
|
+
if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256 && control.mcpSha256 === parsed.mcpSha256))
|
|
13459
13503
|
return false;
|
|
13460
13504
|
}
|
|
13461
13505
|
}
|
|
@@ -13515,7 +13559,7 @@ function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read2, r
|
|
|
13515
13559
|
}
|
|
13516
13560
|
result.push({ ...parsed, pluginId: expectedPluginId, ...remotePluginId ? { remotePluginId } : {} });
|
|
13517
13561
|
}
|
|
13518
|
-
if (!result.length || new Set(result.map((item) => item.name)).size !== result.length)
|
|
13562
|
+
if (!result.length && documents.some((document2) => document2.startsWith(cache + sep4)) || new Set(result.map((item) => item.name)).size !== result.length)
|
|
13519
13563
|
refuse2();
|
|
13520
13564
|
return result;
|
|
13521
13565
|
}
|
|
@@ -13528,7 +13572,7 @@ function isReviewedCodexPluginSkillDisabled(document2, cache, controls, rules, r
|
|
|
13528
13572
|
} catch {
|
|
13529
13573
|
return false;
|
|
13530
13574
|
}
|
|
13531
|
-
const reviewed = controls.find((item) => item.name === parsed.name && item.namespace === parsed.namespace && item.pluginParent === parsed.pluginParent && item.manifestSha256 === parsed.manifestSha256 && item.appSha256 === parsed.appSha256);
|
|
13575
|
+
const reviewed = controls.find((item) => item.name === parsed.name && item.namespace === parsed.namespace && item.pluginParent === parsed.pluginParent && item.manifestSha256 === parsed.manifestSha256 && item.appSha256 === parsed.appSha256 && item.mcpSha256 === parsed.mcpSha256);
|
|
13532
13576
|
if (!reviewed || reviewed.remotePluginId !== undefined && !remoteInstallationMatches(reviewed.pluginParent, reviewed.remotePluginId, read2))
|
|
13533
13577
|
return false;
|
|
13534
13578
|
return isCodexNativeSkillDisabled({ name: parsed.name, path: document2, pluginId: reviewed.pluginId, enabled: true }, rules);
|
package/dist/sdk/index.js
CHANGED
|
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
|
|
|
32373
32373
|
// package.json
|
|
32374
32374
|
var package_default = {
|
|
32375
32375
|
name: "@hasna/skills",
|
|
32376
|
-
version: "0.10.
|
|
32376
|
+
version: "0.10.23",
|
|
32377
32377
|
description: "Skills library for AI coding agents",
|
|
32378
32378
|
type: "module",
|
|
32379
32379
|
bin: {
|
|
@@ -38347,6 +38347,42 @@ function appControls(path, read) {
|
|
|
38347
38347
|
}
|
|
38348
38348
|
return sha2562;
|
|
38349
38349
|
}
|
|
38350
|
+
function mcpControls(path, read) {
|
|
38351
|
+
const text = read(path);
|
|
38352
|
+
let value, sha2562;
|
|
38353
|
+
try {
|
|
38354
|
+
sha2562 = hashNativeJsonControls(text);
|
|
38355
|
+
value = JSON.parse(text);
|
|
38356
|
+
} catch {
|
|
38357
|
+
refuse3();
|
|
38358
|
+
}
|
|
38359
|
+
const object3 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
|
|
38360
|
+
const textField = (v, empty = false) => typeof v === "string" && (empty || Boolean(v.trim())) && Buffer.byteLength(v) <= 16384 && !/[\x00-\x1f\x7f]/.test(v);
|
|
38361
|
+
const envName = (v) => typeof v === "string" && /^[A-Za-z_][A-Za-z0-9_]{0,255}$/.test(v);
|
|
38362
|
+
if (!object3(value) || Object.keys(value).length !== 1 || !object3(value.mcpServers))
|
|
38363
|
+
refuse3();
|
|
38364
|
+
const servers = Object.entries(value.mcpServers);
|
|
38365
|
+
if (!servers.length || servers.length > 256)
|
|
38366
|
+
refuse3();
|
|
38367
|
+
for (const [name, server] of servers) {
|
|
38368
|
+
if (!identifier3(name) || !object3(server) || !Object.keys(server).every((key) => ["command", "args", "cwd", "env_vars"].includes(key)) || !textField(server.command) || server.args !== undefined && (!Array.isArray(server.args) || server.args.length > 256 || !server.args.every((arg) => textField(arg, true))) || server.cwd !== undefined && !textField(server.cwd))
|
|
38369
|
+
refuse3();
|
|
38370
|
+
if (server.env_vars !== undefined) {
|
|
38371
|
+
if (!Array.isArray(server.env_vars) || server.env_vars.length > 256)
|
|
38372
|
+
refuse3();
|
|
38373
|
+
const names = server.env_vars.map((entry) => {
|
|
38374
|
+
if (envName(entry))
|
|
38375
|
+
return entry;
|
|
38376
|
+
if (!object3(entry) || !Object.keys(entry).every((key) => ["name", "source"].includes(key)) || !envName(entry.name) || entry.source !== undefined && entry.source !== "local")
|
|
38377
|
+
refuse3();
|
|
38378
|
+
return entry.name;
|
|
38379
|
+
});
|
|
38380
|
+
if (new Set(names).size !== names.length)
|
|
38381
|
+
refuse3();
|
|
38382
|
+
}
|
|
38383
|
+
}
|
|
38384
|
+
return sha2562;
|
|
38385
|
+
}
|
|
38350
38386
|
function rootControls(root, read) {
|
|
38351
38387
|
const manifestPath = join10(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync6(manifestPath, { throwIfNoEntry: false });
|
|
38352
38388
|
if (!lstatSync6(join10(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
|
|
@@ -38364,15 +38400,21 @@ function rootControls(root, read) {
|
|
|
38364
38400
|
const cacheVersion = basename3(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
38365
38401
|
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
38366
38402
|
refuse3();
|
|
38367
|
-
if (manifest.hooks !== undefined || manifest.
|
|
38403
|
+
if (manifest.hooks !== undefined || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync6(join10(root, "hooks"), { throwIfNoEntry: false }))
|
|
38404
|
+
refuse3();
|
|
38405
|
+
const mcp = join10(root, ".mcp.json"), mcpPresent = lstatSync6(mcp, { throwIfNoEntry: false });
|
|
38406
|
+
if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync5(mcp) !== mcp))
|
|
38407
|
+
refuse3();
|
|
38408
|
+
if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
|
|
38368
38409
|
refuse3();
|
|
38410
|
+
const mcpSha256 = mcpPresent ? mcpControls(mcp, read) : undefined;
|
|
38369
38411
|
const app = join10(root, ".app.json"), present = lstatSync6(app, { throwIfNoEntry: false });
|
|
38370
38412
|
if (present && (!present.isFile() || present.isSymbolicLink() || present.size > 1024 * 1024))
|
|
38371
38413
|
refuse3();
|
|
38372
38414
|
if (manifest.apps !== undefined && !present)
|
|
38373
38415
|
refuse3();
|
|
38374
38416
|
const appSha256 = present ? appControls(app, read) : undefined;
|
|
38375
|
-
return { namespace: manifest.name, manifestSha256, ...appSha256 ? { appSha256 } : {} };
|
|
38417
|
+
return { namespace: manifest.name, manifestSha256, ...appSha256 ? { appSha256 } : {}, ...mcpSha256 ? { mcpSha256 } : {} };
|
|
38376
38418
|
}
|
|
38377
38419
|
function identity(document, cache, read) {
|
|
38378
38420
|
if (!document.startsWith(cache + sep2) || !document.endsWith(sep2 + "SKILL.md"))
|
|
@@ -38435,7 +38477,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read) {
|
|
|
38435
38477
|
if (!stat.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync6(join10(root, path), { throwIfNoEntry: false })))
|
|
38436
38478
|
continue;
|
|
38437
38479
|
const parsed = rootControls(root, read);
|
|
38438
|
-
if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256))
|
|
38480
|
+
if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256 && control.mcpSha256 === parsed.mcpSha256))
|
|
38439
38481
|
return false;
|
|
38440
38482
|
}
|
|
38441
38483
|
}
|
|
@@ -38495,7 +38537,7 @@ function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read, ru
|
|
|
38495
38537
|
}
|
|
38496
38538
|
result.push({ ...parsed, pluginId: expectedPluginId, ...remotePluginId ? { remotePluginId } : {} });
|
|
38497
38539
|
}
|
|
38498
|
-
if (!result.length || new Set(result.map((item) => item.name)).size !== result.length)
|
|
38540
|
+
if (!result.length && documents.some((document) => document.startsWith(cache + sep2)) || new Set(result.map((item) => item.name)).size !== result.length)
|
|
38499
38541
|
refuse3();
|
|
38500
38542
|
return result;
|
|
38501
38543
|
}
|
|
@@ -38508,7 +38550,7 @@ function isReviewedCodexPluginSkillDisabled(document, cache, controls, rules, re
|
|
|
38508
38550
|
} catch {
|
|
38509
38551
|
return false;
|
|
38510
38552
|
}
|
|
38511
|
-
const reviewed = controls.find((item) => item.name === parsed.name && item.namespace === parsed.namespace && item.pluginParent === parsed.pluginParent && item.manifestSha256 === parsed.manifestSha256 && item.appSha256 === parsed.appSha256);
|
|
38553
|
+
const reviewed = controls.find((item) => item.name === parsed.name && item.namespace === parsed.namespace && item.pluginParent === parsed.pluginParent && item.manifestSha256 === parsed.manifestSha256 && item.appSha256 === parsed.appSha256 && item.mcpSha256 === parsed.mcpSha256);
|
|
38512
38554
|
if (!reviewed || reviewed.remotePluginId !== undefined && !remoteInstallationMatches(reviewed.pluginParent, reviewed.remotePluginId, read))
|
|
38513
38555
|
return false;
|
|
38514
38556
|
return isCodexNativeSkillDisabled({ name: parsed.name, path: document, pluginId: reviewed.pluginId, enabled: true }, rules);
|
|
@@ -38860,7 +38902,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38860
38902
|
}
|
|
38861
38903
|
if (bridge.codexPluginSkills !== undefined)
|
|
38862
38904
|
for (const control of array(bridge.codexPluginSkills, 4096)) {
|
|
38863
|
-
requireBound(object3(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "remotePluginId"].includes(key)));
|
|
38905
|
+
requireBound(object3(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "mcpSha256", "remotePluginId"].includes(key)));
|
|
38864
38906
|
text(control.name, 129);
|
|
38865
38907
|
text(control.pluginId, 1024);
|
|
38866
38908
|
text(control.namespace, 64);
|
|
@@ -38868,6 +38910,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38868
38910
|
requireBound(isAbsolute6(control.pluginParent) && resolve5(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
|
|
38869
38911
|
if (control.remotePluginId !== undefined)
|
|
38870
38912
|
requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
|
|
38913
|
+
if (control.mcpSha256 !== undefined)
|
|
38914
|
+
requireBound(typeof control.mcpSha256 === "string" && /^[a-f0-9]{64}$/.test(control.mcpSha256));
|
|
38871
38915
|
if (control.appSha256 !== undefined)
|
|
38872
38916
|
requireBound(typeof control.appSha256 === "string" && /^[a-f0-9]{64}$/.test(control.appSha256));
|
|
38873
38917
|
}
|