@hasna/skills 0.10.91 → 0.10.92
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/THIRD_PARTY_NOTICES +1 -1
- package/bin/index.js +247 -24
- package/bin/mcp.js +263 -24
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.js +245 -23
- package/dist/lib/agent-discovery.d.ts +14 -1
- package/dist/runtime-prerequisites.js +1 -1
- package/dist/sdk/index.js +497 -275
- package/package.json +1 -1
package/bin/mcp.js
CHANGED
|
@@ -38,7 +38,7 @@ var package_default;
|
|
|
38
38
|
var init_package = __esm(() => {
|
|
39
39
|
package_default = {
|
|
40
40
|
name: "@hasna/skills",
|
|
41
|
-
version: "0.10.
|
|
41
|
+
version: "0.10.92",
|
|
42
42
|
description: "Skills library for AI coding agents",
|
|
43
43
|
type: "module",
|
|
44
44
|
bin: {
|
|
@@ -22526,6 +22526,11 @@ var init_agent_opencode = __esm(() => {
|
|
|
22526
22526
|
});
|
|
22527
22527
|
|
|
22528
22528
|
// src/lib/agent-adapters.ts
|
|
22529
|
+
function renderAgentHookCommand(command, agent, profileId, event) {
|
|
22530
|
+
if (typeof profileId !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(profileId) || profileId.includes(".."))
|
|
22531
|
+
throw new Error("Invalid selection profile id");
|
|
22532
|
+
return `'${command.replace(/'/g, `'\\''`)}' hook user-prompt --agent ${agent} --selection-profile ${profileId} --event ${event}`;
|
|
22533
|
+
}
|
|
22529
22534
|
var INTEGRATION_AGENTS;
|
|
22530
22535
|
var init_agent_adapters = __esm(() => {
|
|
22531
22536
|
init_agent_opencode();
|
|
@@ -30556,6 +30561,17 @@ function parseHermesConfig(text2) {
|
|
|
30556
30561
|
throw new Error(`Expected Hermes ${name} object`);
|
|
30557
30562
|
return value;
|
|
30558
30563
|
}
|
|
30564
|
+
function quoted(value) {
|
|
30565
|
+
if (!value || /[\0\r\n]/.test(value))
|
|
30566
|
+
throw new Error("Invalid Hermes Skills command");
|
|
30567
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
30568
|
+
}
|
|
30569
|
+
function hermesHookDefinitions(supervisor) {
|
|
30570
|
+
if (!isAbsolute7(supervisor.runtime) || !isAbsolute7(supervisor.path))
|
|
30571
|
+
throw new Error("Expected absolute Hermes supervisor paths");
|
|
30572
|
+
const entry = (event) => ({ command: `${quoted(supervisor.runtime)} ${quoted(supervisor.path)} --event ${event}`, timeout: 15, ...event === "pre_tool_call" ? { fail_closed: true } : {} });
|
|
30573
|
+
return { pre_llm_call: entry("pre_llm_call"), pre_tool_call: entry("pre_tool_call") };
|
|
30574
|
+
}
|
|
30559
30575
|
function assertHermesEnvironment(home) {
|
|
30560
30576
|
if (process.env.TERMINAL_CWD && process.env.TERMINAL_CWD !== process.cwd())
|
|
30561
30577
|
throw new NativeBridgeIntegrityRefusal("NATIVE_SKILL_DRIFT: Hermes TERMINAL_CWD must match the checked process working directory; review the effective project before using this adapter");
|
|
@@ -38666,9 +38682,94 @@ function nativeDiscoveryAliasTargets(roots, home) {
|
|
|
38666
38682
|
}
|
|
38667
38683
|
return [...targets];
|
|
38668
38684
|
}
|
|
38685
|
+
function hooksAreManagedBridge(agent, hooks, managed) {
|
|
38686
|
+
const table = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
38687
|
+
const exactKeys3 = (value, keys2) => Object.keys(value).sort().join("\x00") === [...keys2].sort().join("\x00");
|
|
38688
|
+
if (!table(hooks) || typeof managed.command !== "string" || !isAbsolute22(managed.command))
|
|
38689
|
+
return false;
|
|
38690
|
+
const events3 = agent === "gemini" ? ["BeforeAgent", "SessionStart", "BeforeTool"] : ["beforeSubmitPrompt", "sessionStart"];
|
|
38691
|
+
for (const [event, entries] of Object.entries(hooks)) {
|
|
38692
|
+
if (!events3.includes(event) || !Array.isArray(entries) || entries.length !== 1)
|
|
38693
|
+
return false;
|
|
38694
|
+
let expected;
|
|
38695
|
+
try {
|
|
38696
|
+
expected = renderAgentHookCommand(managed.command, agent, managed.profile, event);
|
|
38697
|
+
} catch {
|
|
38698
|
+
return false;
|
|
38699
|
+
}
|
|
38700
|
+
const entry = entries[0];
|
|
38701
|
+
if (!table(entry))
|
|
38702
|
+
return false;
|
|
38703
|
+
if (agent === "cursor") {
|
|
38704
|
+
if (!exactKeys3(entry, ["command", "timeout"]) || entry.timeout !== 15 || entry.command !== expected)
|
|
38705
|
+
return false;
|
|
38706
|
+
continue;
|
|
38707
|
+
}
|
|
38708
|
+
if (!exactKeys3(entry, event === "BeforeTool" ? ["hooks", "matcher"] : ["hooks"]) || event === "BeforeTool" && entry.matcher !== "activate_skill" || !Array.isArray(entry.hooks) || entry.hooks.length !== 1)
|
|
38709
|
+
return false;
|
|
38710
|
+
const hook = entry.hooks[0];
|
|
38711
|
+
if (!table(hook) || !exactKeys3(hook, ["command", "timeout", "type"]) || hook.type !== "command" || hook.timeout !== 15000 || hook.command !== expected)
|
|
38712
|
+
return false;
|
|
38713
|
+
}
|
|
38714
|
+
return true;
|
|
38715
|
+
}
|
|
38716
|
+
function sumiPluginLoadsOnlyBuiltins(text2) {
|
|
38717
|
+
for (const match of text2.matchAll(/\b(?:import|require)\s*\(\s*(.?)/g)) {
|
|
38718
|
+
const rest = text2.slice(match.index + match[0].length - match[1].length);
|
|
38719
|
+
if (!/^(['"])node:[A-Za-z0-9_/.-]+\1/.test(rest))
|
|
38720
|
+
return false;
|
|
38721
|
+
}
|
|
38722
|
+
for (const match of text2.matchAll(/\b(?:from|import)\s*(['"])([^'"]*)\1/g))
|
|
38723
|
+
if (!match[2].startsWith("node:"))
|
|
38724
|
+
return false;
|
|
38725
|
+
return true;
|
|
38726
|
+
}
|
|
38727
|
+
function codexRootFreeControls(config2) {
|
|
38728
|
+
const table = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date));
|
|
38729
|
+
const adapted = [];
|
|
38730
|
+
const servers = config2.mcp_servers;
|
|
38731
|
+
if (table(servers) && Object.keys(servers).length <= AGENT_POLICY_LIMITS.discoveryRoots && Object.entries(servers).every(([name, row]) => name !== "codex_apps" && name !== "_codex_apps" && isCodexLocalStdioMcpServer(name, row)))
|
|
38732
|
+
adapted.push("mcp_servers");
|
|
38733
|
+
const agents = config2.agents;
|
|
38734
|
+
if (table(agents) && Object.keys(agents).length <= AGENT_POLICY_LIMITS.fields && Object.values(agents).every((value) => typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)))
|
|
38735
|
+
adapted.push("agents");
|
|
38736
|
+
return adapted;
|
|
38737
|
+
}
|
|
38738
|
+
function codexPluginHookHandlers(value) {
|
|
38739
|
+
const table = (item) => Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
38740
|
+
const identifier5 = (item) => typeof item === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(item);
|
|
38741
|
+
const text2 = (item) => typeof item === "string" && item.length <= AGENT_POLICY_LIMITS.pathCharacters && !item.includes("\x00");
|
|
38742
|
+
if (!table(value) || !Object.keys(value).every((key2) => key2 === "hooks" || key2 === "description") || value.description !== undefined && !text2(value.description) || !table(value.hooks) || Object.keys(value.hooks).length > 32)
|
|
38743
|
+
return null;
|
|
38744
|
+
const result = { commands: 0, servers: new Set };
|
|
38745
|
+
for (const [event, groups] of Object.entries(value.hooks)) {
|
|
38746
|
+
if (!CODEX_HOOK_EVENTS.has(event) || !Array.isArray(groups) || groups.length > 32)
|
|
38747
|
+
return null;
|
|
38748
|
+
for (const group of groups) {
|
|
38749
|
+
if (!table(group) || !Object.keys(group).every((key2) => key2 === "hooks" || key2 === "matcher") || group.matcher !== undefined && !text2(group.matcher) || !Array.isArray(group.hooks) || group.hooks.length > 32)
|
|
38750
|
+
return null;
|
|
38751
|
+
for (const handler of group.hooks) {
|
|
38752
|
+
if (!table(handler) || handler.timeout !== undefined && !(Number.isSafeInteger(handler.timeout) && handler.timeout >= 0) || handler.statusMessage !== undefined && !text2(handler.statusMessage))
|
|
38753
|
+
return null;
|
|
38754
|
+
if (handler.type === "command") {
|
|
38755
|
+
if (!text2(handler.command) || !handler.command || !Object.keys(handler).every((key2) => ["type", "command", "commandWindows", "command_windows", "timeout", "async", "statusMessage", "additionalContextLimit"].includes(key2)))
|
|
38756
|
+
return null;
|
|
38757
|
+
result.commands++;
|
|
38758
|
+
} else if (handler.type === "mcp_tool") {
|
|
38759
|
+
if (!identifier5(handler.server) || !identifier5(handler.tool) || handler.input !== undefined && !table(handler.input) || !Object.keys(handler).every((key2) => ["type", "server", "tool", "input", "timeout", "statusMessage"].includes(key2)))
|
|
38760
|
+
return null;
|
|
38761
|
+
result.servers.add(handler.server);
|
|
38762
|
+
} else
|
|
38763
|
+
return null;
|
|
38764
|
+
}
|
|
38765
|
+
}
|
|
38766
|
+
}
|
|
38767
|
+
return result;
|
|
38768
|
+
}
|
|
38669
38769
|
function resolveDiscovery(options, exclusion) {
|
|
38670
38770
|
const canonical9 = options.canonical ?? resolve23, home = resolve23(options.home), agent = options.agent;
|
|
38671
38771
|
const sources = [], roots = new Set, builtinNames = [];
|
|
38772
|
+
const sumiLocalPluginTexts = new Map;
|
|
38672
38773
|
const budget3 = discoveryByteBudget();
|
|
38673
38774
|
let remainingEntries = AGENT_POLICY_LIMITS.discoveryDirectoryEntries;
|
|
38674
38775
|
const entries = (path) => {
|
|
@@ -38745,12 +38846,38 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38745
38846
|
const controls = agent === "claude" ? claudeDiscoveryControlKeys(configText ?? "{}") : agent === "codex" ? codexDiscoveryControlKeys(config2) : Object.keys(config2).filter((key2) => /skill|plugin|hook|marketplace|extension|instruction/i.test(key2));
|
|
38746
38847
|
const fieldKey = (key2) => /^[A-Za-z_$][A-Za-z0-9_$.-]{0,22}$/.test(key2) && !/(?:sk|rk|pk)_(?:live|test)_|whsec_/i.test(key2) ? JSON.stringify(key2) : "[withheld field key]";
|
|
38747
38848
|
const unsupportedFields = (names, label) => unresolved(`unknown discovery controls have no root-exclusion adapter for ${label}${names.slice(0, 8).map(fieldKey).join(", ")}${names.length > 8 ? ", additional keys withheld" : ""} in ${quotedPath(canonical9(configPath))}`);
|
|
38748
|
-
const
|
|
38849
|
+
const adapted = agent === "codex" ? codexRootFreeControls(config2) : agent === "opencode" && Array.isArray(config2.instructions) && config2.instructions.length === 0 ? ["instructions"] : [];
|
|
38850
|
+
const unsupportedControls = controls.filter((key2) => !supported[agent].includes(key2) && !adapted.includes(key2));
|
|
38749
38851
|
if (unsupportedControls.length)
|
|
38750
38852
|
unsupportedFields(unsupportedControls, "");
|
|
38751
38853
|
if (config2.hooks !== undefined && !object6(config2.hooks))
|
|
38752
38854
|
unresolved("hooks must be an object");
|
|
38753
|
-
const
|
|
38855
|
+
const managedSupervisorOnly = () => {
|
|
38856
|
+
const supervisor = exclusion.managedHook?.supervisor;
|
|
38857
|
+
if (agent !== "hermes" || !supervisor || typeof supervisor.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(supervisor.sha256) || !object6(config2.hooks))
|
|
38858
|
+
return false;
|
|
38859
|
+
let expected;
|
|
38860
|
+
try {
|
|
38861
|
+
expected = hermesHookDefinitions(supervisor);
|
|
38862
|
+
} catch {
|
|
38863
|
+
return false;
|
|
38864
|
+
}
|
|
38865
|
+
for (const [event, entries2] of Object.entries(config2.hooks)) {
|
|
38866
|
+
const want = expected[event];
|
|
38867
|
+
if (!want || !Array.isArray(entries2) || entries2.length !== 1 || !object6(entries2[0]))
|
|
38868
|
+
return false;
|
|
38869
|
+
const entry = entries2[0];
|
|
38870
|
+
if (Object.keys(entry).sort().join("\x00") !== Object.keys(want).sort().join("\x00") || Object.keys(want).some((key2) => entry[key2] !== want[key2]))
|
|
38871
|
+
return false;
|
|
38872
|
+
}
|
|
38873
|
+
try {
|
|
38874
|
+
return hashRawDiscoveryFile(canonical9(supervisor.path), budget3) === supervisor.sha256;
|
|
38875
|
+
} catch {
|
|
38876
|
+
return false;
|
|
38877
|
+
}
|
|
38878
|
+
};
|
|
38879
|
+
const managedBridgeOnly = (agent === "gemini" || agent === "cursor") && exclusion.managedHook !== undefined && hooksAreManagedBridge(agent, config2.hooks, exclusion.managedHook) || managedSupervisorOnly();
|
|
38880
|
+
const hasHooks = controls.includes("hooks") && config2.hooks !== undefined && Object.keys(config2.hooks).length > 0 && !managedBridgeOnly;
|
|
38754
38881
|
let hasPluginConfigs = false, hasFunctionHookEnvironment = false;
|
|
38755
38882
|
const verifyCurrentOpaqueSettings = (label) => {
|
|
38756
38883
|
const retained = exclusion.retained;
|
|
@@ -38855,7 +38982,9 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38855
38982
|
unresolved("malformed Sumi plugins");
|
|
38856
38983
|
}
|
|
38857
38984
|
if (agent === "hermes" && config2.skills !== undefined) {
|
|
38858
|
-
keys2(config2.skills, ["external_dirs"], "Hermes skills");
|
|
38985
|
+
keys2(config2.skills, ["external_dirs", "creation_nudge_interval"], "Hermes skills");
|
|
38986
|
+
if (config2.skills.creation_nudge_interval !== undefined && !(Number.isSafeInteger(config2.skills.creation_nudge_interval) && config2.skills.creation_nudge_interval >= 0))
|
|
38987
|
+
unresolved("malformed Hermes skills creation_nudge_interval");
|
|
38859
38988
|
if (config2.skills.external_dirs !== undefined)
|
|
38860
38989
|
paths(typeof config2.skills.external_dirs === "string" ? [config2.skills.external_dirs] : config2.skills.external_dirs, "Hermes external directories");
|
|
38861
38990
|
}
|
|
@@ -38875,10 +39004,21 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38875
39004
|
unresolved(`malformed Codex ${key2}`);
|
|
38876
39005
|
for (const value of Object.values(config2.plugins ?? {}))
|
|
38877
39006
|
keys2(value, ["enabled"], "Codex plugin registration");
|
|
38878
|
-
for (const value of Object.values(config2.marketplaces ?? {}))
|
|
38879
|
-
keys2(value, ["source_type", "source"], "Codex marketplace registration");
|
|
39007
|
+
for (const value of Object.values(config2.marketplaces ?? {})) {
|
|
39008
|
+
keys2(value, ["source_type", "source", "last_updated"], "Codex marketplace registration");
|
|
39009
|
+
if (value.last_updated !== undefined && (typeof value.last_updated !== "string" || !CODEX_MARKETPLACE_TIMESTAMP.test(value.last_updated)))
|
|
39010
|
+
unresolved("malformed Codex marketplace refresh time");
|
|
39011
|
+
}
|
|
38880
39012
|
if (config2.skills !== undefined)
|
|
38881
|
-
keys2(config2.skills, ["config", "bundled"], "Codex skills");
|
|
39013
|
+
keys2(config2.skills, ["config", "bundled", "native_allowed_paths"], "Codex skills");
|
|
39014
|
+
if (config2.skills?.native_allowed_paths !== undefined) {
|
|
39015
|
+
for (const value of paths(config2.skills.native_allowed_paths, "Codex native allowed skill paths")) {
|
|
39016
|
+
if (!isAbsolute22(value))
|
|
39017
|
+
unresolved("relative Codex native allowed skill path");
|
|
39018
|
+
const path = canonical9(value);
|
|
39019
|
+
roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname24(path) : path);
|
|
39020
|
+
}
|
|
39021
|
+
}
|
|
38882
39022
|
if (config2.skills?.bundled !== undefined) {
|
|
38883
39023
|
keys2(config2.skills.bundled, ["enabled"], "Codex bundled skills");
|
|
38884
39024
|
if (typeof config2.skills.bundled.enabled !== "boolean")
|
|
@@ -38936,7 +39076,9 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38936
39076
|
const target = join33(path, name);
|
|
38937
39077
|
if (!lstatSync25(target).isFile())
|
|
38938
39078
|
unresolved("local plugin packages need a dedicated discovery adapter");
|
|
38939
|
-
witness(target);
|
|
39079
|
+
const text2 = witness(target);
|
|
39080
|
+
if (exclusion && text2 !== null)
|
|
39081
|
+
sumiLocalPluginTexts.set(canonical9(target), text2);
|
|
38940
39082
|
}
|
|
38941
39083
|
}
|
|
38942
39084
|
for (const root of roots) {
|
|
@@ -39070,16 +39212,88 @@ function resolveDiscovery(options, exclusion) {
|
|
|
39070
39212
|
const unique = combined.filter((source, index) => combined.findIndex((candidate) => isDeepStrictEqual6(candidate, source)) === index);
|
|
39071
39213
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
|
|
39072
39214
|
}
|
|
39073
|
-
|
|
39215
|
+
const reviewedManifestAbsence = (root, manifestPath) => {
|
|
39216
|
+
const retained = exclusion?.retained;
|
|
39217
|
+
if (agent !== "claude" || retained?.method !== "reviewed" || ![join33(root, "skills"), root].some((path) => retained.roots.includes(path)))
|
|
39218
|
+
return false;
|
|
39219
|
+
const saved = retained.sources.filter((source) => source.path === canonical9(manifestPath) && source.hashMode === "path-bytes" && source.sha256 !== null && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined);
|
|
39220
|
+
return saved.length > 0 && saved.every((source) => projected(source, undefined, budget3) === source.sha256);
|
|
39221
|
+
};
|
|
39222
|
+
const reviewedInstalledCopy = (root, path, identity4) => {
|
|
39223
|
+
const retained = exclusion?.retained;
|
|
39224
|
+
if (agent !== "codex" || retained?.method !== "reviewed")
|
|
39225
|
+
return false;
|
|
39226
|
+
const inside = relative7(root, canonical9(path));
|
|
39227
|
+
if (!inside || inside === ".." || inside.startsWith(`..${sep11}`) || isAbsolute22(inside))
|
|
39228
|
+
return false;
|
|
39229
|
+
const parent = canonical9(join33(nativeHome, "plugins/cache", identity4.marketplace, identity4.name));
|
|
39230
|
+
const current = hashRawDiscoveryFile(canonical9(path), budget3);
|
|
39231
|
+
if (current === null)
|
|
39232
|
+
return false;
|
|
39233
|
+
return retained.sources.some((source) => {
|
|
39234
|
+
if (source.sha256 !== current || source.format !== undefined || source.fields !== undefined || ![undefined, "bytes"].includes(source.hashMode) || source.managedPlugins !== undefined || source.reviewArtifact !== undefined || !source.path.startsWith(parent + sep11))
|
|
39235
|
+
return false;
|
|
39236
|
+
const [version2, ...rest] = source.path.slice(parent.length + 1).split(sep11);
|
|
39237
|
+
return Boolean(version2) && version2 !== "." && version2 !== ".." && rest.join(sep11) === inside;
|
|
39238
|
+
});
|
|
39239
|
+
};
|
|
39240
|
+
const verifyCodexPluginHookClosure = (root, identity4, marketplaceSource, servers, declarations) => {
|
|
39241
|
+
const retained = exclusion.retained;
|
|
39242
|
+
if (retained.codexSemanticCache || retained.codexInstallationInputs || retained.codexRetiredMaterializations)
|
|
39243
|
+
return verifyOpaqueClosure(declarations);
|
|
39244
|
+
const within = (base, path) => path === base || path.startsWith(base + sep11);
|
|
39245
|
+
const executables = [];
|
|
39246
|
+
for (const server of servers) {
|
|
39247
|
+
const row = config2.mcp_servers?.[server];
|
|
39248
|
+
if (server === "codex_apps" || server === "_codex_apps" || !isCodexLocalStdioMcpServer(server, row))
|
|
39249
|
+
unresolved("plugin hook MCP server is not a configured local stdio server");
|
|
39250
|
+
for (const value of [row.command, ...row.args ?? []])
|
|
39251
|
+
for (const candidate of [value, value.slice(value.indexOf("=") + 1)]) {
|
|
39252
|
+
if (!isAbsolute22(candidate) || /[\0$]/.test(candidate) || executables.length >= AGENT_POLICY_LIMITS.discoveryRoots)
|
|
39253
|
+
continue;
|
|
39254
|
+
const path = canonical9(candidate);
|
|
39255
|
+
if (lstatSync25(path, { throwIfNoEntry: false })?.isFile())
|
|
39256
|
+
executables.push(path);
|
|
39257
|
+
}
|
|
39258
|
+
}
|
|
39259
|
+
const cacheRoot = canonical9(join33(nativeHome, "plugins/cache"));
|
|
39260
|
+
const ownCache = canonical9(join33(nativeHome, "plugins/cache", identity4.marketplace, identity4.name));
|
|
39261
|
+
const ownCatalog = canonical9(join33(marketplaceSource, ".agents/plugins/marketplace.json"));
|
|
39262
|
+
const account = canonical9(home);
|
|
39263
|
+
const marketplaceRoots = Object.values(config2.marketplaces ?? {}).filter((market) => market?.source_type === "local" && typeof market.source === "string" && isAbsolute22(market.source)).map((market) => canonical9(market.source)).filter((path) => !within(path, account));
|
|
39264
|
+
const otherPlugin = (path) => !within(root, path) && !within(ownCache, path) && path !== ownCatalog && !executables.includes(path) && (within(cacheRoot, path) || marketplaceRoots.some((base) => within(base, path)));
|
|
39265
|
+
const sources2 = retained.sources.filter((source) => source.path !== canonical9(configPath) && !otherPlugin(source.path));
|
|
39266
|
+
if (sources2.some((source) => source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.reviewArtifact !== undefined || ![undefined, "bytes", "path-bytes", "executable-v1"].includes(source.hashMode)))
|
|
39267
|
+
return verifyOpaqueClosure(declarations);
|
|
39268
|
+
const declared = declarations.map((path) => relative7(root, path));
|
|
39269
|
+
const declaration = (path) => declarations.includes(path) || path.startsWith(ownCache + sep11) && declared.includes(path.slice(ownCache.length + 1).split(sep11).slice(1).join(sep11));
|
|
39270
|
+
if (!sources2.some((source) => !declaration(source.path) && source.sha256 !== null))
|
|
39271
|
+
unresolved("opaque executable dependency closure is unavailable");
|
|
39272
|
+
for (const source of sources2)
|
|
39273
|
+
if (projected(source, undefined, budget3) !== source.sha256) {
|
|
39274
|
+
throw new NativeDiscoveryWitnessChange("input", source.path, `Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
39275
|
+
}
|
|
39276
|
+
verifyDiscoveryDirectories((retained.directories ?? []).filter((directory) => !otherPlugin(directory.path)));
|
|
39277
|
+
};
|
|
39278
|
+
const readCodexHookDeclaration = (text2, path) => {
|
|
39279
|
+
if (text2 === null)
|
|
39280
|
+
return null;
|
|
39281
|
+
try {
|
|
39282
|
+
return codexPluginHookHandlers(parseConfig(text2, path));
|
|
39283
|
+
} catch {
|
|
39284
|
+
return null;
|
|
39285
|
+
}
|
|
39286
|
+
};
|
|
39287
|
+
function plugin(root, codex) {
|
|
39074
39288
|
root = canonical9(root);
|
|
39075
39289
|
safe6(root);
|
|
39076
39290
|
if (exclusion)
|
|
39077
39291
|
roots.add(root);
|
|
39078
39292
|
const manifestPath = join33(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
39079
39293
|
const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
|
|
39080
|
-
if (raw === null)
|
|
39294
|
+
if (raw === null && !reviewedManifestAbsence(root, manifestPath))
|
|
39081
39295
|
unresolved("plugin manifest missing");
|
|
39082
|
-
const manifest = parseConfig(raw, manifestPath);
|
|
39296
|
+
const manifest = raw === null ? {} : parseConfig(raw, manifestPath);
|
|
39083
39297
|
if (exclusion && Object.keys(manifest).some((key2) => /skill|plugin|hook|marketplace|extension|instruction/i.test(key2) && !["skills", "hooks"].includes(key2)))
|
|
39084
39298
|
unresolved("unknown plugin discovery controls");
|
|
39085
39299
|
const hooks = witness(join33(root, "hooks/hooks.json"));
|
|
@@ -39087,20 +39301,35 @@ function resolveDiscovery(options, exclusion) {
|
|
|
39087
39301
|
if (!exclusion || exclusion.retained?.method !== "reviewed")
|
|
39088
39302
|
unresolved("plugin hooks require a separate no-skill-injection review");
|
|
39089
39303
|
const required2 = [manifestPath, ...hooks !== null ? [join33(root, "hooks/hooks.json")] : []];
|
|
39304
|
+
const scoped = agent === "codex" && codex !== undefined ? [] : undefined;
|
|
39090
39305
|
if (manifest.hooks !== undefined) {
|
|
39091
|
-
if (typeof manifest.hooks
|
|
39092
|
-
|
|
39093
|
-
|
|
39094
|
-
|
|
39095
|
-
|
|
39096
|
-
|
|
39097
|
-
|
|
39306
|
+
if (scoped && manifest.hooks && typeof manifest.hooks === "object" && !Array.isArray(manifest.hooks)) {
|
|
39307
|
+
const inline = codexPluginHookHandlers(manifest.hooks);
|
|
39308
|
+
if (!inline)
|
|
39309
|
+
unresolved("unsupported inline plugin hooks");
|
|
39310
|
+
scoped.push(inline);
|
|
39311
|
+
} else {
|
|
39312
|
+
if (typeof manifest.hooks !== "string")
|
|
39313
|
+
unresolved("unsupported plugin hooks target");
|
|
39314
|
+
const hook = resolve23(root, manifest.hooks);
|
|
39315
|
+
if (!hook.startsWith(root + sep11))
|
|
39316
|
+
unresolved("plugin hooks target escapes its root");
|
|
39317
|
+
required2.push(hook);
|
|
39318
|
+
if (scoped)
|
|
39319
|
+
scoped.push(readCodexHookDeclaration(witness(hook), hook));
|
|
39320
|
+
}
|
|
39321
|
+
}
|
|
39322
|
+
if (scoped && hooks !== null)
|
|
39323
|
+
scoped.push(readCodexHookDeclaration(hooks, join33(root, "hooks/hooks.json")));
|
|
39098
39324
|
for (const path of required2) {
|
|
39099
39325
|
const saved = exclusion.retained.sources.filter((source) => source.path === canonical9(path) && source.sha256 !== null && source.format === undefined && source.fields === undefined);
|
|
39100
|
-
if (
|
|
39326
|
+
if (saved.length ? saved.some((source) => projected(source, undefined, budget3) !== source.sha256) : !(scoped && reviewedInstalledCopy(root, path, codex)))
|
|
39101
39327
|
unresolved("plugin hooks require current independently reviewed sources");
|
|
39102
39328
|
}
|
|
39103
|
-
|
|
39329
|
+
if (scoped && scoped.every((item) => item !== null && item.commands === 0)) {
|
|
39330
|
+
verifyCodexPluginHookClosure(root, codex, codex.source, new Set(scoped.flatMap((item) => [...item.servers])), required2.map((path) => canonical9(path)));
|
|
39331
|
+
} else
|
|
39332
|
+
verifyOpaqueClosure(required2.map((path) => canonical9(path)));
|
|
39104
39333
|
}
|
|
39105
39334
|
const commands = join33(root, "commands");
|
|
39106
39335
|
safe6(commands);
|
|
@@ -39156,7 +39385,7 @@ function resolveDiscovery(options, exclusion) {
|
|
|
39156
39385
|
const catalog = parseConfig(catalogText, join33(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
39157
39386
|
if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
|
|
39158
39387
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
39159
|
-
plugin(resolve23(market.source, matches[0].source.path));
|
|
39388
|
+
plugin(resolve23(market.source, matches[0].source.path), exclusion ? { marketplace, name, source: market.source } : undefined);
|
|
39160
39389
|
}
|
|
39161
39390
|
} else if (agent === "opencode") {
|
|
39162
39391
|
if (witness(join33(home, ".config/opencode/opencode.jsonc")) !== null || witness(join33(home, ".config/opencode/config.json")) !== null)
|
|
@@ -39173,7 +39402,11 @@ function resolveDiscovery(options, exclusion) {
|
|
|
39173
39402
|
if (lstatSync25(localPlugins, { throwIfNoEntry: false }) && entries(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
39174
39403
|
unresolved("additional local plugin hooks require review");
|
|
39175
39404
|
} else if (agent === "sumi") {
|
|
39176
|
-
|
|
39405
|
+
const pinnedLocalPlugin = (source) => {
|
|
39406
|
+
const retained = exclusion?.retained, text2 = sumiLocalPluginTexts.get(source.path);
|
|
39407
|
+
return retained?.method === "reviewed" && text2 !== undefined && sumiPluginLoadsOnlyBuiltins(text2) && retained.sources.some((saved) => saved.path === source.path && saved.sha256 === source.sha256 && saved.sha256 !== null && [undefined, "bytes"].includes(saved.hashMode) && saved.format === undefined && saved.fields === undefined && saved.managedPlugins === undefined && saved.reviewArtifact === undefined);
|
|
39408
|
+
};
|
|
39409
|
+
if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical9(configPath) && source.path !== canonical9(join33(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null && !pinnedLocalPlugin(source)))
|
|
39177
39410
|
unresolved("external or foreign local plugins require review");
|
|
39178
39411
|
} else if (agent === "hermes") {
|
|
39179
39412
|
for (const directory of [join33(home, ".hermes/plugins"), join33(home, ".hermes/hermes-agent")]) {
|
|
@@ -39213,11 +39446,12 @@ var DISCOVERY_RUNTIME_COMMANDS, quotedPath = (path) => JSON.stringify(path).repl
|
|
|
39213
39446
|
} catch {
|
|
39214
39447
|
return null;
|
|
39215
39448
|
}
|
|
39216
|
-
}, digest2 = (text2) => createHash26("sha256").update(text2).digest("hex"), CLAUDE_CONTROL_WITNESS_MODES, CLAUDE_CONTROL_FILES, ADOPTABLE_SETTINGS_MATCHES, CLAUDE_PROJECT_DISCOVERY_KEYS;
|
|
39449
|
+
}, digest2 = (text2) => createHash26("sha256").update(text2).digest("hex"), CLAUDE_CONTROL_WITNESS_MODES, CLAUDE_CONTROL_FILES, ADOPTABLE_SETTINGS_MATCHES, CLAUDE_PROJECT_DISCOVERY_KEYS, CODEX_MARKETPLACE_TIMESTAMP, CODEX_HOOK_EVENTS;
|
|
39217
39450
|
var init_agent_discovery = __esm(() => {
|
|
39218
39451
|
init_sumi_settings_witness();
|
|
39219
39452
|
init_agent_policy_limits();
|
|
39220
39453
|
init_agent_hermes();
|
|
39454
|
+
init_agent_adapters();
|
|
39221
39455
|
init_agent_discovery_directories();
|
|
39222
39456
|
init_agent_discovery_bytes();
|
|
39223
39457
|
init_plugin_projection_store();
|
|
@@ -39247,6 +39481,8 @@ var init_agent_discovery = __esm(() => {
|
|
|
39247
39481
|
CLAUDE_CONTROL_FILES = new Set(["settings.json", "settings.local.json", "installed_plugins.json", "known_marketplaces.json"]);
|
|
39248
39482
|
ADOPTABLE_SETTINGS_MATCHES = Object.freeze(["exact", "screen-reader-receipt"]);
|
|
39249
39483
|
CLAUDE_PROJECT_DISCOVERY_KEYS = Object.freeze(["enabledPlugins", "extraKnownMarketplaces", "additionalMarketplaces", "skillOverrides"]);
|
|
39484
|
+
CODEX_MARKETPLACE_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
39485
|
+
CODEX_HOOK_EVENTS = new Set(["PreToolUse", "PermissionRequest", "PostToolUse", "PreCompact", "PostCompact", "SessionStart", "SessionEnd", "UserPromptSubmit", "SubagentStart", "SubagentStop", "Stop", "Interrupt"]);
|
|
39250
39486
|
});
|
|
39251
39487
|
|
|
39252
39488
|
// src/lib/authoring-path.ts
|
|
@@ -39324,7 +39560,10 @@ function configuredRoots(home, explicitHome) {
|
|
|
39324
39560
|
if (recorded && (!executable || executable.target !== recorded.target || onPath && onPath.target !== recorded.target) || !executable && (binding.builtinNames?.length || binding.agent === "gemini" && binding.sources.some((source) => basename15(source.path) === "package.json"))) {
|
|
39325
39561
|
throw new Error("Native discovery runtime target is unresolved or changed");
|
|
39326
39562
|
}
|
|
39327
|
-
|
|
39563
|
+
const managedCommand = current.commands?.[agent], managedProfile = current.profiles?.[agent];
|
|
39564
|
+
const supervisor = current.supervisors?.[agent];
|
|
39565
|
+
const managedHook = (binding.agent === "gemini" || binding.agent === "cursor") && typeof managedCommand === "string" && typeof managedProfile === "string" ? { command: managedCommand, profile: managedProfile } : binding.agent === "hermes" && typeof managedCommand === "string" && typeof managedProfile === "string" && supervisor && typeof supervisor === "object" && typeof supervisor.path === "string" && typeof supervisor.runtime === "string" && typeof supervisor.sha256 === "string" ? { command: managedCommand, profile: managedProfile, supervisor: { path: supervisor.path, runtime: supervisor.runtime, sha256: supervisor.sha256 } } : undefined;
|
|
39566
|
+
roots.push(...resolveAgentDiscoveryExclusionRoots({ home, agent: binding.agent, canonical: physicalPath, retained: binding, executable, narrowed, ...managedHook ? { managedHook } : {} }));
|
|
39328
39567
|
}
|
|
39329
39568
|
};
|
|
39330
39569
|
if (homePolicy)
|
package/bin/migrate.js
CHANGED
package/bin/server.js
CHANGED
|
@@ -83767,7 +83767,7 @@ restoreLaunchCwd();
|
|
|
83767
83767
|
// package.json
|
|
83768
83768
|
var package_default = {
|
|
83769
83769
|
name: "@hasna/skills",
|
|
83770
|
-
version: "0.10.
|
|
83770
|
+
version: "0.10.92",
|
|
83771
83771
|
description: "Skills library for AI coding agents",
|
|
83772
83772
|
type: "module",
|
|
83773
83773
|
bin: {
|
package/bin/worker.js
CHANGED
|
@@ -76186,7 +76186,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
76186
76186
|
// package.json
|
|
76187
76187
|
var package_default = {
|
|
76188
76188
|
name: "@hasna/skills",
|
|
76189
|
-
version: "0.10.
|
|
76189
|
+
version: "0.10.92",
|
|
76190
76190
|
description: "Skills library for AI coding agents",
|
|
76191
76191
|
type: "module",
|
|
76192
76192
|
bin: {
|