@hasna/skills 0.10.91 → 0.10.93
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 +1051 -725
- package/bin/mcp.js +333 -46
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/cli/commands/portable-skills.d.ts +1 -0
- package/dist/index.js +381 -67
- package/dist/lib/agent-discovery.d.ts +27 -1
- package/dist/lib/authoring-path.d.ts +5 -0
- package/dist/lib/linux-access-acl.d.ts +55 -0
- package/dist/runtime-prerequisites.js +1 -1
- package/dist/sdk/index.js +671 -357
- 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.93",
|
|
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");
|
|
@@ -36387,6 +36403,17 @@ var init_runtime_launcher = __esm(() => {
|
|
|
36387
36403
|
PINNED_LAUNCHER_MAX_BYTES = 16 * 1024;
|
|
36388
36404
|
});
|
|
36389
36405
|
|
|
36406
|
+
// src/lib/linux-access-acl.ts
|
|
36407
|
+
var LINUX_ACL_FREE_WHEN_UNSUPPORTED;
|
|
36408
|
+
var init_linux_access_acl = __esm(() => {
|
|
36409
|
+
LINUX_ACL_FREE_WHEN_UNSUPPORTED = new Set([
|
|
36410
|
+
0xef53n,
|
|
36411
|
+
0x58465342n,
|
|
36412
|
+
0x9123683en,
|
|
36413
|
+
0x01021994n
|
|
36414
|
+
]);
|
|
36415
|
+
});
|
|
36416
|
+
|
|
36390
36417
|
// src/lib/retained-review-artifacts.ts
|
|
36391
36418
|
import { createHash as createHash23 } from "crypto";
|
|
36392
36419
|
import { constants as constants15, closeSync as closeSync17, fstatSync as fstatSync17, fsyncSync as fsyncSync4, lstatSync as lstatSync22, mkdirSync as mkdirSync6, openSync as openSync17, readSync as readSync11, writeSync as writeSync3 } from "fs";
|
|
@@ -36508,6 +36535,7 @@ var init_agent_integration = __esm(() => {
|
|
|
36508
36535
|
init_claude_settings_witness();
|
|
36509
36536
|
init_codex_hook_trust_files();
|
|
36510
36537
|
init_runtime_launcher();
|
|
36538
|
+
init_linux_access_acl();
|
|
36511
36539
|
init_retained_review_artifacts();
|
|
36512
36540
|
});
|
|
36513
36541
|
|
|
@@ -38666,9 +38694,94 @@ function nativeDiscoveryAliasTargets(roots, home) {
|
|
|
38666
38694
|
}
|
|
38667
38695
|
return [...targets];
|
|
38668
38696
|
}
|
|
38697
|
+
function hooksAreManagedBridge(agent, hooks, managed) {
|
|
38698
|
+
const table = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
38699
|
+
const exactKeys3 = (value, keys2) => Object.keys(value).sort().join("\x00") === [...keys2].sort().join("\x00");
|
|
38700
|
+
if (!table(hooks) || typeof managed.command !== "string" || !isAbsolute22(managed.command))
|
|
38701
|
+
return false;
|
|
38702
|
+
const events3 = agent === "gemini" ? ["BeforeAgent", "SessionStart", "BeforeTool"] : ["beforeSubmitPrompt", "sessionStart"];
|
|
38703
|
+
for (const [event, entries] of Object.entries(hooks)) {
|
|
38704
|
+
if (!events3.includes(event) || !Array.isArray(entries) || entries.length !== 1)
|
|
38705
|
+
return false;
|
|
38706
|
+
let expected;
|
|
38707
|
+
try {
|
|
38708
|
+
expected = renderAgentHookCommand(managed.command, agent, managed.profile, event);
|
|
38709
|
+
} catch {
|
|
38710
|
+
return false;
|
|
38711
|
+
}
|
|
38712
|
+
const entry = entries[0];
|
|
38713
|
+
if (!table(entry))
|
|
38714
|
+
return false;
|
|
38715
|
+
if (agent === "cursor") {
|
|
38716
|
+
if (!exactKeys3(entry, ["command", "timeout"]) || entry.timeout !== 15 || entry.command !== expected)
|
|
38717
|
+
return false;
|
|
38718
|
+
continue;
|
|
38719
|
+
}
|
|
38720
|
+
if (!exactKeys3(entry, event === "BeforeTool" ? ["hooks", "matcher"] : ["hooks"]) || event === "BeforeTool" && entry.matcher !== "activate_skill" || !Array.isArray(entry.hooks) || entry.hooks.length !== 1)
|
|
38721
|
+
return false;
|
|
38722
|
+
const hook = entry.hooks[0];
|
|
38723
|
+
if (!table(hook) || !exactKeys3(hook, ["command", "timeout", "type"]) || hook.type !== "command" || hook.timeout !== 15000 || hook.command !== expected)
|
|
38724
|
+
return false;
|
|
38725
|
+
}
|
|
38726
|
+
return true;
|
|
38727
|
+
}
|
|
38728
|
+
function sumiPluginLoadsOnlyBuiltins(text2) {
|
|
38729
|
+
for (const match of text2.matchAll(/\b(?:import|require)\s*\(\s*(.?)/g)) {
|
|
38730
|
+
const rest = text2.slice(match.index + match[0].length - match[1].length);
|
|
38731
|
+
if (!/^(['"])node:[A-Za-z0-9_/.-]+\1/.test(rest))
|
|
38732
|
+
return false;
|
|
38733
|
+
}
|
|
38734
|
+
for (const match of text2.matchAll(/\b(?:from|import)\s*(['"])([^'"]*)\1/g))
|
|
38735
|
+
if (!match[2].startsWith("node:"))
|
|
38736
|
+
return false;
|
|
38737
|
+
return true;
|
|
38738
|
+
}
|
|
38739
|
+
function codexRootFreeControls(config2) {
|
|
38740
|
+
const table = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date));
|
|
38741
|
+
const adapted = [];
|
|
38742
|
+
const servers = config2.mcp_servers;
|
|
38743
|
+
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)))
|
|
38744
|
+
adapted.push("mcp_servers");
|
|
38745
|
+
const agents = config2.agents;
|
|
38746
|
+
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)))
|
|
38747
|
+
adapted.push("agents");
|
|
38748
|
+
return adapted;
|
|
38749
|
+
}
|
|
38750
|
+
function codexPluginHookHandlers(value) {
|
|
38751
|
+
const table = (item) => Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
38752
|
+
const identifier5 = (item) => typeof item === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(item);
|
|
38753
|
+
const text2 = (item) => typeof item === "string" && item.length <= AGENT_POLICY_LIMITS.pathCharacters && !item.includes("\x00");
|
|
38754
|
+
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)
|
|
38755
|
+
return null;
|
|
38756
|
+
const result = { commands: 0, servers: new Set };
|
|
38757
|
+
for (const [event, groups] of Object.entries(value.hooks)) {
|
|
38758
|
+
if (!CODEX_HOOK_EVENTS.has(event) || !Array.isArray(groups) || groups.length > 32)
|
|
38759
|
+
return null;
|
|
38760
|
+
for (const group of groups) {
|
|
38761
|
+
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)
|
|
38762
|
+
return null;
|
|
38763
|
+
for (const handler of group.hooks) {
|
|
38764
|
+
if (!table(handler) || handler.timeout !== undefined && !(Number.isSafeInteger(handler.timeout) && handler.timeout >= 0) || handler.statusMessage !== undefined && !text2(handler.statusMessage))
|
|
38765
|
+
return null;
|
|
38766
|
+
if (handler.type === "command") {
|
|
38767
|
+
if (!text2(handler.command) || !handler.command || !Object.keys(handler).every((key2) => ["type", "command", "commandWindows", "command_windows", "timeout", "async", "statusMessage", "additionalContextLimit"].includes(key2)))
|
|
38768
|
+
return null;
|
|
38769
|
+
result.commands++;
|
|
38770
|
+
} else if (handler.type === "mcp_tool") {
|
|
38771
|
+
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)))
|
|
38772
|
+
return null;
|
|
38773
|
+
result.servers.add(handler.server);
|
|
38774
|
+
} else
|
|
38775
|
+
return null;
|
|
38776
|
+
}
|
|
38777
|
+
}
|
|
38778
|
+
}
|
|
38779
|
+
return result;
|
|
38780
|
+
}
|
|
38669
38781
|
function resolveDiscovery(options, exclusion) {
|
|
38670
38782
|
const canonical9 = options.canonical ?? resolve23, home = resolve23(options.home), agent = options.agent;
|
|
38671
38783
|
const sources = [], roots = new Set, builtinNames = [];
|
|
38784
|
+
const sumiLocalPluginTexts = new Map;
|
|
38672
38785
|
const budget3 = discoveryByteBudget();
|
|
38673
38786
|
let remainingEntries = AGENT_POLICY_LIMITS.discoveryDirectoryEntries;
|
|
38674
38787
|
const entries = (path) => {
|
|
@@ -38705,8 +38818,8 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38705
38818
|
const configPath = exclusion?.nativeHome === undefined ? agentDiscoveryConfigPath(home, agent) : join33(nativeHome, agent === "codex" ? "config.toml" : "settings.json");
|
|
38706
38819
|
const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : agent === "sumi" ? [...SUMI_DISCOVERY_PROJECTION_FIELDS] : ["version"]);
|
|
38707
38820
|
const config2 = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
|
|
38708
|
-
const unresolved = (detail) => {
|
|
38709
|
-
throw new
|
|
38821
|
+
const unresolved = (detail, source) => {
|
|
38822
|
+
throw new NativeDiscoveryUnresolved(agent, detail, source);
|
|
38710
38823
|
};
|
|
38711
38824
|
let opaqueClosureVerified = false;
|
|
38712
38825
|
const verifyOpaqueClosure = (declarations) => {
|
|
@@ -38720,6 +38833,17 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38720
38833
|
verifyDiscovery(retained, undefined, undefined, undefined, exclusion?.narrowed, canonical9(configPath));
|
|
38721
38834
|
opaqueClosureVerified = true;
|
|
38722
38835
|
};
|
|
38836
|
+
const reviewRemedy = (source, check2) => {
|
|
38837
|
+
try {
|
|
38838
|
+
check2();
|
|
38839
|
+
} catch (error61) {
|
|
38840
|
+
if (error61 instanceof NativeDiscoveryUnresolved) {
|
|
38841
|
+
error61.reviewable = true;
|
|
38842
|
+
error61.source ??= source;
|
|
38843
|
+
}
|
|
38844
|
+
throw error61;
|
|
38845
|
+
}
|
|
38846
|
+
};
|
|
38723
38847
|
if (exclusion) {
|
|
38724
38848
|
if (configText !== null && agent !== "codex" && agent !== "hermes")
|
|
38725
38849
|
parseNativeJsonObject(configText);
|
|
@@ -38745,12 +38869,38 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38745
38869
|
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
38870
|
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
38871
|
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
|
|
38872
|
+
const adapted = agent === "codex" ? codexRootFreeControls(config2) : agent === "opencode" && Array.isArray(config2.instructions) && config2.instructions.length === 0 ? ["instructions"] : [];
|
|
38873
|
+
const unsupportedControls = controls.filter((key2) => !supported[agent].includes(key2) && !adapted.includes(key2));
|
|
38749
38874
|
if (unsupportedControls.length)
|
|
38750
38875
|
unsupportedFields(unsupportedControls, "");
|
|
38751
38876
|
if (config2.hooks !== undefined && !object6(config2.hooks))
|
|
38752
38877
|
unresolved("hooks must be an object");
|
|
38753
|
-
const
|
|
38878
|
+
const managedSupervisorOnly = () => {
|
|
38879
|
+
const supervisor = exclusion.managedHook?.supervisor;
|
|
38880
|
+
if (agent !== "hermes" || !supervisor || typeof supervisor.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(supervisor.sha256) || !object6(config2.hooks))
|
|
38881
|
+
return false;
|
|
38882
|
+
let expected;
|
|
38883
|
+
try {
|
|
38884
|
+
expected = hermesHookDefinitions(supervisor);
|
|
38885
|
+
} catch {
|
|
38886
|
+
return false;
|
|
38887
|
+
}
|
|
38888
|
+
for (const [event, entries2] of Object.entries(config2.hooks)) {
|
|
38889
|
+
const want = expected[event];
|
|
38890
|
+
if (!want || !Array.isArray(entries2) || entries2.length !== 1 || !object6(entries2[0]))
|
|
38891
|
+
return false;
|
|
38892
|
+
const entry = entries2[0];
|
|
38893
|
+
if (Object.keys(entry).sort().join("\x00") !== Object.keys(want).sort().join("\x00") || Object.keys(want).some((key2) => entry[key2] !== want[key2]))
|
|
38894
|
+
return false;
|
|
38895
|
+
}
|
|
38896
|
+
try {
|
|
38897
|
+
return hashRawDiscoveryFile(canonical9(supervisor.path), budget3) === supervisor.sha256;
|
|
38898
|
+
} catch {
|
|
38899
|
+
return false;
|
|
38900
|
+
}
|
|
38901
|
+
};
|
|
38902
|
+
const managedBridgeOnly = (agent === "gemini" || agent === "cursor") && exclusion.managedHook !== undefined && hooksAreManagedBridge(agent, config2.hooks, exclusion.managedHook) || managedSupervisorOnly();
|
|
38903
|
+
const hasHooks = controls.includes("hooks") && config2.hooks !== undefined && Object.keys(config2.hooks).length > 0 && !managedBridgeOnly;
|
|
38754
38904
|
let hasPluginConfigs = false, hasFunctionHookEnvironment = false;
|
|
38755
38905
|
const verifyCurrentOpaqueSettings = (label) => {
|
|
38756
38906
|
const retained = exclusion.retained;
|
|
@@ -38765,7 +38915,7 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38765
38915
|
unresolved(`non-enumerable ${label} require a current settings review`);
|
|
38766
38916
|
};
|
|
38767
38917
|
if (hasHooks)
|
|
38768
|
-
verifyCurrentOpaqueSettings("hooks");
|
|
38918
|
+
reviewRemedy(canonical9(configPath), () => verifyCurrentOpaqueSettings("hooks"));
|
|
38769
38919
|
if (agent === "claude") {
|
|
38770
38920
|
if (config2.env !== undefined) {
|
|
38771
38921
|
if (!object6(config2.env) || Object.keys(config2.env).length > 512)
|
|
@@ -38778,7 +38928,7 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38778
38928
|
if (hasFunctionHookEnvironment) {
|
|
38779
38929
|
if (!["0", "1"].includes(config2.env.CLAUDE_CODE_ENABLE_FUNCTION_HOOKS))
|
|
38780
38930
|
unresolved("malformed Claude env.CLAUDE_CODE_ENABLE_FUNCTION_HOOKS flag");
|
|
38781
|
-
verifyCurrentOpaqueSettings("function-hook environment controls");
|
|
38931
|
+
reviewRemedy(canonical9(configPath), () => verifyCurrentOpaqueSettings("function-hook environment controls"));
|
|
38782
38932
|
}
|
|
38783
38933
|
}
|
|
38784
38934
|
if (config2.pluginConfigs !== undefined) {
|
|
@@ -38805,7 +38955,7 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38805
38955
|
}
|
|
38806
38956
|
hasPluginConfigs = Object.keys(config2.pluginConfigs).length > 0;
|
|
38807
38957
|
if (hasPluginConfigs)
|
|
38808
|
-
verifyCurrentOpaqueSettings("plugin configurations");
|
|
38958
|
+
reviewRemedy(canonical9(configPath), () => verifyCurrentOpaqueSettings("plugin configurations"));
|
|
38809
38959
|
}
|
|
38810
38960
|
if (config2.enabledPlugins !== undefined && !object6(config2.enabledPlugins))
|
|
38811
38961
|
unresolved("enabledPlugins must be an object");
|
|
@@ -38855,7 +39005,9 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38855
39005
|
unresolved("malformed Sumi plugins");
|
|
38856
39006
|
}
|
|
38857
39007
|
if (agent === "hermes" && config2.skills !== undefined) {
|
|
38858
|
-
keys2(config2.skills, ["external_dirs"], "Hermes skills");
|
|
39008
|
+
keys2(config2.skills, ["external_dirs", "creation_nudge_interval"], "Hermes skills");
|
|
39009
|
+
if (config2.skills.creation_nudge_interval !== undefined && !(Number.isSafeInteger(config2.skills.creation_nudge_interval) && config2.skills.creation_nudge_interval >= 0))
|
|
39010
|
+
unresolved("malformed Hermes skills creation_nudge_interval");
|
|
38859
39011
|
if (config2.skills.external_dirs !== undefined)
|
|
38860
39012
|
paths(typeof config2.skills.external_dirs === "string" ? [config2.skills.external_dirs] : config2.skills.external_dirs, "Hermes external directories");
|
|
38861
39013
|
}
|
|
@@ -38875,10 +39027,21 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38875
39027
|
unresolved(`malformed Codex ${key2}`);
|
|
38876
39028
|
for (const value of Object.values(config2.plugins ?? {}))
|
|
38877
39029
|
keys2(value, ["enabled"], "Codex plugin registration");
|
|
38878
|
-
for (const value of Object.values(config2.marketplaces ?? {}))
|
|
38879
|
-
keys2(value, ["source_type", "source"], "Codex marketplace registration");
|
|
39030
|
+
for (const value of Object.values(config2.marketplaces ?? {})) {
|
|
39031
|
+
keys2(value, ["source_type", "source", "last_updated"], "Codex marketplace registration");
|
|
39032
|
+
if (value.last_updated !== undefined && (typeof value.last_updated !== "string" || !CODEX_MARKETPLACE_TIMESTAMP.test(value.last_updated)))
|
|
39033
|
+
unresolved("malformed Codex marketplace refresh time");
|
|
39034
|
+
}
|
|
38880
39035
|
if (config2.skills !== undefined)
|
|
38881
|
-
keys2(config2.skills, ["config", "bundled"], "Codex skills");
|
|
39036
|
+
keys2(config2.skills, ["config", "bundled", "native_allowed_paths"], "Codex skills");
|
|
39037
|
+
if (config2.skills?.native_allowed_paths !== undefined) {
|
|
39038
|
+
for (const value of paths(config2.skills.native_allowed_paths, "Codex native allowed skill paths")) {
|
|
39039
|
+
if (!isAbsolute22(value))
|
|
39040
|
+
unresolved("relative Codex native allowed skill path");
|
|
39041
|
+
const path = canonical9(value);
|
|
39042
|
+
roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname24(path) : path);
|
|
39043
|
+
}
|
|
39044
|
+
}
|
|
38882
39045
|
if (config2.skills?.bundled !== undefined) {
|
|
38883
39046
|
keys2(config2.skills.bundled, ["enabled"], "Codex bundled skills");
|
|
38884
39047
|
if (typeof config2.skills.bundled.enabled !== "boolean")
|
|
@@ -38904,7 +39067,7 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38904
39067
|
if (Object.keys(config2.enabledPlugins ?? config2.plugins ?? config2.extensions ?? {}).length > 512)
|
|
38905
39068
|
unresolved("unbounded native registrations");
|
|
38906
39069
|
if (hasHooks || hasPluginConfigs || hasFunctionHookEnvironment)
|
|
38907
|
-
verifyOpaqueClosure([]);
|
|
39070
|
+
reviewRemedy(canonical9(configPath), () => verifyOpaqueClosure([]));
|
|
38908
39071
|
}
|
|
38909
39072
|
if (options.reviewed && (options.reviewed.version !== 1 || !Array.isArray(options.reviewed.agents) || options.reviewed.agents.some((item) => !item || typeof item !== "object") || new Set(options.reviewed.agents.map((item) => item.agent)).size !== options.reviewed.agents.length))
|
|
38910
39073
|
throw new Error("Invalid --discovery-inputs version or agents");
|
|
@@ -38936,7 +39099,9 @@ function resolveDiscovery(options, exclusion) {
|
|
|
38936
39099
|
const target = join33(path, name);
|
|
38937
39100
|
if (!lstatSync25(target).isFile())
|
|
38938
39101
|
unresolved("local plugin packages need a dedicated discovery adapter");
|
|
38939
|
-
witness(target);
|
|
39102
|
+
const text2 = witness(target);
|
|
39103
|
+
if (exclusion && text2 !== null)
|
|
39104
|
+
sumiLocalPluginTexts.set(canonical9(target), text2);
|
|
38940
39105
|
}
|
|
38941
39106
|
}
|
|
38942
39107
|
for (const root of roots) {
|
|
@@ -39070,38 +39235,126 @@ function resolveDiscovery(options, exclusion) {
|
|
|
39070
39235
|
const unique = combined.filter((source, index) => combined.findIndex((candidate) => isDeepStrictEqual6(candidate, source)) === index);
|
|
39071
39236
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
|
|
39072
39237
|
}
|
|
39073
|
-
|
|
39238
|
+
const reviewedManifestAbsence = (root, manifestPath) => {
|
|
39239
|
+
const retained = exclusion?.retained;
|
|
39240
|
+
if (agent !== "claude" || retained?.method !== "reviewed" || ![join33(root, "skills"), root].some((path) => retained.roots.includes(path)))
|
|
39241
|
+
return false;
|
|
39242
|
+
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);
|
|
39243
|
+
return saved.length > 0 && saved.every((source) => projected(source, undefined, budget3) === source.sha256);
|
|
39244
|
+
};
|
|
39245
|
+
const reviewedInstalledCopy = (root, path, identity4) => {
|
|
39246
|
+
const retained = exclusion?.retained;
|
|
39247
|
+
if (agent !== "codex" || retained?.method !== "reviewed")
|
|
39248
|
+
return false;
|
|
39249
|
+
const inside = relative7(root, canonical9(path));
|
|
39250
|
+
if (!inside || inside === ".." || inside.startsWith(`..${sep11}`) || isAbsolute22(inside))
|
|
39251
|
+
return false;
|
|
39252
|
+
const parent = canonical9(join33(nativeHome, "plugins/cache", identity4.marketplace, identity4.name));
|
|
39253
|
+
const current = hashRawDiscoveryFile(canonical9(path), budget3);
|
|
39254
|
+
if (current === null)
|
|
39255
|
+
return false;
|
|
39256
|
+
return retained.sources.some((source) => {
|
|
39257
|
+
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))
|
|
39258
|
+
return false;
|
|
39259
|
+
const [version2, ...rest] = source.path.slice(parent.length + 1).split(sep11);
|
|
39260
|
+
return Boolean(version2) && version2 !== "." && version2 !== ".." && rest.join(sep11) === inside;
|
|
39261
|
+
});
|
|
39262
|
+
};
|
|
39263
|
+
const verifyCodexPluginHookClosure = (root, identity4, marketplaceSource, servers, declarations) => {
|
|
39264
|
+
const retained = exclusion.retained;
|
|
39265
|
+
if (retained.codexSemanticCache || retained.codexInstallationInputs || retained.codexRetiredMaterializations)
|
|
39266
|
+
return verifyOpaqueClosure(declarations);
|
|
39267
|
+
const within = (base, path) => path === base || path.startsWith(base + sep11);
|
|
39268
|
+
const executables = [];
|
|
39269
|
+
for (const server of servers) {
|
|
39270
|
+
const row = config2.mcp_servers?.[server];
|
|
39271
|
+
if (server === "codex_apps" || server === "_codex_apps" || !isCodexLocalStdioMcpServer(server, row))
|
|
39272
|
+
unresolved("plugin hook MCP server is not a configured local stdio server");
|
|
39273
|
+
for (const value of [row.command, ...row.args ?? []])
|
|
39274
|
+
for (const candidate of [value, value.slice(value.indexOf("=") + 1)]) {
|
|
39275
|
+
if (!isAbsolute22(candidate) || /[\0$]/.test(candidate) || executables.length >= AGENT_POLICY_LIMITS.discoveryRoots)
|
|
39276
|
+
continue;
|
|
39277
|
+
const path = canonical9(candidate);
|
|
39278
|
+
if (lstatSync25(path, { throwIfNoEntry: false })?.isFile())
|
|
39279
|
+
executables.push(path);
|
|
39280
|
+
}
|
|
39281
|
+
}
|
|
39282
|
+
const cacheRoot = canonical9(join33(nativeHome, "plugins/cache"));
|
|
39283
|
+
const ownCache = canonical9(join33(nativeHome, "plugins/cache", identity4.marketplace, identity4.name));
|
|
39284
|
+
const ownCatalog = canonical9(join33(marketplaceSource, ".agents/plugins/marketplace.json"));
|
|
39285
|
+
const account = canonical9(home);
|
|
39286
|
+
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));
|
|
39287
|
+
const otherPlugin = (path) => !within(root, path) && !within(ownCache, path) && path !== ownCatalog && !executables.includes(path) && (within(cacheRoot, path) || marketplaceRoots.some((base) => within(base, path)));
|
|
39288
|
+
const sources2 = retained.sources.filter((source) => source.path !== canonical9(configPath) && !otherPlugin(source.path));
|
|
39289
|
+
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)))
|
|
39290
|
+
return verifyOpaqueClosure(declarations);
|
|
39291
|
+
const declared = declarations.map((path) => relative7(root, path));
|
|
39292
|
+
const declaration = (path) => declarations.includes(path) || path.startsWith(ownCache + sep11) && declared.includes(path.slice(ownCache.length + 1).split(sep11).slice(1).join(sep11));
|
|
39293
|
+
if (!sources2.some((source) => !declaration(source.path) && source.sha256 !== null))
|
|
39294
|
+
unresolved("opaque executable dependency closure is unavailable");
|
|
39295
|
+
for (const source of sources2)
|
|
39296
|
+
if (projected(source, undefined, budget3) !== source.sha256) {
|
|
39297
|
+
throw new NativeDiscoveryWitnessChange("input", source.path, `Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
39298
|
+
}
|
|
39299
|
+
verifyDiscoveryDirectories((retained.directories ?? []).filter((directory) => !otherPlugin(directory.path)));
|
|
39300
|
+
};
|
|
39301
|
+
const readCodexHookDeclaration = (text2, path) => {
|
|
39302
|
+
if (text2 === null)
|
|
39303
|
+
return null;
|
|
39304
|
+
try {
|
|
39305
|
+
return codexPluginHookHandlers(parseConfig(text2, path));
|
|
39306
|
+
} catch {
|
|
39307
|
+
return null;
|
|
39308
|
+
}
|
|
39309
|
+
};
|
|
39310
|
+
function plugin(root, codex) {
|
|
39074
39311
|
root = canonical9(root);
|
|
39075
39312
|
safe6(root);
|
|
39076
39313
|
if (exclusion)
|
|
39077
39314
|
roots.add(root);
|
|
39078
39315
|
const manifestPath = join33(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
39079
39316
|
const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
|
|
39080
|
-
if (raw === null)
|
|
39317
|
+
if (raw === null && !reviewedManifestAbsence(root, manifestPath))
|
|
39081
39318
|
unresolved("plugin manifest missing");
|
|
39082
|
-
const manifest = parseConfig(raw, manifestPath);
|
|
39319
|
+
const manifest = raw === null ? {} : parseConfig(raw, manifestPath);
|
|
39083
39320
|
if (exclusion && Object.keys(manifest).some((key2) => /skill|plugin|hook|marketplace|extension|instruction/i.test(key2) && !["skills", "hooks"].includes(key2)))
|
|
39084
39321
|
unresolved("unknown plugin discovery controls");
|
|
39085
39322
|
const hooks = witness(join33(root, "hooks/hooks.json"));
|
|
39086
|
-
if (manifest.hooks !== undefined || hooks !== null)
|
|
39087
|
-
|
|
39088
|
-
|
|
39089
|
-
|
|
39090
|
-
|
|
39091
|
-
|
|
39092
|
-
|
|
39093
|
-
|
|
39094
|
-
|
|
39095
|
-
|
|
39096
|
-
|
|
39097
|
-
|
|
39098
|
-
|
|
39099
|
-
|
|
39100
|
-
|
|
39101
|
-
|
|
39102
|
-
|
|
39103
|
-
|
|
39104
|
-
|
|
39323
|
+
if (manifest.hooks !== undefined || hooks !== null)
|
|
39324
|
+
reviewRemedy(canonical9(hooks !== null ? join33(root, "hooks/hooks.json") : manifestPath), () => {
|
|
39325
|
+
if (!exclusion || exclusion.retained?.method !== "reviewed")
|
|
39326
|
+
unresolved("plugin hooks require a separate no-skill-injection review");
|
|
39327
|
+
const required2 = [manifestPath, ...hooks !== null ? [join33(root, "hooks/hooks.json")] : []];
|
|
39328
|
+
const scoped = agent === "codex" && codex !== undefined ? [] : undefined;
|
|
39329
|
+
if (manifest.hooks !== undefined) {
|
|
39330
|
+
if (scoped && manifest.hooks && typeof manifest.hooks === "object" && !Array.isArray(manifest.hooks)) {
|
|
39331
|
+
const inline = codexPluginHookHandlers(manifest.hooks);
|
|
39332
|
+
if (!inline)
|
|
39333
|
+
unresolved("unsupported inline plugin hooks");
|
|
39334
|
+
scoped.push(inline);
|
|
39335
|
+
} else {
|
|
39336
|
+
if (typeof manifest.hooks !== "string")
|
|
39337
|
+
unresolved("unsupported plugin hooks target");
|
|
39338
|
+
const hook = resolve23(root, manifest.hooks);
|
|
39339
|
+
if (!hook.startsWith(root + sep11))
|
|
39340
|
+
unresolved("plugin hooks target escapes its root");
|
|
39341
|
+
required2.push(hook);
|
|
39342
|
+
if (scoped)
|
|
39343
|
+
scoped.push(readCodexHookDeclaration(witness(hook), hook));
|
|
39344
|
+
}
|
|
39345
|
+
}
|
|
39346
|
+
if (scoped && hooks !== null)
|
|
39347
|
+
scoped.push(readCodexHookDeclaration(hooks, join33(root, "hooks/hooks.json")));
|
|
39348
|
+
for (const path of required2) {
|
|
39349
|
+
const saved = exclusion.retained.sources.filter((source) => source.path === canonical9(path) && source.sha256 !== null && source.format === undefined && source.fields === undefined);
|
|
39350
|
+
if (saved.length ? saved.some((source) => projected(source, undefined, budget3) !== source.sha256) : !(scoped && reviewedInstalledCopy(root, path, codex)))
|
|
39351
|
+
unresolved("plugin hooks require current independently reviewed sources", canonical9(path));
|
|
39352
|
+
}
|
|
39353
|
+
if (scoped && scoped.every((item) => item !== null && item.commands === 0)) {
|
|
39354
|
+
verifyCodexPluginHookClosure(root, codex, codex.source, new Set(scoped.flatMap((item) => [...item.servers])), required2.map((path) => canonical9(path)));
|
|
39355
|
+
} else
|
|
39356
|
+
verifyOpaqueClosure(required2.map((path) => canonical9(path)));
|
|
39357
|
+
});
|
|
39105
39358
|
const commands = join33(root, "commands");
|
|
39106
39359
|
safe6(commands);
|
|
39107
39360
|
if (agent === "claude" && (manifest.commands !== undefined || lstatSync25(commands, { throwIfNoEntry: false })?.isDirectory() && entries(commands).length))
|
|
@@ -39156,7 +39409,7 @@ function resolveDiscovery(options, exclusion) {
|
|
|
39156
39409
|
const catalog = parseConfig(catalogText, join33(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
39157
39410
|
if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
|
|
39158
39411
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
39159
|
-
plugin(resolve23(market.source, matches[0].source.path));
|
|
39412
|
+
plugin(resolve23(market.source, matches[0].source.path), exclusion ? { marketplace, name, source: market.source } : undefined);
|
|
39160
39413
|
}
|
|
39161
39414
|
} else if (agent === "opencode") {
|
|
39162
39415
|
if (witness(join33(home, ".config/opencode/opencode.jsonc")) !== null || witness(join33(home, ".config/opencode/config.json")) !== null)
|
|
@@ -39173,7 +39426,11 @@ function resolveDiscovery(options, exclusion) {
|
|
|
39173
39426
|
if (lstatSync25(localPlugins, { throwIfNoEntry: false }) && entries(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
39174
39427
|
unresolved("additional local plugin hooks require review");
|
|
39175
39428
|
} else if (agent === "sumi") {
|
|
39176
|
-
|
|
39429
|
+
const pinnedLocalPlugin = (source) => {
|
|
39430
|
+
const retained = exclusion?.retained, text2 = sumiLocalPluginTexts.get(source.path);
|
|
39431
|
+
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);
|
|
39432
|
+
};
|
|
39433
|
+
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
39434
|
unresolved("external or foreign local plugins require review");
|
|
39178
39435
|
} else if (agent === "hermes") {
|
|
39179
39436
|
for (const directory of [join33(home, ".hermes/plugins"), join33(home, ".hermes/hermes-agent")]) {
|
|
@@ -39207,17 +39464,18 @@ function resolveDiscovery(options, exclusion) {
|
|
|
39207
39464
|
unresolved("native discovery roots exceed their bound");
|
|
39208
39465
|
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join33(home, ".hermes/plugins"), join33(home, ".hermes/hermes-agent")].map((path) => canonical9(path))) } : {} };
|
|
39209
39466
|
}
|
|
39210
|
-
var DISCOVERY_RUNTIME_COMMANDS, quotedPath = (path) => JSON.stringify(path).replace(/[^\x20-\x7e]/g, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`), realpathOrNull = (path) => {
|
|
39467
|
+
var DISCOVERY_RUNTIME_COMMANDS, NativeDiscoveryUnresolved, quotedPath = (path) => JSON.stringify(path).replace(/[^\x20-\x7e]/g, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`), realpathOrNull = (path) => {
|
|
39211
39468
|
try {
|
|
39212
39469
|
return realpathSync8(path);
|
|
39213
39470
|
} catch {
|
|
39214
39471
|
return null;
|
|
39215
39472
|
}
|
|
39216
|
-
}, digest2 = (text2) => createHash26("sha256").update(text2).digest("hex"), CLAUDE_CONTROL_WITNESS_MODES, CLAUDE_CONTROL_FILES, ADOPTABLE_SETTINGS_MATCHES, CLAUDE_PROJECT_DISCOVERY_KEYS;
|
|
39473
|
+
}, 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
39474
|
var init_agent_discovery = __esm(() => {
|
|
39218
39475
|
init_sumi_settings_witness();
|
|
39219
39476
|
init_agent_policy_limits();
|
|
39220
39477
|
init_agent_hermes();
|
|
39478
|
+
init_agent_adapters();
|
|
39221
39479
|
init_agent_discovery_directories();
|
|
39222
39480
|
init_agent_discovery_bytes();
|
|
39223
39481
|
init_plugin_projection_store();
|
|
@@ -39243,10 +39501,24 @@ var init_agent_discovery = __esm(() => {
|
|
|
39243
39501
|
init_codex_semantic_cache_witness();
|
|
39244
39502
|
init_agent_discovery_directories();
|
|
39245
39503
|
DISCOVERY_RUNTIME_COMMANDS = Object.freeze({ gemini: "gemini" });
|
|
39504
|
+
NativeDiscoveryUnresolved = class NativeDiscoveryUnresolved extends Error {
|
|
39505
|
+
agent;
|
|
39506
|
+
detail;
|
|
39507
|
+
source;
|
|
39508
|
+
reviewable = false;
|
|
39509
|
+
constructor(agent, detail, source) {
|
|
39510
|
+
super(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
|
|
39511
|
+
this.agent = agent;
|
|
39512
|
+
this.detail = detail;
|
|
39513
|
+
this.source = source;
|
|
39514
|
+
}
|
|
39515
|
+
};
|
|
39246
39516
|
CLAUDE_CONTROL_WITNESS_MODES = new Set(["claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-settings-v5", "claude-marketplace-registry", "claude-marketplace-registry-v2", "claude-marketplace-entry-v1", "claude-plugin-registry"]);
|
|
39247
39517
|
CLAUDE_CONTROL_FILES = new Set(["settings.json", "settings.local.json", "installed_plugins.json", "known_marketplaces.json"]);
|
|
39248
39518
|
ADOPTABLE_SETTINGS_MATCHES = Object.freeze(["exact", "screen-reader-receipt"]);
|
|
39249
39519
|
CLAUDE_PROJECT_DISCOVERY_KEYS = Object.freeze(["enabledPlugins", "extraKnownMarketplaces", "additionalMarketplaces", "skillOverrides"]);
|
|
39520
|
+
CODEX_MARKETPLACE_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
39521
|
+
CODEX_HOOK_EVENTS = new Set(["PreToolUse", "PermissionRequest", "PostToolUse", "PreCompact", "PostCompact", "SessionStart", "SessionEnd", "UserPromptSubmit", "SubagentStart", "SubagentStop", "Stop", "Interrupt"]);
|
|
39250
39522
|
});
|
|
39251
39523
|
|
|
39252
39524
|
// src/lib/authoring-path.ts
|
|
@@ -39279,6 +39551,11 @@ function physicalPath(path) {
|
|
|
39279
39551
|
}
|
|
39280
39552
|
return resolve24(realpathSync9(cursor), ...suffix);
|
|
39281
39553
|
}
|
|
39554
|
+
function portableAuthoringDiscoveryRefusal(error61, destination) {
|
|
39555
|
+
const head = `Native discovery is unresolved (${error61.agent}: ${error61.detail}).${error61.source ? ` Checked source: ${error61.source}.` : ""}`;
|
|
39556
|
+
const review = `skills hook install --agent ${error61.agent} --discovery-inputs <reviewed-file> --apply`;
|
|
39557
|
+
return error61.reviewable ? `${head} Portable Skills authoring stays refused: an unreviewed ${error61.agent} hook or plugin option could load skills written to ${destination}. This command takes no --discovery-inputs option; review the current ${error61.agent} configuration with ${review}, then retry.` : `${head} Portable Skills authoring stays refused: Skills cannot list every skill root this ${error61.agent} configuration registers, so it cannot rule out ${destination}. This command takes no --discovery-inputs option; correct that ${error61.agent} configuration entry, then retry. Where a reviewed discovery binding covers it, record one with ${review}.`;
|
|
39558
|
+
}
|
|
39282
39559
|
function contains(root, path) {
|
|
39283
39560
|
const boundary = root.endsWith(sep12) ? root : root + sep12;
|
|
39284
39561
|
return path === root || path.startsWith(boundary);
|
|
@@ -39324,7 +39601,10 @@ function configuredRoots(home, explicitHome) {
|
|
|
39324
39601
|
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
39602
|
throw new Error("Native discovery runtime target is unresolved or changed");
|
|
39326
39603
|
}
|
|
39327
|
-
|
|
39604
|
+
const managedCommand = current.commands?.[agent], managedProfile = current.profiles?.[agent];
|
|
39605
|
+
const supervisor = current.supervisors?.[agent];
|
|
39606
|
+
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;
|
|
39607
|
+
roots.push(...resolveAgentDiscoveryExclusionRoots({ home, agent: binding.agent, canonical: physicalPath, retained: binding, executable, narrowed, ...managedHook ? { managedHook } : {} }));
|
|
39328
39608
|
}
|
|
39329
39609
|
};
|
|
39330
39610
|
if (homePolicy)
|
|
@@ -39376,11 +39656,18 @@ function assertPortableAuthoringPath(path, options = {}) {
|
|
|
39376
39656
|
if (native) {
|
|
39377
39657
|
throw new Error(`Refusing portable Skills authoring below native discovery root '${native}': ${lexical}. Set HASNA_SKILLS_DIR to a private authoring corpus outside native roots.`);
|
|
39378
39658
|
}
|
|
39379
|
-
const roots =
|
|
39380
|
-
|
|
39381
|
-
|
|
39382
|
-
|
|
39383
|
-
|
|
39659
|
+
const roots = [];
|
|
39660
|
+
try {
|
|
39661
|
+
roots.push(...configuredRoots(home, options.homeDir !== undefined));
|
|
39662
|
+
for (const value of selected) {
|
|
39663
|
+
if (physicalPath(value.path) === physicalPath(join34(home, `.${value.agent}`)))
|
|
39664
|
+
continue;
|
|
39665
|
+
roots.push(...resolveAgentDiscoveryExclusionRoots({ home, agent: value.agent, nativeHome: value.path, canonical: physicalPath, executable: null }));
|
|
39666
|
+
}
|
|
39667
|
+
} catch (error61) {
|
|
39668
|
+
if (error61 instanceof NativeDiscoveryUnresolved)
|
|
39669
|
+
throw new Error(portableAuthoringDiscoveryRefusal(error61, lexical));
|
|
39670
|
+
throw error61;
|
|
39384
39671
|
}
|
|
39385
39672
|
for (const root of roots) {
|
|
39386
39673
|
if (candidates.some((candidate) => [resolve24(root), physicalPath(root)].some((nativeRoot) => contains(nativeRoot, candidate) || contains(candidate, nativeRoot)))) {
|
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.93",
|
|
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.93",
|
|
76190
76190
|
description: "Skills library for AI coding agents",
|
|
76191
76191
|
type: "module",
|
|
76192
76192
|
bin: {
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
|
+
export declare const AUTHORING_NATIVE_HOOKS_HELP = "\nNative hooks:\n Authoring refuses while another agent's native hooks, plugin hooks or plugin\n options are not covered by a current discovery review, because they could\n load skills from the authoring corpus. The refusal names the agent and the\n file it checked; review that agent's configuration with\n skills hook install --agent <agent> --discovery-inputs <reviewed-file> --apply\n and retry. Authoring commands themselves take no --discovery-inputs option.\n";
|
|
2
3
|
export declare function registerPortableSkillCommands(parent: Command): void;
|