@hasna/skills 0.10.51 → 0.10.52
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/README.md +78 -0
- package/bin/index.js +1795 -1346
- package/bin/mcp.js +702 -457
- package/bin/migrate.js +1 -1
- package/bin/server.js +11 -4
- package/bin/worker.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1023 -679
- package/dist/lib/agent-discovery.d.ts +37 -1
- package/dist/lib/agent-integration.d.ts +4 -1
- package/dist/lib/claude-marketplace-entry-witness.d.ts +26 -0
- package/dist/lib/claude-settings-witness.d.ts +25 -1
- package/dist/lib/codex-hook-trust-files.d.ts +17 -0
- package/dist/lib/selection-cache.d.ts +2 -2
- package/dist/lib/session-reconciliation.d.ts +9 -0
- package/dist/sdk/index.js +990 -649
- package/docs/plugin-admission.md +185 -0
- package/package.json +1 -1
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.52",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -38339,6 +38339,10 @@ function parse6(text) {
|
|
|
38339
38339
|
need(root.entries.length <= CLAUDE_SETTINGS_WITNESS_LIMITS.rows, "exceeds its settings field limit");
|
|
38340
38340
|
return root;
|
|
38341
38341
|
}
|
|
38342
|
+
function parseNativeJsonObject(text) {
|
|
38343
|
+
need(typeof text === "string" && Buffer.byteLength(text) <= CLAUDE_SETTINGS_WITNESS_LIMITS.bytes, "exceeds its byte limit");
|
|
38344
|
+
return parse6(text);
|
|
38345
|
+
}
|
|
38342
38346
|
function canonical(value) {
|
|
38343
38347
|
if (value.kind === "object")
|
|
38344
38348
|
return { kind: "object", entries: value.entries.map(([key, child]) => [key, canonical(child)]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0) };
|
|
@@ -38561,8 +38565,193 @@ var init_codex_native_compatibility = __esm(() => {
|
|
|
38561
38565
|
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version2) => supportsCodexNativeCapability(version2, "hooks")));
|
|
38562
38566
|
});
|
|
38563
38567
|
|
|
38568
|
+
// src/lib/claude-marketplace-entry-witness.ts
|
|
38569
|
+
import { createHash as createHash3 } from "crypto";
|
|
38570
|
+
import { basename as basename4, dirname as dirname5, isAbsolute as isAbsolute4, resolve as resolve3 } from "path";
|
|
38571
|
+
function need2(value, reason) {
|
|
38572
|
+
if (!value)
|
|
38573
|
+
throw new Error(`Claude marketplace entry witness ${reason}`);
|
|
38574
|
+
}
|
|
38575
|
+
function unknownKey(selector, path, key) {
|
|
38576
|
+
throw new Error(path === null ? `${CLAUDE_MARKETPLACE_ENTRY_HASH_MODE}: unknown top-level key ${quote(bounded(key))} in ${selector.marketplace}` : `${CLAUDE_MARKETPLACE_ENTRY_HASH_MODE}: unknown key ${quote(child(path, key))} in ${selector.marketplace}`);
|
|
38577
|
+
}
|
|
38578
|
+
function knownKeys(object4, allowed, selector, path) {
|
|
38579
|
+
for (const [key] of object4.entries)
|
|
38580
|
+
if (!allowed.has(key))
|
|
38581
|
+
unknownKey(selector, path, key);
|
|
38582
|
+
}
|
|
38583
|
+
function claudeMarketplaceEntrySourceValid(source) {
|
|
38584
|
+
const path = source?.path;
|
|
38585
|
+
return typeof path === "string" && path.length > 0 && path.length <= PATH_CHARACTERS && !/[\x00-\x1f\x7f]/.test(path) && isAbsolute4(path) && resolve3(path) === path && basename4(path) === "marketplace.json" && basename4(dirname5(path)) === ".claude-plugin" && typeof source.marketplace === "string" && NAME.test(source.marketplace) && !source.marketplace.includes("..") && typeof source.plugin === "string" && NAME.test(source.plugin);
|
|
38586
|
+
}
|
|
38587
|
+
function canonical2(value) {
|
|
38588
|
+
if (value.kind === "string")
|
|
38589
|
+
return JSON.stringify(value.value);
|
|
38590
|
+
if (value.kind === "number" || value.kind === "literal")
|
|
38591
|
+
return value.value;
|
|
38592
|
+
if (value.kind === "array")
|
|
38593
|
+
return "[" + value.items.map(canonical2).join(",") + "]";
|
|
38594
|
+
return "{" + [...value.entries].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => JSON.stringify(key) + ":" + canonical2(item)).join(",") + "}";
|
|
38595
|
+
}
|
|
38596
|
+
function validateMarketplace(root, selector) {
|
|
38597
|
+
knownKeys(root, MARKETPLACE_KEYS, selector, null);
|
|
38598
|
+
const name = field(root, "name");
|
|
38599
|
+
need2(isString(name) && name.value === selector.marketplace, "marketplace name does not match the reviewed binding");
|
|
38600
|
+
for (const key of ["$schema", "description", "version"]) {
|
|
38601
|
+
const value = field(root, key);
|
|
38602
|
+
need2(value === undefined || isString(value), `has an invalid marketplace ${key}`);
|
|
38603
|
+
}
|
|
38604
|
+
const owner = field(root, "owner");
|
|
38605
|
+
need2(owner === undefined || owner.kind === "object", "has an invalid marketplace owner");
|
|
38606
|
+
const metadata = field(root, "metadata");
|
|
38607
|
+
if (metadata !== undefined) {
|
|
38608
|
+
need2(metadata.kind === "object", "has an invalid marketplace metadata object");
|
|
38609
|
+
knownKeys(metadata, MARKETPLACE_METADATA_KEYS, selector, "metadata");
|
|
38610
|
+
for (const [key, value] of metadata.entries)
|
|
38611
|
+
need2(isString(value), `has an invalid marketplace metadata.${key}`);
|
|
38612
|
+
}
|
|
38613
|
+
const remove = field(root, "forceRemoveDeletedPlugins");
|
|
38614
|
+
need2(remove === undefined || isBoolean(remove), "has an invalid forceRemoveDeletedPlugins value");
|
|
38615
|
+
const cross = field(root, "allowCrossMarketplaceDependenciesOn");
|
|
38616
|
+
need2(cross === undefined || stringArray(cross), "has an invalid allowCrossMarketplaceDependenciesOn value");
|
|
38617
|
+
const renames = field(root, "renames");
|
|
38618
|
+
if (renames !== undefined) {
|
|
38619
|
+
need2(renames.kind === "object" && renames.entries.every(([, target]) => isString(target) || target.kind === "literal" && target.value === "null"), "has an invalid renames map");
|
|
38620
|
+
need2(!renames.entries.some(([from]) => from.toLowerCase() === selector.plugin.toLowerCase()), "plugin id is redirected by the marketplace renames map");
|
|
38621
|
+
}
|
|
38622
|
+
}
|
|
38623
|
+
function validateSource(source, selector, path) {
|
|
38624
|
+
if (isString(source)) {
|
|
38625
|
+
need2(source.value.length > 0, "has an empty plugin source");
|
|
38626
|
+
return;
|
|
38627
|
+
}
|
|
38628
|
+
need2(source?.kind === "object", "has an invalid plugin source");
|
|
38629
|
+
const type = field(source, "source");
|
|
38630
|
+
need2(isString(type) && Object.hasOwn(SOURCE_KEYS, type.value), "has an unreviewed plugin source type");
|
|
38631
|
+
knownKeys(source, new Set(SOURCE_KEYS[type.value]), selector, path);
|
|
38632
|
+
}
|
|
38633
|
+
function projectEntry(entry, selector) {
|
|
38634
|
+
const path = `plugins[${selector.plugin}]`;
|
|
38635
|
+
knownKeys(entry, { has: (key) => ENTRY_BOUND_KEYS.has(key) || ENTRY_OMITTED_KEYS.has(key) }, selector, path);
|
|
38636
|
+
const name = field(entry, "name");
|
|
38637
|
+
need2(isString(name) && name.value === selector.plugin, "selected entry name does not match");
|
|
38638
|
+
validateSource(field(entry, "source"), selector, `${path}.source`);
|
|
38639
|
+
for (const key of ["strict", "defaultEnabled"]) {
|
|
38640
|
+
const value = field(entry, key);
|
|
38641
|
+
need2(value === undefined || isBoolean(value), `has an invalid entry ${key}`);
|
|
38642
|
+
}
|
|
38643
|
+
const headersHelper = field(entry, "headersHelper");
|
|
38644
|
+
need2(headersHelper === undefined || isString(headersHelper), "has an invalid entry headersHelper");
|
|
38645
|
+
const experimental = field(entry, "experimental");
|
|
38646
|
+
if (experimental !== undefined) {
|
|
38647
|
+
need2(experimental.kind === "object", "has an invalid entry experimental object");
|
|
38648
|
+
knownKeys(experimental, EXPERIMENTAL_KEYS, selector, `${path}.experimental`);
|
|
38649
|
+
}
|
|
38650
|
+
for (const key of ["$schema", "description", "version", "homepage", "license", "category", "displayName"]) {
|
|
38651
|
+
const value = field(entry, key);
|
|
38652
|
+
need2(value === undefined || isString(value), `has an invalid entry ${key}`);
|
|
38653
|
+
}
|
|
38654
|
+
for (const [key, keys] of [["author", new Set(["name", "email", "url"])], ["repository", new Set(["type", "url", "directory"])]]) {
|
|
38655
|
+
const value = field(entry, key);
|
|
38656
|
+
if (value?.kind === "object")
|
|
38657
|
+
knownKeys(value, keys, selector, `${path}.${key}`);
|
|
38658
|
+
need2(value === undefined || isString(value) || stringObject(value), `has an invalid entry ${key}`);
|
|
38659
|
+
}
|
|
38660
|
+
for (const key of ["keywords", "tags"]) {
|
|
38661
|
+
const value = field(entry, key);
|
|
38662
|
+
need2(value === undefined || stringArray(value), `has an invalid entry ${key}`);
|
|
38663
|
+
}
|
|
38664
|
+
const metadata = field(entry, "metadata");
|
|
38665
|
+
need2(metadata === undefined || metadata.kind === "object", "has an invalid entry metadata object");
|
|
38666
|
+
return { kind: "object", entries: entry.entries.filter(([key]) => ENTRY_BOUND_KEYS.has(key)) };
|
|
38667
|
+
}
|
|
38668
|
+
function hashClaudeMarketplaceEntry(text, selector) {
|
|
38669
|
+
need2(selector && typeof selector.marketplace === "string" && NAME.test(selector.marketplace) && !selector.marketplace.includes("..") && typeof selector.plugin === "string" && NAME.test(selector.plugin), "requires an exact marketplace and plugin name");
|
|
38670
|
+
let root;
|
|
38671
|
+
try {
|
|
38672
|
+
root = parseNativeJsonObject(text);
|
|
38673
|
+
} catch (error61) {
|
|
38674
|
+
throw new Error(`Claude marketplace entry witness cannot parse marketplace.json: ${reason(error61)}`);
|
|
38675
|
+
}
|
|
38676
|
+
validateMarketplace(root, selector);
|
|
38677
|
+
const plugins = field(root, "plugins");
|
|
38678
|
+
need2(plugins?.kind === "array", "requires a plugins array");
|
|
38679
|
+
const entryName = (item) => {
|
|
38680
|
+
if (item.kind !== "object")
|
|
38681
|
+
return;
|
|
38682
|
+
const name = field(item, "name");
|
|
38683
|
+
return isString(name) ? name.value : undefined;
|
|
38684
|
+
};
|
|
38685
|
+
const exact = plugins.items.filter((item) => entryName(item) === selector.plugin);
|
|
38686
|
+
const folded = plugins.items.filter((item) => entryName(item)?.toLowerCase() === selector.plugin.toLowerCase());
|
|
38687
|
+
need2(exact.length > 0, "selected plugin entry is missing");
|
|
38688
|
+
need2(exact.length === 1 && folded.length === 1, "selected plugin entry is duplicated or ambiguous");
|
|
38689
|
+
const entry = projectEntry(exact[0], selector);
|
|
38690
|
+
const metadata = field(root, "metadata"), pluginRoot = metadata?.kind === "object" ? field(metadata, "pluginRoot") : undefined;
|
|
38691
|
+
const nullValue = { kind: "literal", value: "null" };
|
|
38692
|
+
const marketplace = { kind: "object", entries: [
|
|
38693
|
+
["name", field(root, "name")],
|
|
38694
|
+
["pluginRoot", pluginRoot ?? nullValue],
|
|
38695
|
+
["allowCrossMarketplaceDependenciesOn", field(root, "allowCrossMarketplaceDependenciesOn") ?? nullValue]
|
|
38696
|
+
] };
|
|
38697
|
+
const projection = { kind: "object", entries: [["marketplace", marketplace], ["plugin", entry]] };
|
|
38698
|
+
return createHash3("sha256").update(DOMAIN).update(canonical2(projection)).digest("hex");
|
|
38699
|
+
}
|
|
38700
|
+
function captureClaudeMarketplaceEntry(path, marketplace, plugin, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
38701
|
+
need2(claudeMarketplaceEntrySourceValid({ path, marketplace, plugin }), "requires a normalized absolute .claude-plugin/marketplace.json path and exact names");
|
|
38702
|
+
let text;
|
|
38703
|
+
try {
|
|
38704
|
+
text = readNativeSettingsWitnessFile(path, budget2, "marketplace.json");
|
|
38705
|
+
} catch (error61) {
|
|
38706
|
+
throw new Error(`Claude marketplace entry witness cannot read marketplace.json: ${reason(error61)}`);
|
|
38707
|
+
}
|
|
38708
|
+
return { path, hashMode: CLAUDE_MARKETPLACE_ENTRY_HASH_MODE, marketplace, plugin, sha256: hashClaudeMarketplaceEntry(text, { marketplace, plugin }) };
|
|
38709
|
+
}
|
|
38710
|
+
var CLAUDE_MARKETPLACE_ENTRY_HASH_MODE = "claude-marketplace-entry-v1", DOMAIN = "hasna.skills.claude-marketplace-entry.v1\x00", PATH_CHARACTERS = 4096, NAME, bounded = (key) => key.length > 64 ? `${key.slice(0, 64)}...` : key, quote = (text) => JSON.stringify(text).replace(/[^\x20-\x7e]/g, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`), child = (path, key) => path + (/^[A-Za-z0-9_$-]{1,64}$/.test(key) ? `.${key}` : `[${JSON.stringify(bounded(key))}]`), reason = (error61) => String(error61?.message ?? error61).replace(/^Claude settings witness /, ""), MARKETPLACE_KEYS, MARKETPLACE_METADATA_KEYS, ENTRY_BOUND_KEYS, ENTRY_OMITTED_KEYS, EXPERIMENTAL_KEYS, SOURCE_KEYS, field = (object4, key) => object4.entries.find(([name]) => name === key)?.[1], isString = (value) => value?.kind === "string", isBoolean = (value) => value?.kind === "literal" && (value.value === "true" || value.value === "false"), stringArray = (value) => value?.kind === "array" && value.items.every(isString), stringObject = (value) => value?.kind === "object" && value.entries.every(([, item]) => isString(item));
|
|
38711
|
+
var init_claude_marketplace_entry_witness = __esm(() => {
|
|
38712
|
+
init_claude_settings_witness();
|
|
38713
|
+
NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
38714
|
+
MARKETPLACE_KEYS = new Set(["$schema", "name", "owner", "plugins", "description", "version", "metadata", "forceRemoveDeletedPlugins", "allowCrossMarketplaceDependenciesOn", "renames"]);
|
|
38715
|
+
MARKETPLACE_METADATA_KEYS = new Set(["description", "version", "pluginRoot"]);
|
|
38716
|
+
ENTRY_BOUND_KEYS = new Set([
|
|
38717
|
+
"name",
|
|
38718
|
+
"source",
|
|
38719
|
+
"strict",
|
|
38720
|
+
"defaultEnabled",
|
|
38721
|
+
"dependencies",
|
|
38722
|
+
"relevance",
|
|
38723
|
+
"headers",
|
|
38724
|
+
"headersHelper",
|
|
38725
|
+
"settings",
|
|
38726
|
+
"userConfig",
|
|
38727
|
+
"types",
|
|
38728
|
+
"channels",
|
|
38729
|
+
"skills",
|
|
38730
|
+
"commands",
|
|
38731
|
+
"agents",
|
|
38732
|
+
"hooks",
|
|
38733
|
+
"mcpServers",
|
|
38734
|
+
"lspServers",
|
|
38735
|
+
"outputStyles",
|
|
38736
|
+
"workflows",
|
|
38737
|
+
"experimental",
|
|
38738
|
+
"themes",
|
|
38739
|
+
"monitors"
|
|
38740
|
+
]);
|
|
38741
|
+
ENTRY_OMITTED_KEYS = new Set(["$schema", "description", "version", "author", "homepage", "repository", "license", "keywords", "category", "tags", "displayName", "metadata"]);
|
|
38742
|
+
EXPERIMENTAL_KEYS = new Set(["themes", "monitors", "evals"]);
|
|
38743
|
+
SOURCE_KEYS = Object.freeze({
|
|
38744
|
+
github: ["source", "repo", "ref", "sha"],
|
|
38745
|
+
url: ["source", "url", "ref", "sha", "path"],
|
|
38746
|
+
"git-subdir": ["source", "url", "path", "ref", "sha"],
|
|
38747
|
+
npm: ["source", "package", "version", "registry"],
|
|
38748
|
+
archive: ["source", "url", "sha256"],
|
|
38749
|
+
command: ["source", "command", "timeout", "mode"]
|
|
38750
|
+
});
|
|
38751
|
+
});
|
|
38752
|
+
|
|
38564
38753
|
// src/lib/agent-policy-limits.ts
|
|
38565
|
-
import { basename as
|
|
38754
|
+
import { basename as basename5, isAbsolute as isAbsolute5, join as join10, resolve as resolve4, sep as sep3 } from "path";
|
|
38566
38755
|
function object4(value) {
|
|
38567
38756
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
38568
38757
|
}
|
|
@@ -38615,7 +38804,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38615
38804
|
text(control.pluginId, 1024);
|
|
38616
38805
|
text(control.namespace, 64);
|
|
38617
38806
|
text(control.pluginParent);
|
|
38618
|
-
requireBound(
|
|
38807
|
+
requireBound(isAbsolute5(control.pluginParent) && resolve4(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
|
|
38619
38808
|
if (control.remotePluginId !== undefined)
|
|
38620
38809
|
requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
|
|
38621
38810
|
if (control.skillsOnly !== undefined)
|
|
@@ -38633,10 +38822,18 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38633
38822
|
text(control.pluginId, 1024);
|
|
38634
38823
|
text(control.namespace, 64);
|
|
38635
38824
|
text(control.pluginParent);
|
|
38636
|
-
requireBound(!ids.has(control.pluginId) &&
|
|
38825
|
+
requireBound(!ids.has(control.pluginId) && isAbsolute5(control.pluginParent) && resolve4(control.pluginParent) === control.pluginParent && ["local", "git", "npm"].includes(control.sourceType) && typeof control.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(control.sourceSha256));
|
|
38637
38826
|
ids.add(control.pluginId);
|
|
38638
38827
|
}
|
|
38639
38828
|
}
|
|
38829
|
+
if (bridge.discoveryExecutables !== undefined)
|
|
38830
|
+
for (const [agent, executable] of Object.entries(record3(bridge.discoveryExecutables, AGENT_POLICY_LIMITS.agents))) {
|
|
38831
|
+
requireBound(agent === "gemini" && object4(executable) && Object.keys(executable).length === 3 && executable.command === "gemini");
|
|
38832
|
+
for (const path of [executable.path, executable.target]) {
|
|
38833
|
+
text(path);
|
|
38834
|
+
requireBound(!/[\x00-\x1f\x7f-\x9f\u200e\u200f\u202a-\u202e\u2066-\u2069]/.test(path) && isAbsolute5(path) && resolve4(path) === path);
|
|
38835
|
+
}
|
|
38836
|
+
}
|
|
38640
38837
|
if (bridge.disabledBuiltins !== undefined)
|
|
38641
38838
|
for (const builtin of array3(bridge.disabledBuiltins, AGENT_POLICY_LIMITS.builtinNames)) {
|
|
38642
38839
|
requireBound(object4(builtin));
|
|
@@ -38662,11 +38859,11 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38662
38859
|
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && Object.keys(proof).every((key) => ["roots", "parents", "directories"].includes(key)) && roots.length + parents2.length > 0 && new Set(roots).size === roots.length && new Set(parents2).size === parents2.length);
|
|
38663
38860
|
for (const root of roots) {
|
|
38664
38861
|
text(root);
|
|
38665
|
-
requireBound(
|
|
38862
|
+
requireBound(isAbsolute5(root) && resolve4(root) === root);
|
|
38666
38863
|
}
|
|
38667
38864
|
for (const parent of parents2) {
|
|
38668
38865
|
text(parent);
|
|
38669
|
-
requireBound(
|
|
38866
|
+
requireBound(isAbsolute5(parent) && resolve4(parent) === parent);
|
|
38670
38867
|
}
|
|
38671
38868
|
for (const directory of array3(proof.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
|
|
38672
38869
|
requireBound(object4(directory));
|
|
@@ -38686,7 +38883,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38686
38883
|
text(input2.namespace, 64);
|
|
38687
38884
|
text(input2.pluginParent);
|
|
38688
38885
|
text(input2.sourceRoot);
|
|
38689
|
-
requireBound(!ids.has(input2.pluginId) && [input2.pluginParent, input2.sourceRoot].every((path) =>
|
|
38886
|
+
requireBound(!ids.has(input2.pluginId) && [input2.pluginParent, input2.sourceRoot].every((path) => isAbsolute5(path) && resolve4(path) === path) && typeof input2.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(input2.sourceSha256));
|
|
38690
38887
|
ids.add(input2.pluginId);
|
|
38691
38888
|
}
|
|
38692
38889
|
if (proof.directories !== undefined)
|
|
@@ -38703,17 +38900,19 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38703
38900
|
text(source.path);
|
|
38704
38901
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
38705
38902
|
if (source.hashMode !== undefined)
|
|
38706
|
-
requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
38903
|
+
requireBound(["bytes", "path-bytes", "claude-plugin-manifest-v1", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-settings-v4", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2", "codex-settings-v3", "codex-settings-v4", "sumi-settings-v1", "claude-marketplace-entry-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
38707
38904
|
if (source.hashMode === "claude-plugin-manifest-v1")
|
|
38708
|
-
requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
38905
|
+
requireBound(agent === "claude" && value.agent === "claude" && ["automatic", "reviewed"].includes(value.method) && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute5(source.path) && resolve4(source.path) === source.path && source.path.endsWith(join10(sep3, ".claude-plugin", "plugin.json")) && source.managedPlugins === undefined);
|
|
38709
38906
|
if (source.hashMode === "sumi-settings-v1")
|
|
38710
|
-
requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
38907
|
+
requireBound(agent === "sumi" && value.agent === "sumi" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute5(source.path) && resolve4(source.path) === source.path && basename5(source.path) === "sumi.json");
|
|
38711
38908
|
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
|
|
38712
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
38909
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute5(source.path) && resolve4(source.path) === source.path && basename5(source.path) === "config.toml");
|
|
38713
38910
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4"))
|
|
38714
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
38911
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute5(source.path) && resolve4(source.path) === source.path && basename5(source.path) === "settings.json");
|
|
38715
38912
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
|
|
38716
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) &&
|
|
38913
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute5(source.path) && resolve4(source.path) === source.path && basename5(source.path) === "known_marketplaces.json");
|
|
38914
|
+
if (source.hashMode === "claude-marketplace-entry-v1")
|
|
38915
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && claudeMarketplaceEntrySourceValid(source));
|
|
38717
38916
|
if (source.hashMode === "claude-plugin-registry") {
|
|
38718
38917
|
requireBound(agent === "claude");
|
|
38719
38918
|
const managed = array3(source.managedPlugins, 64);
|
|
@@ -38728,8 +38927,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38728
38927
|
if (source.format !== undefined)
|
|
38729
38928
|
requireBound(["json", "toml", "yaml"].includes(source.format));
|
|
38730
38929
|
if (source.fields !== undefined)
|
|
38731
|
-
for (const
|
|
38732
|
-
text(
|
|
38930
|
+
for (const field2 of array3(source.fields, AGENT_POLICY_LIMITS.fields))
|
|
38931
|
+
text(field2, 256);
|
|
38733
38932
|
}
|
|
38734
38933
|
if (value.directories !== undefined)
|
|
38735
38934
|
for (const directory of array3(value.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
|
|
@@ -38745,6 +38944,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38745
38944
|
var AGENT_POLICY_LIMITS;
|
|
38746
38945
|
var init_agent_policy_limits = __esm(() => {
|
|
38747
38946
|
init_codex_native_compatibility();
|
|
38947
|
+
init_claude_marketplace_entry_witness();
|
|
38748
38948
|
AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRawSourceBytes: 64 * 1024 * 1024, discoveryRawTotalBytes: 256 * 1024 * 1024, discoveryPathLinks: 40, discoveryPathSteps: 256, discoveryPathSourceMetadataBytes: 64 * 1024, discoveryPathTotalMetadataBytes: 8 * 1024 * 1024, discoveryRoots: 512, discoveryDirectories: 64, discoveryDirectoryEntries: 20000, discoveryDirectoryBytes: 8 * 1024 * 1024, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
|
|
38749
38949
|
});
|
|
38750
38950
|
|
|
@@ -43969,8 +44169,8 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
43969
44169
|
visit2.REMOVE = REMOVE;
|
|
43970
44170
|
visit2.itemAtPath = (cst, path) => {
|
|
43971
44171
|
let item = cst;
|
|
43972
|
-
for (const [
|
|
43973
|
-
const tok = item?.[
|
|
44172
|
+
for (const [field2, index] of path) {
|
|
44173
|
+
const tok = item?.[field2];
|
|
43974
44174
|
if (tok && "items" in tok) {
|
|
43975
44175
|
item = tok.items[index];
|
|
43976
44176
|
} else
|
|
@@ -43980,8 +44180,8 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
43980
44180
|
};
|
|
43981
44181
|
visit2.parentCollection = (cst, path) => {
|
|
43982
44182
|
const parent = visit2.itemAtPath(cst, path.slice(0, -1));
|
|
43983
|
-
const
|
|
43984
|
-
const coll = parent?.[
|
|
44183
|
+
const field2 = path[path.length - 1][0];
|
|
44184
|
+
const coll = parent?.[field2];
|
|
43985
44185
|
if (coll && "items" in coll)
|
|
43986
44186
|
return coll;
|
|
43987
44187
|
throw new Error("Parent collection not found");
|
|
@@ -43990,11 +44190,11 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
43990
44190
|
let ctrl = visitor(item, path);
|
|
43991
44191
|
if (typeof ctrl === "symbol")
|
|
43992
44192
|
return ctrl;
|
|
43993
|
-
for (const
|
|
43994
|
-
const token = item[
|
|
44193
|
+
for (const field2 of ["key", "value"]) {
|
|
44194
|
+
const token = item[field2];
|
|
43995
44195
|
if (token && "items" in token) {
|
|
43996
44196
|
for (let i = 0;i < token.items.length; ++i) {
|
|
43997
|
-
const ci = _visit(Object.freeze(path.concat([[
|
|
44197
|
+
const ci = _visit(Object.freeze(path.concat([[field2, i]])), token.items[i], visitor);
|
|
43998
44198
|
if (typeof ci === "number")
|
|
43999
44199
|
i = ci - 1;
|
|
44000
44200
|
else if (ci === BREAK)
|
|
@@ -44004,7 +44204,7 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
44004
44204
|
i -= 1;
|
|
44005
44205
|
}
|
|
44006
44206
|
}
|
|
44007
|
-
if (typeof ctrl === "function" &&
|
|
44207
|
+
if (typeof ctrl === "function" && field2 === "key")
|
|
44008
44208
|
ctrl = ctrl(item, path);
|
|
44009
44209
|
}
|
|
44010
44210
|
}
|
|
@@ -44430,9 +44630,9 @@ var require_lexer = __commonJS((exports) => {
|
|
|
44430
44630
|
}
|
|
44431
44631
|
}
|
|
44432
44632
|
*parseQuotedScalar() {
|
|
44433
|
-
const
|
|
44434
|
-
let end = this.buffer.indexOf(
|
|
44435
|
-
if (
|
|
44633
|
+
const quote2 = this.charAt(0);
|
|
44634
|
+
let end = this.buffer.indexOf(quote2, this.pos + 1);
|
|
44635
|
+
if (quote2 === "'") {
|
|
44436
44636
|
while (end !== -1 && this.buffer[end + 1] === "'")
|
|
44437
44637
|
end = this.buffer.indexOf("'", end + 2);
|
|
44438
44638
|
} else {
|
|
@@ -45739,7 +45939,7 @@ var init_dist = __esm(() => {
|
|
|
45739
45939
|
});
|
|
45740
45940
|
|
|
45741
45941
|
// src/lib/agent-hermes.ts
|
|
45742
|
-
import { dirname as
|
|
45942
|
+
import { dirname as dirname6, isAbsolute as isAbsolute6, join as join11, resolve as resolve5 } from "path";
|
|
45743
45943
|
function object5(value) {
|
|
45744
45944
|
return Boolean(value && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null));
|
|
45745
45945
|
}
|
|
@@ -45773,7 +45973,7 @@ function assertHermesEnvironment(home) {
|
|
|
45773
45973
|
throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
|
|
45774
45974
|
}
|
|
45775
45975
|
const selected = process.env.HERMES_HOME?.trim();
|
|
45776
|
-
if (selected && (!
|
|
45976
|
+
if (selected && (!isAbsolute6(selected) || resolve5(selected) !== join11(resolve5(home), ".hermes")))
|
|
45777
45977
|
throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
|
|
45778
45978
|
if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
|
|
45779
45979
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
|
|
@@ -45783,18 +45983,18 @@ var init_agent_hermes = __esm(() => {
|
|
|
45783
45983
|
});
|
|
45784
45984
|
|
|
45785
45985
|
// src/lib/agent-discovery-directories.ts
|
|
45786
|
-
import { createHash as
|
|
45986
|
+
import { createHash as createHash4 } from "crypto";
|
|
45787
45987
|
import { lstatSync as lstatSync6, opendirSync } from "fs";
|
|
45788
|
-
import { dirname as
|
|
45789
|
-
function
|
|
45988
|
+
import { dirname as dirname7, isAbsolute as isAbsolute7, join as join12, resolve as resolve6 } from "path";
|
|
45989
|
+
function need3(value, message) {
|
|
45790
45990
|
if (!value)
|
|
45791
45991
|
throw new Error(message);
|
|
45792
45992
|
}
|
|
45793
45993
|
function safe(path) {
|
|
45794
|
-
|
|
45795
|
-
for (let cursor = path;; cursor =
|
|
45796
|
-
|
|
45797
|
-
if (
|
|
45994
|
+
need3(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute7(path) && resolve6(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
|
|
45995
|
+
for (let cursor = path;; cursor = dirname7(cursor)) {
|
|
45996
|
+
need3(!lstatSync6(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
|
|
45997
|
+
if (dirname7(cursor) === cursor)
|
|
45798
45998
|
break;
|
|
45799
45999
|
}
|
|
45800
46000
|
}
|
|
@@ -45808,45 +46008,45 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
|
|
|
45808
46008
|
const root = lstatSync6(path, { throwIfNoEntry: false });
|
|
45809
46009
|
if (!root)
|
|
45810
46010
|
return { path, sha256: null };
|
|
45811
|
-
|
|
45812
|
-
const hash2 =
|
|
46011
|
+
need3(root.isDirectory(), "Unsupported native discovery directory input");
|
|
46012
|
+
const hash2 = createHash4("sha256");
|
|
45813
46013
|
function walk(current, relative3, before, depth) {
|
|
45814
|
-
|
|
46014
|
+
need3(depth <= 64, "Native discovery directory depth limit exceeded");
|
|
45815
46015
|
const names = [], directory = opendirSync(current);
|
|
45816
46016
|
try {
|
|
45817
46017
|
for (let entry = directory.readSync();entry; entry = directory.readSync()) {
|
|
45818
|
-
|
|
46018
|
+
need3(++budget2.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
|
|
45819
46019
|
names.push(entry.name);
|
|
45820
46020
|
}
|
|
45821
46021
|
} finally {
|
|
45822
46022
|
directory.closeSync();
|
|
45823
46023
|
}
|
|
45824
|
-
|
|
46024
|
+
need3(new Set(names).size === names.length, "Ambiguous native discovery directory names");
|
|
45825
46025
|
for (const name of names.sort()) {
|
|
45826
|
-
const
|
|
45827
|
-
if (omittedRoots.includes(
|
|
46026
|
+
const child2 = join12(current, name), childRelative = relative3 ? `${relative3}/${name}` : name;
|
|
46027
|
+
if (omittedRoots.includes(child2))
|
|
45828
46028
|
continue;
|
|
45829
|
-
|
|
45830
|
-
const stat = lstatSync6(
|
|
45831
|
-
|
|
46029
|
+
need3(child2.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
|
|
46030
|
+
const stat = lstatSync6(child2);
|
|
46031
|
+
need3(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
|
|
45832
46032
|
const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
|
|
45833
46033
|
`;
|
|
45834
46034
|
budget2.bytes += Buffer.byteLength(row);
|
|
45835
|
-
|
|
46035
|
+
need3(budget2.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
|
|
45836
46036
|
hash2.update(row);
|
|
45837
46037
|
rows?.push(row);
|
|
45838
|
-
if (stat.isDirectory() && !excludedRoots.includes(
|
|
45839
|
-
walk(
|
|
46038
|
+
if (stat.isDirectory() && !excludedRoots.includes(child2))
|
|
46039
|
+
walk(child2, childRelative, stat, depth + 1);
|
|
45840
46040
|
}
|
|
45841
|
-
|
|
46041
|
+
need3(same(before, lstatSync6(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
|
|
45842
46042
|
}
|
|
45843
46043
|
walk(path, "", root, 0);
|
|
45844
46044
|
safe(path);
|
|
45845
46045
|
return { path, sha256: hash2.digest("hex") };
|
|
45846
46046
|
}
|
|
45847
46047
|
function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
|
|
45848
|
-
|
|
45849
|
-
|
|
46048
|
+
need3(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid projected discovery directory collection");
|
|
46049
|
+
need3(omittedRoots.length <= AGENT_POLICY_LIMITS.discoveryRoots && new Set(omittedRoots).size === omittedRoots.length, "Invalid inactive discovery roots");
|
|
45850
46050
|
for (const root of omittedRoots)
|
|
45851
46051
|
safe(root);
|
|
45852
46052
|
const budget2 = { entries: 0, bytes: 0 };
|
|
@@ -45856,65 +46056,65 @@ function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
|
|
|
45856
46056
|
});
|
|
45857
46057
|
}
|
|
45858
46058
|
function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
|
|
45859
|
-
|
|
46059
|
+
need3(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
|
|
45860
46060
|
let count = 0, bytes = 0;
|
|
45861
46061
|
const expected = directories.map((directory) => {
|
|
45862
46062
|
safe(directory.path);
|
|
45863
|
-
|
|
45864
|
-
const hash2 =
|
|
46063
|
+
need3(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
|
|
46064
|
+
const hash2 = createHash4("sha256");
|
|
45865
46065
|
const kept = [];
|
|
45866
46066
|
for (const row of directory.entries) {
|
|
45867
|
-
|
|
46067
|
+
need3(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
|
|
45868
46068
|
bytes += Buffer.byteLength(row);
|
|
45869
|
-
|
|
46069
|
+
need3(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
|
|
45870
46070
|
const value = JSON.parse(row);
|
|
45871
|
-
|
|
46071
|
+
need3(Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && value[0] && !isAbsolute7(value[0]) && !value[0].split("/").some((part) => !part || part === "." || part === "..") && ["file", "directory"].includes(value[1]) && row === JSON.stringify(value) + `
|
|
45872
46072
|
`, "Invalid reviewed directory member");
|
|
45873
46073
|
hash2.update(row);
|
|
45874
46074
|
const path = join12(directory.path, value[0]);
|
|
45875
46075
|
if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
|
|
45876
46076
|
kept.push(row);
|
|
45877
46077
|
}
|
|
45878
|
-
|
|
46078
|
+
need3(directory.sha256 === null ? directory.entries.length === 0 : hash2.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
|
|
45879
46079
|
const absent = omittedRoots.some((root) => directory.path === root || directory.path.startsWith(root + "/"));
|
|
45880
|
-
return { path: directory.path, sha256: absent || directory.sha256 === null ? null :
|
|
46080
|
+
return { path: directory.path, sha256: absent || directory.sha256 === null ? null : createHash4("sha256").update(kept.join("")).digest("hex") };
|
|
45881
46081
|
});
|
|
45882
46082
|
const current = captureDiscoveryDirectoryProjection(directories.map((item) => item.path), omittedRoots);
|
|
45883
|
-
|
|
46083
|
+
need3(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
|
|
45884
46084
|
}
|
|
45885
46085
|
function captureDiscoveryDirectories(paths, excludedRoots = []) {
|
|
45886
|
-
|
|
46086
|
+
need3(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
|
|
45887
46087
|
const budget2 = { entries: 0, bytes: 0 };
|
|
45888
46088
|
for (const root of excludedRoots)
|
|
45889
46089
|
safe(root);
|
|
45890
46090
|
return paths.map((path) => capture(path, budget2, excludedRoots));
|
|
45891
46091
|
}
|
|
45892
46092
|
function verifyDiscoveryDirectories(directories, excludedRoots = []) {
|
|
45893
|
-
|
|
46093
|
+
need3(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
|
|
45894
46094
|
for (const directory of directories)
|
|
45895
|
-
|
|
46095
|
+
need3(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
|
|
45896
46096
|
const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
|
|
45897
46097
|
for (let i = 0;i < directories.length; i++)
|
|
45898
|
-
|
|
46098
|
+
need3(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
|
|
45899
46099
|
}
|
|
45900
46100
|
var init_agent_discovery_directories = __esm(() => {
|
|
45901
46101
|
init_agent_policy_limits();
|
|
45902
46102
|
});
|
|
45903
46103
|
|
|
45904
46104
|
// src/lib/agent-discovery-bytes.ts
|
|
45905
|
-
import { createHash as
|
|
46105
|
+
import { createHash as createHash5 } from "crypto";
|
|
45906
46106
|
import { closeSync as closeSync6, constants as constants3, fstatSync as fstatSync6, lstatSync as lstatSync7, openSync as openSync6, readSync as readSync3 } from "fs";
|
|
45907
|
-
import { dirname as
|
|
46107
|
+
import { dirname as dirname8, isAbsolute as isAbsolute8, resolve as resolve7 } from "path";
|
|
45908
46108
|
function discoveryByteBudget() {
|
|
45909
46109
|
return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
|
|
45910
46110
|
}
|
|
45911
46111
|
function safe2(path) {
|
|
45912
|
-
if (typeof path !== "string" || !
|
|
46112
|
+
if (typeof path !== "string" || !isAbsolute8(path) || path !== resolve7(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
|
|
45913
46113
|
throw new Error("Expected a canonical absolute raw discovery path");
|
|
45914
|
-
for (let cursor = path;; cursor =
|
|
46114
|
+
for (let cursor = path;; cursor = dirname8(cursor)) {
|
|
45915
46115
|
if (lstatSync7(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
45916
46116
|
throw new Error("Refusing symlink raw discovery input");
|
|
45917
|
-
if (
|
|
46117
|
+
if (dirname8(cursor) === cursor)
|
|
45918
46118
|
break;
|
|
45919
46119
|
}
|
|
45920
46120
|
}
|
|
@@ -45933,7 +46133,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
|
|
|
45933
46133
|
if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
|
|
45934
46134
|
throw new Error("Raw discovery file byte limit exceeded");
|
|
45935
46135
|
consume(budget2, bytes);
|
|
45936
|
-
return
|
|
46136
|
+
return createHash5("sha256").update(text2).digest("hex");
|
|
45937
46137
|
}
|
|
45938
46138
|
const initial = lstatSync7(path, { throwIfNoEntry: false });
|
|
45939
46139
|
if (!initial)
|
|
@@ -45947,7 +46147,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
|
|
|
45947
46147
|
const opened = fstatSync6(fd);
|
|
45948
46148
|
if (!opened.isFile() || !same2(initial, opened))
|
|
45949
46149
|
throw new Error("Raw discovery input changed during open");
|
|
45950
|
-
const hash2 =
|
|
46150
|
+
const hash2 = createHash5("sha256"), buffer = Buffer.alloc(64 * 1024);
|
|
45951
46151
|
let bytes = 0;
|
|
45952
46152
|
while (true) {
|
|
45953
46153
|
const count = readSync3(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
|
|
@@ -45973,9 +46173,9 @@ var init_agent_discovery_bytes = __esm(() => {
|
|
|
45973
46173
|
});
|
|
45974
46174
|
|
|
45975
46175
|
// src/lib/agent-discovery-path-bytes.ts
|
|
45976
|
-
import { createHash as
|
|
46176
|
+
import { createHash as createHash6 } from "crypto";
|
|
45977
46177
|
import { lstatSync as lstatSync8, readlinkSync } from "fs";
|
|
45978
|
-
import { dirname as
|
|
46178
|
+
import { dirname as dirname9, isAbsolute as isAbsolute9, join as join13, parse as parse7, resolve as resolve8, sep as sep4 } from "path";
|
|
45979
46179
|
function identity2(stat, mutable = false) {
|
|
45980
46180
|
return {
|
|
45981
46181
|
dev: String(stat.dev),
|
|
@@ -45986,12 +46186,12 @@ function identity2(stat, mutable = false) {
|
|
|
45986
46186
|
...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
|
|
45987
46187
|
};
|
|
45988
46188
|
}
|
|
45989
|
-
function
|
|
45990
|
-
if (typeof path !== "string" || !
|
|
46189
|
+
function canonical3(path) {
|
|
46190
|
+
if (typeof path !== "string" || !isAbsolute9(path) || path !== resolve8(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
|
|
45991
46191
|
throw new Error("Expected a canonical absolute discovery path");
|
|
45992
46192
|
}
|
|
45993
46193
|
function trace(path) {
|
|
45994
|
-
|
|
46194
|
+
canonical3(path);
|
|
45995
46195
|
const rows = [], paths = [];
|
|
45996
46196
|
let metadataBytes = 0, steps = 0, links = 0, cursor = parse7(path).root, pending = path.slice(cursor.length).split(sep4);
|
|
45997
46197
|
function record4(path2, row) {
|
|
@@ -46016,7 +46216,7 @@ function trace(path) {
|
|
|
46016
46216
|
if (!component || component === ".")
|
|
46017
46217
|
continue;
|
|
46018
46218
|
if (component === "..") {
|
|
46019
|
-
cursor =
|
|
46219
|
+
cursor = dirname9(cursor);
|
|
46020
46220
|
continue;
|
|
46021
46221
|
}
|
|
46022
46222
|
const candidate = join13(cursor, component);
|
|
@@ -46036,11 +46236,11 @@ function trace(path) {
|
|
|
46036
46236
|
if (!target || target.includes("\x00") || Buffer.byteLength(target) > AGENT_POLICY_LIMITS.pathCharacters || !after.isSymbolicLink() || JSON.stringify(identity2(stat, true)) !== JSON.stringify(identity2(after, true)))
|
|
46037
46237
|
throw new Error("Discovery link changed during read");
|
|
46038
46238
|
record4(candidate, { type: "link", target, ...identity2(stat, true) });
|
|
46039
|
-
if (
|
|
46239
|
+
if (isAbsolute9(target)) {
|
|
46040
46240
|
cursor = parse7(target).root;
|
|
46041
46241
|
root();
|
|
46042
46242
|
}
|
|
46043
|
-
const remainder =
|
|
46243
|
+
const remainder = isAbsolute9(target) ? target.slice(parse7(target).root.length) : target;
|
|
46044
46244
|
pending = [...remainder.split(sep4), ...pending];
|
|
46045
46245
|
if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
|
|
46046
46246
|
throw new Error("Discovery path step limit exceeded");
|
|
@@ -46083,7 +46283,7 @@ function hashDiscoveryPathFile(path, budget2, changes) {
|
|
|
46083
46283
|
const after = trace(path);
|
|
46084
46284
|
if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
|
|
46085
46285
|
throw new Error("Discovery path input changed during read");
|
|
46086
|
-
return
|
|
46286
|
+
return createHash6("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
|
|
46087
46287
|
}
|
|
46088
46288
|
var init_agent_discovery_path_bytes = __esm(() => {
|
|
46089
46289
|
init_agent_policy_limits();
|
|
@@ -46091,10 +46291,10 @@ var init_agent_discovery_path_bytes = __esm(() => {
|
|
|
46091
46291
|
});
|
|
46092
46292
|
|
|
46093
46293
|
// src/lib/claude-plugin-manifest-witness.ts
|
|
46094
|
-
import { createHash as
|
|
46095
|
-
function requireValue(value,
|
|
46294
|
+
import { createHash as createHash7 } from "crypto";
|
|
46295
|
+
function requireValue(value, reason2) {
|
|
46096
46296
|
if (!value)
|
|
46097
|
-
throw new Error("Claude plugin manifest " +
|
|
46297
|
+
throw new Error("Claude plugin manifest " + reason2);
|
|
46098
46298
|
}
|
|
46099
46299
|
function parse8(text2) {
|
|
46100
46300
|
requireValue(Buffer.byteLength(text2, "utf8") <= CLAUDE_PLUGIN_MANIFEST_LIMITS.bytes, "exceeds its byte limit");
|
|
@@ -46170,7 +46370,7 @@ function parse8(text2) {
|
|
|
46170
46370
|
requireValue(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
|
|
46171
46371
|
return root;
|
|
46172
46372
|
}
|
|
46173
|
-
function
|
|
46373
|
+
function canonical4(value) {
|
|
46174
46374
|
if (value.kind === "string")
|
|
46175
46375
|
return JSON.stringify(value.value);
|
|
46176
46376
|
if (value.kind === "number")
|
|
@@ -46178,18 +46378,18 @@ function canonical3(value) {
|
|
|
46178
46378
|
if (value.kind === "literal")
|
|
46179
46379
|
return value.value;
|
|
46180
46380
|
if (value.kind === "array")
|
|
46181
|
-
return "[" + value.items.map(
|
|
46182
|
-
return "{" + value.entries.map(([key, item]) => JSON.stringify(key) + ":" +
|
|
46381
|
+
return "[" + value.items.map(canonical4).join(",") + "]";
|
|
46382
|
+
return "{" + value.entries.map(([key, item]) => JSON.stringify(key) + ":" + canonical4(item)).join(",") + "}";
|
|
46183
46383
|
}
|
|
46184
|
-
function validateText(value,
|
|
46185
|
-
requireValue(value?.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "has an invalid " +
|
|
46384
|
+
function validateText(value, field2) {
|
|
46385
|
+
requireValue(value?.kind === "string" && value.value.length <= CLAUDE_PLUGIN_MANIFEST_LIMITS.stringCharacters, "has an invalid " + field2 + " field");
|
|
46186
46386
|
}
|
|
46187
46387
|
function validateDescriptiveFields(manifest) {
|
|
46188
46388
|
const values = new Map(manifest.entries);
|
|
46189
|
-
for (const
|
|
46190
|
-
const value = values.get(
|
|
46389
|
+
for (const field2 of ["description", "version", "homepage", "license"]) {
|
|
46390
|
+
const value = values.get(field2);
|
|
46191
46391
|
if (value !== undefined)
|
|
46192
|
-
validateText(value,
|
|
46392
|
+
validateText(value, field2);
|
|
46193
46393
|
}
|
|
46194
46394
|
const author = values.get("author");
|
|
46195
46395
|
if (author !== undefined) {
|
|
@@ -46214,10 +46414,10 @@ function hashClaudePluginManifest(text2) {
|
|
|
46214
46414
|
const manifest = parse8(text2);
|
|
46215
46415
|
validateDescriptiveFields(manifest);
|
|
46216
46416
|
const discovery = { kind: "object", entries: manifest.entries.filter(([key]) => !DESCRIPTIVE_FIELDS.has(key)) };
|
|
46217
|
-
return
|
|
46417
|
+
return createHash7("sha256").update(canonical4(discovery)).digest("hex");
|
|
46218
46418
|
}
|
|
46219
46419
|
function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
|
|
46220
|
-
if (!/^[a-f0-9]{64}$/.test(reviewedSha256) ||
|
|
46420
|
+
if (!/^[a-f0-9]{64}$/.test(reviewedSha256) || createHash7("sha256").update(text2).digest("hex") !== reviewedSha256) {
|
|
46221
46421
|
throw new Error("Reviewed Claude plugin manifest changed before semantic projection");
|
|
46222
46422
|
}
|
|
46223
46423
|
return hashClaudePluginManifest(text2);
|
|
@@ -46229,7 +46429,7 @@ var init_claude_plugin_manifest_witness = __esm(() => {
|
|
|
46229
46429
|
});
|
|
46230
46430
|
|
|
46231
46431
|
// src/lib/skill-bundle.ts
|
|
46232
|
-
import { createHash as
|
|
46432
|
+
import { createHash as createHash8 } from "crypto";
|
|
46233
46433
|
import { readFileSync as readFileSync9, readdirSync as readdirSync4, statSync as statSync6 } from "fs";
|
|
46234
46434
|
import { join as join14, relative as relative3 } from "path";
|
|
46235
46435
|
import { createGunzip } from "zlib";
|
|
@@ -46261,7 +46461,7 @@ function ownBytes(view) {
|
|
|
46261
46461
|
return out;
|
|
46262
46462
|
}
|
|
46263
46463
|
function sha256Hex(bytes) {
|
|
46264
|
-
return
|
|
46464
|
+
return createHash8("sha256").update(bytes).digest("hex");
|
|
46265
46465
|
}
|
|
46266
46466
|
function collectSkillBundleEntries(dir) {
|
|
46267
46467
|
const entries = [];
|
|
@@ -46389,12 +46589,12 @@ function inspectionLimits(options) {
|
|
|
46389
46589
|
for (const key of Object.keys(options.limits ?? {})) {
|
|
46390
46590
|
if (!Object.hasOwn(limits, key))
|
|
46391
46591
|
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Unknown bundle limit");
|
|
46392
|
-
const
|
|
46393
|
-
const value = options.limits[
|
|
46394
|
-
if (!Number.isSafeInteger(value) || value <= 0 || value > limits[
|
|
46592
|
+
const field2 = key;
|
|
46593
|
+
const value = options.limits[field2];
|
|
46594
|
+
if (!Number.isSafeInteger(value) || value <= 0 || value > limits[field2]) {
|
|
46395
46595
|
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Bundle limits must be positive integers within the hard ceilings");
|
|
46396
46596
|
}
|
|
46397
|
-
limits[
|
|
46597
|
+
limits[field2] = value;
|
|
46398
46598
|
}
|
|
46399
46599
|
return limits;
|
|
46400
46600
|
}
|
|
@@ -46424,7 +46624,14 @@ async function inspectSkillBundle(bundle, options = {}) {
|
|
|
46424
46624
|
decoder.destroy(terminalError);
|
|
46425
46625
|
};
|
|
46426
46626
|
const onAbort = () => stop("BUNDLE_ABORTED");
|
|
46427
|
-
const
|
|
46627
|
+
const expire = () => {
|
|
46628
|
+
const remaining = deadline - performance.now();
|
|
46629
|
+
if (remaining > 0)
|
|
46630
|
+
timer = setTimeout(expire, Math.max(1, Math.ceil(remaining)));
|
|
46631
|
+
else
|
|
46632
|
+
stop("BUNDLE_TIMEOUT");
|
|
46633
|
+
};
|
|
46634
|
+
let timer = setTimeout(expire, Math.max(1, Math.ceil(deadline - performance.now())));
|
|
46428
46635
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
46429
46636
|
let decompressedByteSize = 0;
|
|
46430
46637
|
let bytesSinceYield = 0;
|
|
@@ -46439,7 +46646,7 @@ async function inspectSkillBundle(bundle, options = {}) {
|
|
|
46439
46646
|
parser2.push(chunk);
|
|
46440
46647
|
bytesSinceYield += chunk.byteLength;
|
|
46441
46648
|
if (bytesSinceYield >= 256 * 1024) {
|
|
46442
|
-
await new Promise((
|
|
46649
|
+
await new Promise((resolve9) => setTimeout(resolve9, 0));
|
|
46443
46650
|
bytesSinceYield = 0;
|
|
46444
46651
|
check2();
|
|
46445
46652
|
}
|
|
@@ -46576,8 +46783,8 @@ class BoundedTarReader {
|
|
|
46576
46783
|
}
|
|
46577
46784
|
}
|
|
46578
46785
|
}
|
|
46579
|
-
function tarOctal(
|
|
46580
|
-
const text2 = new TextDecoder().decode(
|
|
46786
|
+
function tarOctal(field2) {
|
|
46787
|
+
const text2 = new TextDecoder().decode(field2);
|
|
46581
46788
|
if (!/^[0-7]+[\0 ]*$/.test(text2))
|
|
46582
46789
|
invalidBundle("Invalid tar octal field");
|
|
46583
46790
|
const value = Number.parseInt(text2, 8);
|
|
@@ -46796,21 +47003,21 @@ var init_profile_limits = __esm(() => {
|
|
|
46796
47003
|
});
|
|
46797
47004
|
|
|
46798
47005
|
// src/lib/selection-cache.ts
|
|
46799
|
-
import { createHash as
|
|
47006
|
+
import { createHash as createHash9, randomUUID } from "crypto";
|
|
46800
47007
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
46801
47008
|
import { closeSync as closeSync7, constants as constants4, fstatSync as fstatSync7, fsyncSync, linkSync, lstatSync as lstatSync9, mkdirSync as mkdirSync3, openSync as openSync7, readFileSync as readFileSync10, readlinkSync as readlinkSync2, readSync as readSync4, renameSync, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
46802
47009
|
import { hostname as hostname3 } from "os";
|
|
46803
|
-
import { dirname as
|
|
47010
|
+
import { dirname as dirname10, join as join15, parse as parse9, resolve as resolve9 } from "path";
|
|
46804
47011
|
import { isDeepStrictEqual } from "util";
|
|
46805
47012
|
function selectionCacheRoot(options = {}) {
|
|
46806
|
-
return
|
|
47013
|
+
return resolve9(options.cacheDir ?? join15(getDataDirReadOnly(), "selection-cache"));
|
|
46807
47014
|
}
|
|
46808
47015
|
function selectionKey(selection) {
|
|
46809
47016
|
validateSelection(selection);
|
|
46810
47017
|
return hash2([selection.authority, selection.workspaceId, selection.slug, selection.version, selection.bundleDigest]);
|
|
46811
47018
|
}
|
|
46812
47019
|
function hash2(value) {
|
|
46813
|
-
return
|
|
47020
|
+
return createHash9("sha256").update(JSON.stringify(value)).digest("hex");
|
|
46814
47021
|
}
|
|
46815
47022
|
function validateSelection(selection) {
|
|
46816
47023
|
if (!selection || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(selection.slug) || !isValidSkillVersion(selection.version) || !/^sha256:[a-f0-9]{64}$/.test(selection.bundleDigest) || typeof selection.workspaceId !== "string" || !selection.workspaceId.trim() || selection.authorizationEpoch !== undefined && (typeof selection.authorizationEpoch !== "string" || !/^[a-f0-9]{32}$/.test(selection.authorizationEpoch)) || typeof selection.profileRevision !== "string" || !selection.profileRevision.trim()) {
|
|
@@ -46850,7 +47057,7 @@ function selectionBundlePath(selection, options = {}) {
|
|
|
46850
47057
|
return join15(selectionCacheRoot(options), "objects", hash2(selection.authority), hash2(selection.workspaceId), `${selection.bundleDigest.slice(7)}.tar.gz`);
|
|
46851
47058
|
}
|
|
46852
47059
|
function assertRegularPath(path, createParents = false) {
|
|
46853
|
-
const absolute =
|
|
47060
|
+
const absolute = resolve9(path);
|
|
46854
47061
|
const root = parse9(absolute).root;
|
|
46855
47062
|
let cursor = root;
|
|
46856
47063
|
const segments = absolute.slice(root.length).split("/");
|
|
@@ -46907,7 +47114,7 @@ function writeSelectionJson(path, value) {
|
|
|
46907
47114
|
}
|
|
46908
47115
|
function atomicWrite(path, bytes, mode, durable = false) {
|
|
46909
47116
|
assertRegularPath(path, true);
|
|
46910
|
-
const temporary = join15(
|
|
47117
|
+
const temporary = join15(dirname10(path), `.selection-${randomUUID()}.tmp`);
|
|
46911
47118
|
try {
|
|
46912
47119
|
const fd = openSync7(temporary, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, mode);
|
|
46913
47120
|
try {
|
|
@@ -46919,7 +47126,7 @@ function atomicWrite(path, bytes, mode, durable = false) {
|
|
|
46919
47126
|
}
|
|
46920
47127
|
renameSync(temporary, path);
|
|
46921
47128
|
if (durable)
|
|
46922
|
-
syncDirectory(
|
|
47129
|
+
syncDirectory(dirname10(path));
|
|
46923
47130
|
} finally {
|
|
46924
47131
|
try {
|
|
46925
47132
|
unlinkSync(temporary);
|
|
@@ -46929,8 +47136,8 @@ function atomicWrite(path, bytes, mode, durable = false) {
|
|
|
46929
47136
|
}
|
|
46930
47137
|
}
|
|
46931
47138
|
}
|
|
46932
|
-
function readSelectionJson(path) {
|
|
46933
|
-
const bytes = readRegularFile(path, MAX_PROFILE_DOCUMENT_BYTES);
|
|
47139
|
+
function readSelectionJson(path, maximumBytes = MAX_PROFILE_DOCUMENT_BYTES) {
|
|
47140
|
+
const bytes = readRegularFile(path, Math.min(maximumBytes, MAX_PROFILE_DOCUMENT_BYTES));
|
|
46934
47141
|
if (!bytes)
|
|
46935
47142
|
return null;
|
|
46936
47143
|
try {
|
|
@@ -46942,10 +47149,10 @@ function readSelectionJson(path) {
|
|
|
46942
47149
|
async function verifiedEntries(selection, bytes, signal, deadline) {
|
|
46943
47150
|
if (`sha256:${sha256Hex(bytes)}` !== selection.bundleDigest)
|
|
46944
47151
|
throw new SkillSelectionError("BUNDLE_DIGEST_MISMATCH", "The skill bundle does not match its selected digest.");
|
|
46945
|
-
const remaining = deadline === undefined ? undefined : Math.
|
|
47152
|
+
const remaining = deadline === undefined ? undefined : Math.ceil(deadline - performance.now());
|
|
46946
47153
|
signal?.throwIfAborted();
|
|
46947
47154
|
if (remaining !== undefined && remaining <= 0)
|
|
46948
|
-
throw new
|
|
47155
|
+
throw new SkillBundleInspectionError("BUNDLE_TIMEOUT", "Bundle inspection deadline exceeded");
|
|
46949
47156
|
const bundle = await inspectSkillBundle(bytes, { signal, ...remaining === undefined ? {} : { limits: { timeoutMs: remaining } } });
|
|
46950
47157
|
return bundle.entries;
|
|
46951
47158
|
}
|
|
@@ -47045,7 +47252,7 @@ function assertFreshCachedProfile(receipt, options = {}) {
|
|
|
47045
47252
|
}
|
|
47046
47253
|
}
|
|
47047
47254
|
function projectSelectionLockPath(projectDir) {
|
|
47048
|
-
return join15(
|
|
47255
|
+
return join15(resolve9(projectDir), ".skills", SELECTION_LOCK_FILE);
|
|
47049
47256
|
}
|
|
47050
47257
|
function readProjectSelection(projectDir) {
|
|
47051
47258
|
const receipt = readSelectionJson(projectSelectionLockPath(projectDir));
|
|
@@ -47196,13 +47403,13 @@ function publishSessionLock(path, marker) {
|
|
|
47196
47403
|
fsyncSync(fd);
|
|
47197
47404
|
linkSync(stagingPath, path);
|
|
47198
47405
|
published = true;
|
|
47199
|
-
syncDirectory(
|
|
47406
|
+
syncDirectory(dirname10(path));
|
|
47200
47407
|
const staged = lstatSync9(stagingPath);
|
|
47201
47408
|
if (!staged.isFile() || staged.dev !== stat.dev || staged.ino !== stat.ino) {
|
|
47202
47409
|
throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "The initialized lock staging inode changed before publication completed.");
|
|
47203
47410
|
}
|
|
47204
47411
|
unlinkSync(stagingPath);
|
|
47205
|
-
syncDirectory(
|
|
47412
|
+
syncDirectory(dirname10(path));
|
|
47206
47413
|
handedOff = true;
|
|
47207
47414
|
return { path, stagingPath, fd, dev: stat.dev, ino: stat.ino };
|
|
47208
47415
|
} finally {
|
|
@@ -47247,14 +47454,14 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
47247
47454
|
writeFileSync3(guardFd, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, operationId: randomUUID() })}
|
|
47248
47455
|
`);
|
|
47249
47456
|
fsyncSync(guardFd);
|
|
47250
|
-
const cacheOptions = { cacheDir:
|
|
47457
|
+
const cacheOptions = { cacheDir: dirname10(dirname10(lock.path)) };
|
|
47251
47458
|
const current = readSessionLock(lock.marker.sessionId, cacheOptions);
|
|
47252
47459
|
if (!current || current.dev !== lock.dev || current.ino !== lock.ino || current.sha256 !== lock.sha256 || current.mtimeMs !== lock.mtimeMs || !writerIsGone(current, explicitLocalHost))
|
|
47253
47460
|
return null;
|
|
47254
47461
|
const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
|
|
47255
47462
|
if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
|
|
47256
47463
|
return null;
|
|
47257
|
-
const directory = join15(
|
|
47464
|
+
const directory = join15(dirname10(dirname10(lock.path)), "session-lock-recoveries", randomUUID());
|
|
47258
47465
|
const archivePath = join15(directory, "original.write-lock");
|
|
47259
47466
|
const recordPath = join15(directory, "recovery.json");
|
|
47260
47467
|
assertRegularPath(archivePath, true);
|
|
@@ -47271,7 +47478,7 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
47271
47478
|
})}
|
|
47272
47479
|
`));
|
|
47273
47480
|
syncDirectory(directory);
|
|
47274
|
-
syncDirectory(
|
|
47481
|
+
syncDirectory(dirname10(directory));
|
|
47275
47482
|
const finalLock = readSessionLock(lock.marker.sessionId, cacheOptions);
|
|
47276
47483
|
if (!finalLock || finalLock.dev !== lock.dev || finalLock.ino !== lock.ino || finalLock.sha256 !== lock.sha256 || readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions)?.sha256 !== receipt?.sha256)
|
|
47277
47484
|
return null;
|
|
@@ -47286,7 +47493,7 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
47286
47493
|
archivedPaths.push(publicationPath);
|
|
47287
47494
|
}
|
|
47288
47495
|
syncDirectory(directory);
|
|
47289
|
-
syncDirectory(
|
|
47496
|
+
syncDirectory(dirname10(lock.path));
|
|
47290
47497
|
for (const path of archivedPaths) {
|
|
47291
47498
|
const before = lstatSync9(path, { throwIfNoEntry: false });
|
|
47292
47499
|
const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
|
|
@@ -47437,8 +47644,8 @@ var init_selection_cache = __esm(() => {
|
|
|
47437
47644
|
init_profile_limits();
|
|
47438
47645
|
SkillSelectionError = class SkillSelectionError extends Error {
|
|
47439
47646
|
code;
|
|
47440
|
-
constructor(code, message) {
|
|
47441
|
-
super(message);
|
|
47647
|
+
constructor(code, message, options) {
|
|
47648
|
+
super(message, options);
|
|
47442
47649
|
this.code = code;
|
|
47443
47650
|
this.name = "SkillSelectionError";
|
|
47444
47651
|
}
|
|
@@ -47455,7 +47662,7 @@ __export(exports_remote_files, {
|
|
|
47455
47662
|
decodeRemoteFiles: () => decodeRemoteFiles,
|
|
47456
47663
|
MAX_REMOTE_FILE_BYTES: () => MAX_REMOTE_FILE_BYTES
|
|
47457
47664
|
});
|
|
47458
|
-
import { createHash as
|
|
47665
|
+
import { createHash as createHash10 } from "crypto";
|
|
47459
47666
|
function describeRemoteFiles(files) {
|
|
47460
47667
|
if (files.length > 10)
|
|
47461
47668
|
throw new Error("At most 10 input files are supported");
|
|
@@ -47472,7 +47679,7 @@ function describeRemoteFiles(files) {
|
|
|
47472
47679
|
});
|
|
47473
47680
|
}
|
|
47474
47681
|
function sha256(bytes) {
|
|
47475
|
-
return
|
|
47682
|
+
return createHash10("sha256").update(bytes).digest("hex");
|
|
47476
47683
|
}
|
|
47477
47684
|
async function readBoundedResponse(response, maximum, signal) {
|
|
47478
47685
|
if (!Number.isSafeInteger(maximum) || maximum < 0 || maximum > MAX_REMOTE_FILE_BYTES)
|
|
@@ -47548,6 +47755,10 @@ function identifier(value) {
|
|
|
47548
47755
|
function invalid() {
|
|
47549
47756
|
throw new Error("The Skills API returned an invalid profile response");
|
|
47550
47757
|
}
|
|
47758
|
+
function unavailable(error61, message) {
|
|
47759
|
+
const name = error61?.name;
|
|
47760
|
+
return new SkillSelectionError("SKILLS_API_UNAVAILABLE", message, name === "AbortError" || name === "TimeoutError" ? { cause: new DOMException("The Skills API request was cut short", name) } : undefined);
|
|
47761
|
+
}
|
|
47551
47762
|
function validateSelection2(value) {
|
|
47552
47763
|
if (!object6(value) || !identifier(value.slug) || typeof value.version !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(value.version) || value.version.includes("..") || typeof value.bundleDigest !== "string" || !/^sha256:[a-f0-9]{64}$/.test(value.bundleDigest))
|
|
47553
47764
|
invalid();
|
|
@@ -47595,8 +47806,8 @@ class HttpProfileClient {
|
|
|
47595
47806
|
...init.headers
|
|
47596
47807
|
}
|
|
47597
47808
|
});
|
|
47598
|
-
} catch {
|
|
47599
|
-
throw
|
|
47809
|
+
} catch (error61) {
|
|
47810
|
+
throw unavailable(error61, "Unable to reach the configured Skills API");
|
|
47600
47811
|
}
|
|
47601
47812
|
if (!response.ok) {
|
|
47602
47813
|
response.body?.cancel().catch(() => {});
|
|
@@ -47613,7 +47824,9 @@ class HttpProfileClient {
|
|
|
47613
47824
|
async read(response, limit = MAX_PROFILE_DOCUMENT_BYTES) {
|
|
47614
47825
|
try {
|
|
47615
47826
|
return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit, this.signal)));
|
|
47616
|
-
} catch {
|
|
47827
|
+
} catch (error61) {
|
|
47828
|
+
if (this.signal?.aborted)
|
|
47829
|
+
throw unavailable(this.signal.reason ?? error61, "The Skills API response was cut short");
|
|
47617
47830
|
invalid();
|
|
47618
47831
|
}
|
|
47619
47832
|
}
|
|
@@ -47703,17 +47916,17 @@ var init_profile_client = __esm(() => {
|
|
|
47703
47916
|
});
|
|
47704
47917
|
|
|
47705
47918
|
// src/lib/preparation-process.ts
|
|
47706
|
-
function capturePreparationProcess(
|
|
47919
|
+
function capturePreparationProcess(child2, platform = process.platform, signalGroup = (pid, signal) => process.kill(pid, signal)) {
|
|
47707
47920
|
let spawnedPid;
|
|
47708
47921
|
try {
|
|
47709
|
-
spawnedPid =
|
|
47922
|
+
spawnedPid = child2.pid;
|
|
47710
47923
|
} catch {}
|
|
47711
47924
|
const groupId = typeof spawnedPid === "number" && Number.isSafeInteger(spawnedPid) && spawnedPid > 1 ? spawnedPid : undefined;
|
|
47712
47925
|
const canSignalGroup = platform !== "win32" && groupId !== undefined;
|
|
47713
47926
|
const killLiveChild = () => {
|
|
47714
|
-
if (
|
|
47927
|
+
if (child2.exitCode === null && child2.signalCode === null) {
|
|
47715
47928
|
try {
|
|
47716
|
-
|
|
47929
|
+
child2.kill("SIGKILL");
|
|
47717
47930
|
} catch {}
|
|
47718
47931
|
}
|
|
47719
47932
|
};
|
|
@@ -47996,7 +48209,7 @@ var init_codex_native_skill_catalog = __esm(() => {
|
|
|
47996
48209
|
});
|
|
47997
48210
|
|
|
47998
48211
|
// src/lib/codex-plugin-skill-controls.ts
|
|
47999
|
-
import { basename as
|
|
48212
|
+
import { basename as basename6, dirname as dirname11, join as join17, relative as relative4, resolve as resolve10, sep as sep5 } from "path";
|
|
48000
48213
|
import { lstatSync as lstatSync11, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync3 } from "fs";
|
|
48001
48214
|
function refuse() {
|
|
48002
48215
|
throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
|
|
@@ -48060,7 +48273,7 @@ function mcpControls(path, read) {
|
|
|
48060
48273
|
function isBundledCleanupHooks(root, namespace, value) {
|
|
48061
48274
|
const object7 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
|
|
48062
48275
|
const exactKeys = (v, keys) => Object.keys(v).length === keys.length && keys.every((key) => Object.hasOwn(v, key));
|
|
48063
|
-
if (
|
|
48276
|
+
if (basename6(dirname11(root)) !== namespace || basename6(dirname11(dirname11(root))) !== "openai-bundled")
|
|
48064
48277
|
return false;
|
|
48065
48278
|
const server = namespace === "unified-computer-use" ? "cua_repl" : ["browser", "chrome", "chrome-dev", "chrome-internal", "computer-use"].includes(namespace) ? "node_repl" : undefined;
|
|
48066
48279
|
if (!server || !object7(value) || !exactKeys(value, ["hooks"]) || !object7(value.hooks))
|
|
@@ -48094,7 +48307,7 @@ function rootControls(root, read) {
|
|
|
48094
48307
|
}
|
|
48095
48308
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
|
|
48096
48309
|
refuse();
|
|
48097
|
-
const cacheVersion =
|
|
48310
|
+
const cacheVersion = basename6(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
48098
48311
|
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
48099
48312
|
refuse();
|
|
48100
48313
|
if (manifest.hooks !== undefined && !isBundledCleanupHooks(root, manifest.name, manifest.hooks) || manifest.commands !== undefined || manifest.mcpServers !== undefined && manifest.mcpServers !== "./.mcp.json" || manifest.apps !== undefined && manifest.apps !== "./.app.json" || lstatSync11(join17(root, "hooks"), { throwIfNoEntry: false }))
|
|
@@ -48118,13 +48331,13 @@ function rootControls(root, read) {
|
|
|
48118
48331
|
function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
48119
48332
|
try {
|
|
48120
48333
|
const parts = relative4(cache, parent).split(sep5), enrolled = controls.filter((control) => control.pluginParent === parent);
|
|
48121
|
-
if (
|
|
48334
|
+
if (resolve10(parent) !== parent || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !enrolled.length || !Array.isArray(rules))
|
|
48122
48335
|
return false;
|
|
48123
|
-
for (let cursor = parent;; cursor =
|
|
48336
|
+
for (let cursor = parent;; cursor = dirname11(cursor)) {
|
|
48124
48337
|
const stat = lstatSync11(cursor, { throwIfNoEntry: false });
|
|
48125
48338
|
if (stat && (!stat.isDirectory() || stat.isSymbolicLink()))
|
|
48126
48339
|
return false;
|
|
48127
|
-
if (
|
|
48340
|
+
if (dirname11(cursor) === cursor)
|
|
48128
48341
|
break;
|
|
48129
48342
|
}
|
|
48130
48343
|
return enrolled.every((control) => control.namespace === parts[1] && control.pluginId === `${parts[1]}@${parts[0]}` && remotePluginIdentifier(control.remotePluginId) && control.skillsOnly === true && !control.appSha256 && !control.mcpSha256 && control.name.startsWith(control.namespace + ":") && /^[a-f0-9]{64}$/.test(control.manifestSha256) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === control.name && rule.enabled === false) && !rules.some((rule) => (typeof rule?.name === "string" && rule.name.trim() === control.name || typeof rule?.path === "string" && (rule.path === parent || rule.path.startsWith(parent + sep5))) && rule.enabled !== false));
|
|
@@ -48137,14 +48350,14 @@ function absentDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
|
48137
48350
|
}
|
|
48138
48351
|
function reviewedRetiredCodexRoot(cache, root, controls, rules, read, allowAbsent = false) {
|
|
48139
48352
|
try {
|
|
48140
|
-
const parent =
|
|
48141
|
-
if (
|
|
48353
|
+
const parent = dirname11(root), parts = relative4(cache, parent).split(sep5), enrolled = controls.filter((control) => control.pluginParent === parent);
|
|
48354
|
+
if (resolve10(root) !== root || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !basename6(root) || basename6(root) === "latest" || !enrolled.length || !Array.isArray(rules))
|
|
48142
48355
|
return false;
|
|
48143
|
-
for (let cursor = root;; cursor =
|
|
48356
|
+
for (let cursor = root;; cursor = dirname11(cursor)) {
|
|
48144
48357
|
const stat = lstatSync11(cursor, { throwIfNoEntry: false });
|
|
48145
48358
|
if (stat && (!stat.isDirectory() || stat.isSymbolicLink()))
|
|
48146
48359
|
return false;
|
|
48147
|
-
if (
|
|
48360
|
+
if (dirname11(cursor) === cursor)
|
|
48148
48361
|
break;
|
|
48149
48362
|
}
|
|
48150
48363
|
if (!enrolled.every((control) => control.namespace === parts[1] && control.pluginId === `${parts[1]}@${parts[0]}` && remotePluginIdentifier(control.remotePluginId) && control.skillsOnly === true && !control.appSha256 && !control.mcpSha256 && control.name.startsWith(control.namespace + ":") && /^[a-f0-9]{64}$/.test(control.manifestSha256) && rules.some((rule) => typeof rule?.name === "string" && rule.name.trim() === control.name && rule.enabled === false) && !rules.some((rule) => (typeof rule?.name === "string" && rule.name.trim() === control.name || typeof rule?.path === "string" && (rule.path === parent || rule.path === root || rule.path.startsWith(root + sep5))) && rule.enabled !== false)))
|
|
@@ -48191,8 +48404,8 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
48191
48404
|
for (const name of names) {
|
|
48192
48405
|
let root = join17(parent, name), stat = lstatSync11(root);
|
|
48193
48406
|
if (stat.isSymbolicLink()) {
|
|
48194
|
-
const target =
|
|
48195
|
-
if (name !== "latest" ||
|
|
48407
|
+
const target = resolve10(parent, readlinkSync3(root));
|
|
48408
|
+
if (name !== "latest" || dirname11(target) !== parent || !lstatSync11(target).isDirectory() || realpathSync3(target) !== target)
|
|
48196
48409
|
return false;
|
|
48197
48410
|
root = target;
|
|
48198
48411
|
stat = lstatSync11(root);
|
|
@@ -48212,7 +48425,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
48212
48425
|
function sourceInputUnchanged(input2, cache, read) {
|
|
48213
48426
|
try {
|
|
48214
48427
|
const parts = relative4(cache, input2.pluginParent).split(sep5);
|
|
48215
|
-
if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== input2.namespace || input2.pluginId !== `${parts[1]}@${parts[0]}` || !codexPluginSourceIsConfigControlled({ id: input2.pluginId, sourceType: "local", sourceSha256: input2.sourceSha256 }) || input2.sourceSha256 !== hashNativeJsonControls(JSON.stringify({ type: "local", path: input2.sourceRoot })) ||
|
|
48428
|
+
if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== input2.namespace || input2.pluginId !== `${parts[1]}@${parts[0]}` || !codexPluginSourceIsConfigControlled({ id: input2.pluginId, sourceType: "local", sourceSha256: input2.sourceSha256 }) || input2.sourceSha256 !== hashNativeJsonControls(JSON.stringify({ type: "local", path: input2.sourceRoot })) || resolve10(input2.sourceRoot) !== input2.sourceRoot || !lstatSync11(input2.sourceRoot).isDirectory() || realpathSync3(input2.sourceRoot) !== input2.sourceRoot || input2.sourceRoot === cache || input2.sourceRoot.startsWith(cache + sep5) || cache.startsWith(input2.sourceRoot + sep5))
|
|
48216
48429
|
return false;
|
|
48217
48430
|
const path = join17(input2.sourceRoot, ".codex-plugin/plugin.json"), stat = lstatSync11(path);
|
|
48218
48431
|
if (!stat.isFile() || stat.size > 1024 * 1024 || realpathSync3(path) !== path)
|
|
@@ -48250,8 +48463,8 @@ var init_codex_native_skill_policy = __esm(() => {
|
|
|
48250
48463
|
});
|
|
48251
48464
|
|
|
48252
48465
|
// src/lib/codex-settings-witness-v1.ts
|
|
48253
|
-
import { createHash as
|
|
48254
|
-
function
|
|
48466
|
+
import { createHash as createHash11 } from "crypto";
|
|
48467
|
+
function need4(value) {
|
|
48255
48468
|
if (!value)
|
|
48256
48469
|
throw new Error("Invalid Codex settings witness");
|
|
48257
48470
|
}
|
|
@@ -48266,14 +48479,14 @@ function numericTokens(text2) {
|
|
|
48266
48479
|
continue;
|
|
48267
48480
|
}
|
|
48268
48481
|
if (char === '"' || char === "'") {
|
|
48269
|
-
const
|
|
48482
|
+
const quote2 = char, triple = text2.slice(at, at + 3) === quote2.repeat(3);
|
|
48270
48483
|
at += triple ? 3 : 1;
|
|
48271
48484
|
while (at < text2.length) {
|
|
48272
|
-
if (
|
|
48485
|
+
if (quote2 === '"' && text2[at] === "\\") {
|
|
48273
48486
|
at += 2;
|
|
48274
48487
|
continue;
|
|
48275
48488
|
}
|
|
48276
|
-
if (text2.slice(at, at + (triple ? 3 : 1)) ===
|
|
48489
|
+
if (text2.slice(at, at + (triple ? 3 : 1)) === quote2.repeat(triple ? 3 : 1)) {
|
|
48277
48490
|
at += triple ? 3 : 1;
|
|
48278
48491
|
break;
|
|
48279
48492
|
}
|
|
@@ -48294,8 +48507,8 @@ function numericTokens(text2) {
|
|
|
48294
48507
|
}
|
|
48295
48508
|
return result;
|
|
48296
48509
|
}
|
|
48297
|
-
function
|
|
48298
|
-
|
|
48510
|
+
function canonical5(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
48511
|
+
need4(depth <= 32 && --budget2.remaining >= 0);
|
|
48299
48512
|
if (value === null)
|
|
48300
48513
|
return ["null"];
|
|
48301
48514
|
if (typeof value === "string")
|
|
@@ -48303,20 +48516,20 @@ function canonical4(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
|
48303
48516
|
if (typeof value === "boolean")
|
|
48304
48517
|
return ["boolean", value];
|
|
48305
48518
|
if (typeof value === "number") {
|
|
48306
|
-
|
|
48519
|
+
need4(Number.isFinite(value));
|
|
48307
48520
|
return ["number", String(value)];
|
|
48308
48521
|
}
|
|
48309
48522
|
if (value instanceof Date) {
|
|
48310
|
-
|
|
48523
|
+
need4(Number.isFinite(value.getTime()));
|
|
48311
48524
|
return ["date", value.toISOString()];
|
|
48312
48525
|
}
|
|
48313
48526
|
if (Array.isArray(value))
|
|
48314
|
-
return ["array", value.map((
|
|
48315
|
-
|
|
48316
|
-
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key,
|
|
48527
|
+
return ["array", value.map((child2) => canonical5(child2, depth + 1, budget2))];
|
|
48528
|
+
need4(value && typeof value === "object");
|
|
48529
|
+
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child2]) => [key, canonical5(child2, depth + 1, budget2)])];
|
|
48317
48530
|
}
|
|
48318
48531
|
function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48319
|
-
|
|
48532
|
+
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48320
48533
|
budget2.remaining -= Buffer.byteLength(text2);
|
|
48321
48534
|
let config2;
|
|
48322
48535
|
try {
|
|
@@ -48324,23 +48537,23 @@ function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 *
|
|
|
48324
48537
|
} catch {
|
|
48325
48538
|
throw new Error("Invalid Codex settings witness");
|
|
48326
48539
|
}
|
|
48327
|
-
|
|
48540
|
+
need4(config2 && typeof config2 === "object" && !Array.isArray(config2));
|
|
48328
48541
|
if (Object.hasOwn(config2, "model")) {
|
|
48329
|
-
|
|
48542
|
+
need4(typeof config2.model === "string" && /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/.test(config2.model));
|
|
48330
48543
|
delete config2.model;
|
|
48331
48544
|
}
|
|
48332
48545
|
for (const [key, values] of [["model_reasoning_effort", EFFORT], ["model_verbosity", VERBOSITY]])
|
|
48333
48546
|
if (Object.hasOwn(config2, key)) {
|
|
48334
|
-
|
|
48547
|
+
need4(typeof config2[key] === "string" && values.has(config2[key]));
|
|
48335
48548
|
delete config2[key];
|
|
48336
48549
|
}
|
|
48337
|
-
return sha(`hasna.skills.codex-settings.v1\x00${JSON.stringify([
|
|
48550
|
+
return sha(`hasna.skills.codex-settings.v1\x00${JSON.stringify([canonical5(config2), numericTokens(text2)])}`);
|
|
48338
48551
|
}
|
|
48339
48552
|
function captureCodexSettings(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48340
48553
|
const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
|
|
48341
48554
|
return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text2) };
|
|
48342
48555
|
}
|
|
48343
|
-
var sha = (text2) =>
|
|
48556
|
+
var sha = (text2) => createHash11("sha256").update(text2).digest("hex"), EFFORT, VERBOSITY;
|
|
48344
48557
|
var init_codex_settings_witness_v1 = __esm(() => {
|
|
48345
48558
|
init_claude_settings_witness();
|
|
48346
48559
|
EFFORT = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
|
|
@@ -48413,9 +48626,9 @@ function projectRegularCodexMcp(config2, source) {
|
|
|
48413
48626
|
var init_codex_mcp_discovery_projection = () => {};
|
|
48414
48627
|
|
|
48415
48628
|
// src/lib/codex-settings-witness.ts
|
|
48416
|
-
import { createHash as
|
|
48629
|
+
import { createHash as createHash12 } from "crypto";
|
|
48417
48630
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
48418
|
-
function
|
|
48631
|
+
function need5(value) {
|
|
48419
48632
|
if (!value)
|
|
48420
48633
|
throw new Error("Invalid Codex settings witness");
|
|
48421
48634
|
}
|
|
@@ -48436,14 +48649,14 @@ function numericTokens2(text2) {
|
|
|
48436
48649
|
continue;
|
|
48437
48650
|
}
|
|
48438
48651
|
if (char === '"' || char === "'") {
|
|
48439
|
-
const
|
|
48652
|
+
const quote2 = char, triple = text2.slice(at, at + 3) === quote2.repeat(3);
|
|
48440
48653
|
at += triple ? 3 : 1;
|
|
48441
48654
|
while (at < text2.length) {
|
|
48442
|
-
if (
|
|
48655
|
+
if (quote2 === '"' && text2[at] === "\\") {
|
|
48443
48656
|
at += 2;
|
|
48444
48657
|
continue;
|
|
48445
48658
|
}
|
|
48446
|
-
if (text2.slice(at, at + (triple ? 3 : 1)) ===
|
|
48659
|
+
if (text2.slice(at, at + (triple ? 3 : 1)) === quote2.repeat(triple ? 3 : 1)) {
|
|
48447
48660
|
at += triple ? 3 : 1;
|
|
48448
48661
|
break;
|
|
48449
48662
|
}
|
|
@@ -48464,8 +48677,8 @@ function numericTokens2(text2) {
|
|
|
48464
48677
|
}
|
|
48465
48678
|
return result.sort();
|
|
48466
48679
|
}
|
|
48467
|
-
function
|
|
48468
|
-
|
|
48680
|
+
function canonical6(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
48681
|
+
need5(depth <= 32 && --budget2.remaining >= 0);
|
|
48469
48682
|
if (value === null)
|
|
48470
48683
|
return ["null"];
|
|
48471
48684
|
if (typeof value === "string")
|
|
@@ -48473,17 +48686,17 @@ function canonical5(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
|
48473
48686
|
if (typeof value === "boolean")
|
|
48474
48687
|
return ["boolean", value];
|
|
48475
48688
|
if (typeof value === "number") {
|
|
48476
|
-
|
|
48689
|
+
need5(Number.isFinite(value));
|
|
48477
48690
|
return ["number", String(value)];
|
|
48478
48691
|
}
|
|
48479
48692
|
if (isDate(value)) {
|
|
48480
|
-
|
|
48693
|
+
need5(Number.isFinite(value.getTime()));
|
|
48481
48694
|
return ["date", value.toISOString()];
|
|
48482
48695
|
}
|
|
48483
48696
|
if (Array.isArray(value))
|
|
48484
|
-
return ["array", value.map((
|
|
48485
|
-
|
|
48486
|
-
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key,
|
|
48697
|
+
return ["array", value.map((child2) => canonical6(child2, depth + 1, budget2))];
|
|
48698
|
+
need5(isRecord3(value));
|
|
48699
|
+
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child2]) => [key, canonical6(child2, depth + 1, budget2)])];
|
|
48487
48700
|
}
|
|
48488
48701
|
function normalize2(config2, version2 = 2) {
|
|
48489
48702
|
if (isRecord3(config2.hooks)) {
|
|
@@ -48525,15 +48738,15 @@ function inference(target, version2) {
|
|
|
48525
48738
|
if (Object.hasOwn(target, key)) {
|
|
48526
48739
|
const value = target[key];
|
|
48527
48740
|
if (key === "model")
|
|
48528
|
-
|
|
48741
|
+
need5(typeof value === "string" && MODEL.test(value));
|
|
48529
48742
|
else if (key === "personality")
|
|
48530
|
-
|
|
48743
|
+
need5(typeof value === "string" && ["none", "friendly", "pragmatic"].includes(value));
|
|
48531
48744
|
else if (version2 >= 3 && key !== "model_verbosity") {
|
|
48532
|
-
|
|
48745
|
+
need5(typeof value === "string" && value.length <= 128 && !/[\x00-\x1f\x7f]/.test(value));
|
|
48533
48746
|
if (key !== "service_tier")
|
|
48534
|
-
|
|
48747
|
+
need5(value.length > 0);
|
|
48535
48748
|
} else
|
|
48536
|
-
|
|
48749
|
+
need5(typeof value === "string" && (key === "model_reasoning_effort" ? EFFORT2.has(value) : VERBOSITY2.has(value)));
|
|
48537
48750
|
delete target[key];
|
|
48538
48751
|
}
|
|
48539
48752
|
}
|
|
@@ -48566,14 +48779,14 @@ function projectModelAvailabilityNux(config2, text2) {
|
|
|
48566
48779
|
continue;
|
|
48567
48780
|
}
|
|
48568
48781
|
if (char === '"' || char === "'") {
|
|
48569
|
-
const
|
|
48782
|
+
const quote2 = char;
|
|
48570
48783
|
at++;
|
|
48571
48784
|
while (at < span.length) {
|
|
48572
|
-
if (
|
|
48785
|
+
if (quote2 === '"' && span[at] === "\\") {
|
|
48573
48786
|
at += 2;
|
|
48574
48787
|
continue;
|
|
48575
48788
|
}
|
|
48576
|
-
if (span[at++] ===
|
|
48789
|
+
if (span[at++] === quote2)
|
|
48577
48790
|
break;
|
|
48578
48791
|
}
|
|
48579
48792
|
continue;
|
|
@@ -48653,14 +48866,14 @@ function settingsDigest2(text2, version2 = 2) {
|
|
|
48653
48866
|
} catch {
|
|
48654
48867
|
throw new Error("Invalid Codex settings witness");
|
|
48655
48868
|
}
|
|
48656
|
-
|
|
48869
|
+
need5(isRecord3(config2));
|
|
48657
48870
|
const mcp = version2 >= 3 ? projectRegularCodexMcp(config2, text2) : { config: config2, numericSource: text2 };
|
|
48658
48871
|
const projected = version2 === 4 ? projectModelAvailabilityNux(mcp.config, mcp.numericSource) : mcp;
|
|
48659
48872
|
normalize2(projected.config, version2);
|
|
48660
|
-
return sha2(`hasna.skills.codex-settings.v${version2}\x00${JSON.stringify([
|
|
48873
|
+
return sha2(`hasna.skills.codex-settings.v${version2}\x00${JSON.stringify([canonical6(projected.config), numericTokens2(projected.numericSource)])}`);
|
|
48661
48874
|
}
|
|
48662
48875
|
function hashCodexSettingsReplacementV2(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48663
|
-
|
|
48876
|
+
need5(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48664
48877
|
budget2.remaining -= Buffer.byteLength(text2);
|
|
48665
48878
|
return settingsDigest2(text2);
|
|
48666
48879
|
}
|
|
@@ -48669,7 +48882,7 @@ function captureCodexSettingsV2(path, budget2 = { remaining: 256 * 1024 * 1024 }
|
|
|
48669
48882
|
return { path, hashMode: "codex-settings-v2", sha256: settingsDigest2(text2) };
|
|
48670
48883
|
}
|
|
48671
48884
|
function hashCodexSettingsReplacementV3(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48672
|
-
|
|
48885
|
+
need5(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48673
48886
|
budget2.remaining -= Buffer.byteLength(text2);
|
|
48674
48887
|
return settingsDigest2(text2, 3);
|
|
48675
48888
|
}
|
|
@@ -48677,14 +48890,14 @@ function captureCodexSettingsV3(path, budget2 = { remaining: 256 * 1024 * 1024 }
|
|
|
48677
48890
|
return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 3) };
|
|
48678
48891
|
}
|
|
48679
48892
|
function hashCodexSettingsReplacementV4(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48680
|
-
|
|
48893
|
+
need5(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48681
48894
|
budget2.remaining -= Buffer.byteLength(text2);
|
|
48682
48895
|
return settingsDigest2(text2, 4);
|
|
48683
48896
|
}
|
|
48684
48897
|
function captureCodexSettingsV4(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48685
48898
|
return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 4) };
|
|
48686
48899
|
}
|
|
48687
|
-
var sha2 = (text2) =>
|
|
48900
|
+
var sha2 = (text2) => createHash12("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
|
|
48688
48901
|
var init_codex_settings_witness = __esm(() => {
|
|
48689
48902
|
init_codex_settings_witness_v1();
|
|
48690
48903
|
init_codex_settings_witness_v1();
|
|
@@ -48700,8 +48913,8 @@ var init_codex_settings_witness = __esm(() => {
|
|
|
48700
48913
|
// src/lib/managed-policy.ts
|
|
48701
48914
|
import { closeSync as closeSync9, constants as constants6, fstatSync as fstatSync9, lstatSync as lstatSync12, openSync as openSync9, readSync as readSync5 } from "fs";
|
|
48702
48915
|
import { join as join18 } from "path";
|
|
48703
|
-
function refusal(
|
|
48704
|
-
return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${
|
|
48916
|
+
function refusal(reason2 = "is unreadable") {
|
|
48917
|
+
return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${reason2}; refusing legacy fallback.`);
|
|
48705
48918
|
}
|
|
48706
48919
|
function parseManagedSkillPolicy(text2) {
|
|
48707
48920
|
if (Buffer.byteLength(text2) > AGENT_POLICY_LIMITS.bytes)
|
|
@@ -48777,7 +48990,7 @@ var init_managed_policy = __esm(() => {
|
|
|
48777
48990
|
});
|
|
48778
48991
|
|
|
48779
48992
|
// src/lib/agent-bridge.ts
|
|
48780
|
-
import { createHash as
|
|
48993
|
+
import { createHash as createHash13 } from "crypto";
|
|
48781
48994
|
var CLI_BRIDGE_VERSION = 1, markdown = `---
|
|
48782
48995
|
name: skills-cli
|
|
48783
48996
|
description: Discover, load, author, and run versioned skills through the Skills CLI when a task needs reusable instructions or an executable skill.
|
|
@@ -48793,7 +49006,7 @@ Use the Skills CLI as the skill authority for this station.
|
|
|
48793
49006
|
This bridge contains no skill payloads. Do not copy skill content into agent-native skill directories or load other native skill copies. If a Skills command refuses authority, selection, integrity, or native drift, report that refusal and use its repair guidance; do not substitute bundled or stale local content. Explicit local draft authoring remains available.
|
|
48794
49007
|
`, CLI_BRIDGE_DIGEST, CLI_BRIDGE_FILES;
|
|
48795
49008
|
var init_agent_bridge = __esm(() => {
|
|
48796
|
-
CLI_BRIDGE_DIGEST =
|
|
49009
|
+
CLI_BRIDGE_DIGEST = createHash13("sha256").update(markdown).digest("hex");
|
|
48797
49010
|
CLI_BRIDGE_FILES = Object.freeze({
|
|
48798
49011
|
"SKILL.md": markdown,
|
|
48799
49012
|
".hasna-skills.json": `${JSON.stringify({ managedBy: "@hasna/skills", kind: "cli-bridge", version: CLI_BRIDGE_VERSION, protocol: "selection-v1", contentSha256: CLI_BRIDGE_DIGEST }, null, 2)}
|
|
@@ -48806,28 +49019,28 @@ var init_agent_codex = () => {};
|
|
|
48806
49019
|
|
|
48807
49020
|
// src/lib/agent-sumi.ts
|
|
48808
49021
|
import { existsSync as existsSync8, lstatSync as lstatSync13, realpathSync as realpathSync4 } from "fs";
|
|
48809
|
-
import { join as join19, resolve as
|
|
49022
|
+
import { join as join19, resolve as resolve11 } from "path";
|
|
48810
49023
|
function sumiConfigDirectory(home, env = process.env) {
|
|
48811
49024
|
for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
|
|
48812
49025
|
if (env[key] !== undefined)
|
|
48813
49026
|
throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
|
|
48814
49027
|
const selected = (key) => env[key]?.trim() ? env[key] : undefined;
|
|
48815
|
-
const expand = (value) =>
|
|
49028
|
+
const expand = (value) => resolve11(value === "~" ? home : value.startsWith("~/") ? join19(home, value.slice(2)) : value);
|
|
48816
49029
|
const explicit = selected("SUMI_CONFIG_DIR");
|
|
48817
49030
|
const xdg = selected("XDG_CONFIG_HOME");
|
|
48818
49031
|
const custom2 = selected("SUMI_HOME");
|
|
48819
|
-
const
|
|
49032
|
+
const canonical7 = explicit ? expand(explicit) : xdg ? join19(expand(xdg), "sumi") : join19(custom2 ? expand(custom2) : join19(home, ".hasna-internal/sumi"), "config");
|
|
48820
49033
|
if (explicit || xdg || custom2)
|
|
48821
|
-
return
|
|
49034
|
+
return canonical7;
|
|
48822
49035
|
const legacy = join19(home, ".config/sumi");
|
|
48823
|
-
const a = lstatSync13(
|
|
48824
|
-
if (a && b && realpathSync4(
|
|
49036
|
+
const a = lstatSync13(canonical7, { throwIfNoEntry: false }), b = lstatSync13(legacy, { throwIfNoEntry: false });
|
|
49037
|
+
if (a && b && realpathSync4(canonical7) !== realpathSync4(legacy))
|
|
48825
49038
|
throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
|
|
48826
|
-
const path = a ?
|
|
49039
|
+
const path = a ? canonical7 : b ? legacy : canonical7;
|
|
48827
49040
|
if (!existsSync8(path))
|
|
48828
49041
|
return path;
|
|
48829
49042
|
const physical = realpathSync4(path);
|
|
48830
|
-
if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![
|
|
49043
|
+
if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
|
|
48831
49044
|
throw new Error("Sumi config alias must resolve to its canonical or legacy root");
|
|
48832
49045
|
return physical;
|
|
48833
49046
|
}
|
|
@@ -48837,19 +49050,22 @@ function sumiConfigPath(home) {
|
|
|
48837
49050
|
var init_agent_sumi = () => {};
|
|
48838
49051
|
|
|
48839
49052
|
// src/lib/codex-hook-trust-files.ts
|
|
48840
|
-
import { closeSync as closeSync10, constants as constants7, fstatSync as fstatSync10, fsyncSync as fsyncSync2, lstatSync as lstatSync14, openSync as openSync10, readSync as readSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
48841
|
-
import { createHash as
|
|
48842
|
-
import { dirname as
|
|
48843
|
-
function
|
|
49053
|
+
import { closeSync as closeSync10, constants as constants7, fstatSync as fstatSync10, fsyncSync as fsyncSync2, lstatSync as lstatSync14, openSync as openSync10, readlinkSync as readlinkSync4, readSync as readSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
49054
|
+
import { createHash as createHash14 } from "crypto";
|
|
49055
|
+
import { dirname as dirname12, isAbsolute as isAbsolute10, resolve as resolve12 } from "path";
|
|
49056
|
+
function need6(value, code) {
|
|
48844
49057
|
if (!value)
|
|
48845
49058
|
throw new Error(`CODEX_HOOK_TRUST_${code}`);
|
|
48846
49059
|
}
|
|
49060
|
+
function trustedAncestorOwner(uid) {
|
|
49061
|
+
return BigInt(uid) === 0n || BigInt(uid) === BigInt(process.getuid());
|
|
49062
|
+
}
|
|
48847
49063
|
function safeParents(file2) {
|
|
48848
|
-
for (let p =
|
|
49064
|
+
for (let p = dirname12(file2);; p = dirname12(p)) {
|
|
48849
49065
|
const s = lstatSync14(p);
|
|
48850
|
-
|
|
48851
|
-
|
|
48852
|
-
if (
|
|
49066
|
+
need6(s.isDirectory() && !s.isSymbolicLink() && trustedAncestorOwner(s.uid), "UNSAFE_PARENT");
|
|
49067
|
+
need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
|
|
49068
|
+
if (dirname12(p) === p)
|
|
48853
49069
|
break;
|
|
48854
49070
|
}
|
|
48855
49071
|
}
|
|
@@ -48857,12 +49073,12 @@ function snapshot(file2, privateFile = false, options = {}) {
|
|
|
48857
49073
|
const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
|
|
48858
49074
|
safeParents(file2);
|
|
48859
49075
|
const initial = lstatSync14(file2, { bigint: true });
|
|
48860
|
-
|
|
48861
|
-
|
|
49076
|
+
need6(initial.isFile() && initial.uid === BigInt(process.getuid()) && (initial.nlink === 1n || readOnlyPackage && initial.nlink > 1n) && (initial.mode & 0o022n) === 0n && (!privateFile || (initial.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
|
|
49077
|
+
need6(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
|
|
48862
49078
|
const fd = openSync10(file2, constants7.O_RDONLY | constants7.O_NOFOLLOW | constants7.O_NONBLOCK);
|
|
48863
49079
|
try {
|
|
48864
49080
|
const before = fstatSync10(fd, { bigint: true });
|
|
48865
|
-
|
|
49081
|
+
need6(sameStat(initial, before), "INPUT_CHANGED");
|
|
48866
49082
|
const bytes = Buffer.alloc(Number(before.size) + 1);
|
|
48867
49083
|
let length = 0;
|
|
48868
49084
|
while (length < bytes.length) {
|
|
@@ -48871,16 +49087,16 @@ function snapshot(file2, privateFile = false, options = {}) {
|
|
|
48871
49087
|
break;
|
|
48872
49088
|
length += n2;
|
|
48873
49089
|
}
|
|
48874
|
-
|
|
49090
|
+
need6(length === Number(before.size) && sameStat(before, fstatSync10(fd, { bigint: true })) && sameStat(before, lstatSync14(file2, { bigint: true })), "INPUT_CHANGED");
|
|
48875
49091
|
const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
48876
|
-
return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256:
|
|
49092
|
+
return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash14("sha256").update(content).digest("hex") };
|
|
48877
49093
|
} finally {
|
|
48878
49094
|
closeSync10(fd);
|
|
48879
49095
|
}
|
|
48880
49096
|
}
|
|
48881
49097
|
function unchanged2(before) {
|
|
48882
49098
|
const after = snapshot(before.file, before.privateFile, before.readOnlyPackage ? { readOnlyPackage: true } : {});
|
|
48883
|
-
|
|
49099
|
+
need6(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
|
|
48884
49100
|
}
|
|
48885
49101
|
var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
|
|
48886
49102
|
var init_codex_hook_trust_files = () => {};
|
|
@@ -49622,7 +49838,7 @@ var init_selection_resolver = __esm(() => {
|
|
|
49622
49838
|
});
|
|
49623
49839
|
|
|
49624
49840
|
// src/lib/plugin-projection.ts
|
|
49625
|
-
import { createHash as
|
|
49841
|
+
import { createHash as createHash15 } from "crypto";
|
|
49626
49842
|
function pluginRefusal(message) {
|
|
49627
49843
|
throw new SkillSelectionError("PLUGIN_ADMISSION_REFUSED", message);
|
|
49628
49844
|
}
|
|
@@ -49700,7 +49916,7 @@ function pluginFileWitnesses(entries) {
|
|
|
49700
49916
|
return { path: item.path, mode: item.mode, size: item.bytes.byteLength, sha256: pluginHash(item.bytes) };
|
|
49701
49917
|
});
|
|
49702
49918
|
}
|
|
49703
|
-
var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) =>
|
|
49919
|
+
var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash15("sha256").update(bytes).digest("hex");
|
|
49704
49920
|
var init_plugin_projection = __esm(() => {
|
|
49705
49921
|
init_selection_cache();
|
|
49706
49922
|
PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
|
|
@@ -49708,7 +49924,7 @@ var init_plugin_projection = __esm(() => {
|
|
|
49708
49924
|
|
|
49709
49925
|
// src/lib/plugin-projection-store.ts
|
|
49710
49926
|
import { constants as constants8, closeSync as closeSync11, fchmodSync, fstatSync as fstatSync11, fsyncSync as fsyncSync3, linkSync as linkSync2, lstatSync as lstatSync15, mkdirSync as mkdirSync6, openSync as openSync11, opendirSync as opendirSync2, readSync as readSync7, renameSync as renameSync2, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
|
|
49711
|
-
import { dirname as
|
|
49927
|
+
import { dirname as dirname13, isAbsolute as isAbsolute11, join as join23, parse as parse10, resolve as resolve13 } from "path";
|
|
49712
49928
|
function stat(path) {
|
|
49713
49929
|
try {
|
|
49714
49930
|
return lstatSync15(path, { bigint: true });
|
|
@@ -49718,8 +49934,8 @@ function stat(path) {
|
|
|
49718
49934
|
return pluginRefusal("Cannot inspect plugin filesystem entry");
|
|
49719
49935
|
}
|
|
49720
49936
|
}
|
|
49721
|
-
function
|
|
49722
|
-
pluginNeed(typeof path === "string" && path.length <= 8192 &&
|
|
49937
|
+
function canonical7(path) {
|
|
49938
|
+
pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute11(path) && resolve13(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
|
|
49723
49939
|
}
|
|
49724
49940
|
function owner(stats, system = false) {
|
|
49725
49941
|
const current = uid();
|
|
@@ -49729,8 +49945,8 @@ function same3(left, right, identityOnly = false) {
|
|
|
49729
49945
|
pluginNeed(right && left.dev === right.dev && left.ino === right.ino && left.mode === right.mode && left.uid === right.uid && left.gid === right.gid && (identityOnly || left.size === right.size && left.nlink === right.nlink && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs), "Plugin filesystem entry changed during access");
|
|
49730
49946
|
}
|
|
49731
49947
|
function ancestors(path, create = false) {
|
|
49732
|
-
|
|
49733
|
-
const result = [], parent =
|
|
49948
|
+
canonical7(path);
|
|
49949
|
+
const result = [], parent = dirname13(path), filesystemRoot = parse10(parent).root;
|
|
49734
49950
|
let current = filesystemRoot;
|
|
49735
49951
|
for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
|
|
49736
49952
|
if (segment)
|
|
@@ -49956,7 +50172,7 @@ var init_selected_manifest = __esm(() => {
|
|
|
49956
50172
|
});
|
|
49957
50173
|
|
|
49958
50174
|
// src/lib/plugin-admission.ts
|
|
49959
|
-
import { isAbsolute as
|
|
50175
|
+
import { isAbsolute as isAbsolute12, join as join24, resolve as resolve14 } from "path";
|
|
49960
50176
|
function validatePluginTarget(value) {
|
|
49961
50177
|
pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
|
|
49962
50178
|
pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
|
|
@@ -49966,7 +50182,7 @@ function validatePluginTarget(value) {
|
|
|
49966
50182
|
for (const registration of value.registrations) {
|
|
49967
50183
|
pluginKeys(registration, ["scope", "projectPath"]);
|
|
49968
50184
|
pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
|
|
49969
|
-
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" &&
|
|
50185
|
+
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute12(registration.projectPath) && resolve14(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
|
|
49970
50186
|
const key = JSON.stringify([registration.scope, registration.projectPath]);
|
|
49971
50187
|
pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
|
|
49972
50188
|
scopes.add(key);
|
|
@@ -49974,7 +50190,7 @@ function validatePluginTarget(value) {
|
|
|
49974
50190
|
for (const key of ["native", "resolver"]) {
|
|
49975
50191
|
pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
|
|
49976
50192
|
pluginText(value[key].executable);
|
|
49977
|
-
pluginNeed(
|
|
50193
|
+
pluginNeed(isAbsolute12(value[key].executable) && resolve14(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
|
|
49978
50194
|
pluginDigest(value[key].digest);
|
|
49979
50195
|
}
|
|
49980
50196
|
pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
|
|
@@ -50113,7 +50329,7 @@ function validatePlan(value) {
|
|
|
50113
50329
|
pluginNeed(identityDigest(plan) === plan.planDigest, "Plugin receipt immutable identity changed");
|
|
50114
50330
|
}
|
|
50115
50331
|
function pluginResolverCommand(binding) {
|
|
50116
|
-
return `${
|
|
50332
|
+
return `${quote2("/bin/sh")} -eu -c ${quote2(resolverGuard)} plugin-resolver ${quote2(binding.target.resolver.executable)} ${quote2(binding.target.resolver.digest)} ${quote2(bindingId(binding))}`;
|
|
50117
50333
|
}
|
|
50118
50334
|
function pluginBindingPath(storeRoot, id) {
|
|
50119
50335
|
pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
|
|
@@ -50147,7 +50363,7 @@ function readPluginAdmissionReceipt(storeRoot, id, digest) {
|
|
|
50147
50363
|
pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
|
|
50148
50364
|
return receipt;
|
|
50149
50365
|
}
|
|
50150
|
-
var
|
|
50366
|
+
var quote2 = (value) => `'${value.replaceAll("'", "'\\''")}'`, resolverGuard = 'exec 9<"$1"; actual=$(/usr/bin/sha256sum /proc/self/fd/9); actual=${actual%% *}; [ "sha256:$actual" = "$2" ]; exec /proc/self/fd/9 integration plugin resolve --binding "$3"';
|
|
50151
50367
|
var init_plugin_admission = __esm(() => {
|
|
50152
50368
|
init_profile_client();
|
|
50153
50369
|
init_skill_bundle();
|
|
@@ -50160,7 +50376,7 @@ var init_plugin_admission = __esm(() => {
|
|
|
50160
50376
|
|
|
50161
50377
|
// src/lib/plugin-discovery.ts
|
|
50162
50378
|
import { closeSync as closeSync12, constants as constants9, fstatSync as fstatSync12, lstatSync as lstatSync16, openSync as openSync12, opendirSync as opendirSync3, readSync as readSync8 } from "fs";
|
|
50163
|
-
import { basename as
|
|
50379
|
+
import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute13, join as join25, resolve as resolve15 } from "path";
|
|
50164
50380
|
function validateManagedPluginWitnesses(value) {
|
|
50165
50381
|
pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
|
|
50166
50382
|
const seen = new Set;
|
|
@@ -50169,15 +50385,15 @@ function validateManagedPluginWitnesses(value) {
|
|
|
50169
50385
|
pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
|
|
50170
50386
|
seen.add(item.bindingId);
|
|
50171
50387
|
pluginText(item.storeRoot);
|
|
50172
|
-
pluginNeed(
|
|
50388
|
+
pluginNeed(isAbsolute13(item.storeRoot) && resolve15(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
|
|
50173
50389
|
}
|
|
50174
50390
|
}
|
|
50175
50391
|
function safe3(path) {
|
|
50176
50392
|
pluginText(path);
|
|
50177
|
-
pluginNeed(
|
|
50178
|
-
for (let at = path;; at =
|
|
50393
|
+
pluginNeed(isAbsolute13(path) && resolve15(path) === path, "Invalid plugin registry path");
|
|
50394
|
+
for (let at = path;; at = dirname14(at)) {
|
|
50179
50395
|
pluginNeed(!lstatSync16(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
|
|
50180
|
-
if (at ===
|
|
50396
|
+
if (at === dirname14(at))
|
|
50181
50397
|
break;
|
|
50182
50398
|
}
|
|
50183
50399
|
}
|
|
@@ -50227,7 +50443,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
50227
50443
|
seen.add(target.pluginId);
|
|
50228
50444
|
const rows = plugins[target.pluginId];
|
|
50229
50445
|
pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
|
|
50230
|
-
const [name, market] = target.pluginId.split("@"), cacheRoot = join25(
|
|
50446
|
+
const [name, market] = target.pluginId.split("@"), cacheRoot = join25(dirname14(path), "cache", market, name);
|
|
50231
50447
|
const scopes = new Set, approvals = new Map, currentFiles = new Map;
|
|
50232
50448
|
plugins[target.pluginId] = rows.map((row) => {
|
|
50233
50449
|
pluginNeed(pluginObject(row), "Invalid managed plugin registration");
|
|
@@ -50243,7 +50459,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
50243
50459
|
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join25(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
50244
50460
|
const approval = (producer) => {
|
|
50245
50461
|
pluginText(producer);
|
|
50246
|
-
const digest = `sha256:${
|
|
50462
|
+
const digest = `sha256:${basename7(producer)}`;
|
|
50247
50463
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest);
|
|
50248
50464
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
50249
50465
|
if (!verified.has(producer)) {
|
|
@@ -50307,37 +50523,37 @@ var init_plugin_discovery = __esm(() => {
|
|
|
50307
50523
|
});
|
|
50308
50524
|
|
|
50309
50525
|
// src/lib/claude-marketplace-registry.ts
|
|
50310
|
-
import { createHash as
|
|
50526
|
+
import { createHash as createHash16 } from "crypto";
|
|
50311
50527
|
import { closeSync as closeSync13, constants as constants10, fstatSync as fstatSync13, lstatSync as lstatSync17, openSync as openSync13, readSync as readSync9 } from "fs";
|
|
50312
|
-
import { basename as
|
|
50313
|
-
function
|
|
50528
|
+
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute14, resolve as resolve16 } from "path";
|
|
50529
|
+
function need7(value, reason2) {
|
|
50314
50530
|
if (!value)
|
|
50315
|
-
throw new Error(`Claude marketplace registry ${
|
|
50531
|
+
throw new Error(`Claude marketplace registry ${reason2}`);
|
|
50316
50532
|
}
|
|
50317
50533
|
function absolutePath2(value) {
|
|
50318
|
-
|
|
50534
|
+
need7(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute14(value) && resolve16(value) === value, "requires a normalized absolute path");
|
|
50319
50535
|
}
|
|
50320
50536
|
function parents2(path) {
|
|
50321
50537
|
const result = [];
|
|
50322
|
-
for (let at =
|
|
50538
|
+
for (let at = dirname15(path);; at = dirname15(at)) {
|
|
50323
50539
|
const stat2 = lstatSync17(at, { bigint: true });
|
|
50324
|
-
|
|
50540
|
+
need7(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
50325
50541
|
result.push([at, stat2]);
|
|
50326
|
-
if (at ===
|
|
50542
|
+
if (at === dirname15(at))
|
|
50327
50543
|
return result;
|
|
50328
50544
|
}
|
|
50329
50545
|
}
|
|
50330
50546
|
function readRegistry2(path, budget2) {
|
|
50331
50547
|
absolutePath2(path);
|
|
50332
|
-
|
|
50333
|
-
|
|
50548
|
+
need7(basename8(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
50549
|
+
need7(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
|
|
50334
50550
|
const ancestors2 = parents2(path), initial = lstatSync17(path, { bigint: true });
|
|
50335
|
-
|
|
50336
|
-
|
|
50551
|
+
need7(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
50552
|
+
need7(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
|
|
50337
50553
|
const fd = openSync13(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
|
|
50338
50554
|
try {
|
|
50339
50555
|
const opened = fstatSync13(fd, { bigint: true });
|
|
50340
|
-
|
|
50556
|
+
need7(opened.isFile() && sameFile2(initial, opened), "changed during open");
|
|
50341
50557
|
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
50342
50558
|
let length = 0;
|
|
50343
50559
|
while (length < bytes.length) {
|
|
@@ -50347,10 +50563,10 @@ function readRegistry2(path, budget2) {
|
|
|
50347
50563
|
length += count;
|
|
50348
50564
|
}
|
|
50349
50565
|
const after = fstatSync13(fd, { bigint: true }), current = lstatSync17(path, { bigint: true });
|
|
50350
|
-
|
|
50566
|
+
need7(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
|
|
50351
50567
|
for (const [ancestor, before] of ancestors2) {
|
|
50352
50568
|
const now = lstatSync17(ancestor, { bigint: true });
|
|
50353
|
-
|
|
50569
|
+
need7(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
50354
50570
|
}
|
|
50355
50571
|
budget2.remaining -= length;
|
|
50356
50572
|
try {
|
|
@@ -50370,7 +50586,7 @@ function parse11(text2) {
|
|
|
50370
50586
|
at++;
|
|
50371
50587
|
};
|
|
50372
50588
|
function string5() {
|
|
50373
|
-
|
|
50589
|
+
need7(text2[at] === '"', "contains invalid JSON");
|
|
50374
50590
|
const start = at++;
|
|
50375
50591
|
while (at < text2.length) {
|
|
50376
50592
|
const character = text2[at++];
|
|
@@ -50381,7 +50597,7 @@ function parse11(text2) {
|
|
|
50381
50597
|
} catch {
|
|
50382
50598
|
throw new Error("Claude marketplace registry contains invalid JSON string");
|
|
50383
50599
|
}
|
|
50384
|
-
|
|
50600
|
+
need7(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
|
|
50385
50601
|
return value2;
|
|
50386
50602
|
}
|
|
50387
50603
|
if (character === "\\")
|
|
@@ -50390,7 +50606,7 @@ function parse11(text2) {
|
|
|
50390
50606
|
throw new Error("Claude marketplace registry contains an unterminated JSON string");
|
|
50391
50607
|
}
|
|
50392
50608
|
function value(depth) {
|
|
50393
|
-
|
|
50609
|
+
need7(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
50394
50610
|
space();
|
|
50395
50611
|
const character = text2[at];
|
|
50396
50612
|
if (character === '"')
|
|
@@ -50404,17 +50620,17 @@ function parse11(text2) {
|
|
|
50404
50620
|
if (object7) {
|
|
50405
50621
|
space();
|
|
50406
50622
|
const key = string5();
|
|
50407
|
-
|
|
50623
|
+
need7(!keys.has(key), "contains a duplicate JSON key");
|
|
50408
50624
|
keys.add(key);
|
|
50409
50625
|
space();
|
|
50410
|
-
|
|
50626
|
+
need7(text2[at++] === ":", "contains invalid JSON");
|
|
50411
50627
|
entries.push([key, value(depth + 1)]);
|
|
50412
50628
|
} else
|
|
50413
50629
|
items.push(value(depth + 1));
|
|
50414
50630
|
space();
|
|
50415
50631
|
if (text2[at] === end)
|
|
50416
50632
|
break;
|
|
50417
|
-
|
|
50633
|
+
need7(text2[at++] === ",", "contains invalid JSON");
|
|
50418
50634
|
}
|
|
50419
50635
|
at++;
|
|
50420
50636
|
return object7 ? { kind: "object", entries } : { kind: "array", items };
|
|
@@ -50426,64 +50642,64 @@ function parse11(text2) {
|
|
|
50426
50642
|
}
|
|
50427
50643
|
numberPattern.lastIndex = at;
|
|
50428
50644
|
const number5 = numberPattern.exec(text2);
|
|
50429
|
-
|
|
50645
|
+
need7(number5, "contains invalid JSON");
|
|
50430
50646
|
at += number5[0].length;
|
|
50431
50647
|
return { kind: "number", value: number5[0] };
|
|
50432
50648
|
}
|
|
50433
50649
|
const root = value(0);
|
|
50434
50650
|
space();
|
|
50435
|
-
|
|
50436
|
-
|
|
50651
|
+
need7(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
|
|
50652
|
+
need7(root.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
|
|
50437
50653
|
return root;
|
|
50438
50654
|
}
|
|
50439
50655
|
function exactKeys(value, keys) {
|
|
50440
50656
|
return value?.kind === "object" && value.entries.length === keys.length && value.entries.every(([key]) => keys.includes(key));
|
|
50441
50657
|
}
|
|
50442
50658
|
function textField(value) {
|
|
50443
|
-
|
|
50659
|
+
need7(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
|
|
50444
50660
|
return value.value;
|
|
50445
50661
|
}
|
|
50446
50662
|
function normalizeRow(row, version2 = 1) {
|
|
50447
50663
|
if (!exactKeys(row, ["source", "installLocation", "lastUpdated"])) {
|
|
50448
50664
|
if (version2 !== 2 || !exactKeys(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
|
|
50449
50665
|
return;
|
|
50450
|
-
const autoUpdate =
|
|
50451
|
-
|
|
50666
|
+
const autoUpdate = field2(row, "autoUpdate");
|
|
50667
|
+
need7(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
|
|
50452
50668
|
}
|
|
50453
|
-
const source =
|
|
50669
|
+
const source = field2(row, "source");
|
|
50454
50670
|
if (source?.kind !== "object")
|
|
50455
50671
|
return;
|
|
50456
|
-
const type =
|
|
50672
|
+
const type = field2(source, "source");
|
|
50457
50673
|
if (type?.kind !== "string" || !["github", "directory"].includes(type.value))
|
|
50458
50674
|
return;
|
|
50459
50675
|
const location = type.value === "github" ? "repo" : "path";
|
|
50460
50676
|
if (!exactKeys(source, ["source", location]))
|
|
50461
50677
|
return;
|
|
50462
|
-
const sourceLocation = textField(
|
|
50678
|
+
const sourceLocation = textField(field2(source, location));
|
|
50463
50679
|
if (type.value === "directory")
|
|
50464
50680
|
absolutePath2(sourceLocation);
|
|
50465
|
-
absolutePath2(textField(
|
|
50466
|
-
const updated = textField(
|
|
50467
|
-
|
|
50681
|
+
absolutePath2(textField(field2(row, "installLocation")));
|
|
50682
|
+
const updated = textField(field2(row, "lastUpdated"));
|
|
50683
|
+
need7(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
|
|
50468
50684
|
const millis = Date.parse(updated);
|
|
50469
|
-
|
|
50685
|
+
need7(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
|
|
50470
50686
|
row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
|
|
50471
50687
|
}
|
|
50472
50688
|
function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
50473
50689
|
const value = parse11(readRegistry2(path, budget2));
|
|
50474
50690
|
for (const [, row] of value.entries)
|
|
50475
50691
|
normalizeRow(row);
|
|
50476
|
-
const sha2562 =
|
|
50692
|
+
const sha2562 = createHash16("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
50477
50693
|
return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
|
|
50478
50694
|
}
|
|
50479
50695
|
function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
50480
50696
|
const value = parse11(readRegistry2(path, budget2));
|
|
50481
50697
|
for (const [, row] of value.entries)
|
|
50482
50698
|
normalizeRow(row, 2);
|
|
50483
|
-
const sha2562 =
|
|
50699
|
+
const sha2562 = createHash16("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
|
|
50484
50700
|
return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
|
|
50485
50701
|
}
|
|
50486
|
-
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS, sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs,
|
|
50702
|
+
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS, sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs, field2 = (object7, key) => object7.entries.find(([name]) => name === key)?.[1];
|
|
50487
50703
|
var init_claude_marketplace_registry = __esm(() => {
|
|
50488
50704
|
CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
50489
50705
|
});
|
|
@@ -50502,10 +50718,10 @@ var init_codex_hook_additions_review = __esm(() => {
|
|
|
50502
50718
|
});
|
|
50503
50719
|
|
|
50504
50720
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
50505
|
-
import { createHash as
|
|
50721
|
+
import { createHash as createHash17 } from "crypto";
|
|
50506
50722
|
function assertCodexHookDiscoveryRecovery(binding, witness) {
|
|
50507
50723
|
const proof = proofs2.get(witness);
|
|
50508
|
-
|
|
50724
|
+
need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha3(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
50509
50725
|
unchanged2(proof.before);
|
|
50510
50726
|
unchanged2(proof.current);
|
|
50511
50727
|
proof.recheckAdditions();
|
|
@@ -50514,10 +50730,10 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
|
|
|
50514
50730
|
if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
|
|
50515
50731
|
return false;
|
|
50516
50732
|
assertCodexHookDiscoveryRecovery(binding, witness);
|
|
50517
|
-
|
|
50733
|
+
need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
50518
50734
|
return true;
|
|
50519
50735
|
}
|
|
50520
|
-
var sha3 = (text2) =>
|
|
50736
|
+
var sha3 = (text2) => createHash17("sha256").update(text2).digest("hex"), fields, proofs2;
|
|
50521
50737
|
var init_codex_hook_discovery_recovery = __esm(() => {
|
|
50522
50738
|
init_codex_hook_trust_files();
|
|
50523
50739
|
init_codex_hook_trust_layout();
|
|
@@ -50528,10 +50744,18 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
50528
50744
|
});
|
|
50529
50745
|
|
|
50530
50746
|
// src/lib/agent-discovery.ts
|
|
50531
|
-
import { createHash as
|
|
50747
|
+
import { createHash as createHash18 } from "crypto";
|
|
50532
50748
|
import { lstatSync as lstatSync18, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync5 } from "fs";
|
|
50533
|
-
import { basename as
|
|
50749
|
+
import { basename as basename9, dirname as dirname16, isAbsolute as isAbsolute15, join as join26, resolve as resolve17, sep as sep6 } from "path";
|
|
50534
50750
|
import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
|
|
50751
|
+
function discoveryExecutable(agent) {
|
|
50752
|
+
const command = DISCOVERY_RUNTIME_COMMANDS[agent];
|
|
50753
|
+
const found = command ? Bun.which(command) : null;
|
|
50754
|
+
if (!command || !found)
|
|
50755
|
+
return null;
|
|
50756
|
+
const path = resolve17(found), target = realpathOrNull(path);
|
|
50757
|
+
return target === null ? null : { command, path, target };
|
|
50758
|
+
}
|
|
50535
50759
|
function parseConfig(text2, path, toml = false) {
|
|
50536
50760
|
try {
|
|
50537
50761
|
const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
|
|
@@ -50543,12 +50767,12 @@ function parseConfig(text2, path, toml = false) {
|
|
|
50543
50767
|
}
|
|
50544
50768
|
}
|
|
50545
50769
|
function safe4(path) {
|
|
50546
|
-
if (!
|
|
50770
|
+
if (!isAbsolute15(path) || path.includes("\x00"))
|
|
50547
50771
|
throw new Error("Expected an absolute native discovery path");
|
|
50548
|
-
for (let cursor = path;; cursor =
|
|
50772
|
+
for (let cursor = path;; cursor = dirname16(cursor)) {
|
|
50549
50773
|
if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
50550
50774
|
throw new Error(`Refusing symlink native discovery input: ${cursor}`);
|
|
50551
|
-
if (
|
|
50775
|
+
if (dirname16(cursor) === cursor)
|
|
50552
50776
|
break;
|
|
50553
50777
|
}
|
|
50554
50778
|
}
|
|
@@ -50567,7 +50791,7 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
|
|
|
50567
50791
|
const object7 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
|
|
50568
50792
|
if (!object7 || typeof object7 !== "object" || Array.isArray(object7))
|
|
50569
50793
|
throw new Error("Expected native discovery configuration object");
|
|
50570
|
-
return digest(JSON.stringify(Object.fromEntries(fields2.map((
|
|
50794
|
+
return digest(JSON.stringify(Object.fromEntries(fields2.map((field3) => [field3, object7[field3] ?? null]))));
|
|
50571
50795
|
}
|
|
50572
50796
|
function isSupersededSettingsProjection(agent, configPath, source) {
|
|
50573
50797
|
if (agent === "sumi")
|
|
@@ -50612,6 +50836,14 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
|
|
|
50612
50836
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
50613
50837
|
return sha2562;
|
|
50614
50838
|
}
|
|
50839
|
+
if (source.hashMode === "claude-marketplace-entry-v1") {
|
|
50840
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256) || changes?.has(source.path) || !claudeMarketplaceEntrySourceValid(source))
|
|
50841
|
+
throw new Error("Claude marketplace entry witnesses require an exact reviewed entry without synthetic changes");
|
|
50842
|
+
const sha2562 = captureClaudeMarketplaceEntry(source.path, source.marketplace, source.plugin, budget2).sha256;
|
|
50843
|
+
if (sha2562 !== source.sha256)
|
|
50844
|
+
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
50845
|
+
return sha2562;
|
|
50846
|
+
}
|
|
50615
50847
|
if (source.hashMode === "claude-plugin-registry") {
|
|
50616
50848
|
if (source.format !== undefined || source.fields !== undefined || !source.managedPlugins || changes?.has(source.path))
|
|
50617
50849
|
throw new Error("Managed plugin registry witnesses require verified native registrations");
|
|
@@ -50649,7 +50881,7 @@ function absentCodexSkillRoots(binding) {
|
|
|
50649
50881
|
throw new Error("Invalid disabled Codex discovery proof");
|
|
50650
50882
|
if (binding.method !== "reviewed" || controls.every((control) => lstatSync18(control.pluginParent, { throwIfNoEntry: false })))
|
|
50651
50883
|
return [];
|
|
50652
|
-
const cache =
|
|
50884
|
+
const cache = dirname16(dirname16(controls[0].pluginParent)), config2 = join26(dirname16(dirname16(cache)), "config.toml");
|
|
50653
50885
|
const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
50654
50886
|
if (!source || projected(source) !== source.sha256)
|
|
50655
50887
|
throw new Error("Missing current disabled Codex configuration witness");
|
|
@@ -50657,7 +50889,7 @@ function absentCodexSkillRoots(binding) {
|
|
|
50657
50889
|
return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
|
|
50658
50890
|
}
|
|
50659
50891
|
function codexDirectHookSelects(cache, root) {
|
|
50660
|
-
const codex =
|
|
50892
|
+
const codex = dirname16(dirname16(cache)), config2 = Bun.TOML.parse(read(join26(codex, "config.toml")) ?? "");
|
|
50661
50893
|
const hooks = read(join26(codex, "hooks.json"));
|
|
50662
50894
|
if (hooks !== null)
|
|
50663
50895
|
hashNativeJsonControls(hooks);
|
|
@@ -50670,7 +50902,7 @@ function retiredCodexRoots(binding) {
|
|
|
50670
50902
|
const controls = binding.codexDisabledPluginSkills;
|
|
50671
50903
|
if (binding.agent !== "codex" || binding.method !== "reviewed" || !Array.isArray(controls) || !controls.length || !Array.isArray(proof.roots) || proof.roots.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.roots).size !== proof.roots.length || !Array.isArray(proof.directories) || proof.parents !== undefined && (!Array.isArray(proof.parents) || proof.parents.length > AGENT_POLICY_LIMITS.discoveryRoots || new Set(proof.parents).size !== proof.parents.length) || !proof.roots.length && !proof.parents?.length)
|
|
50672
50904
|
throw new Error("Invalid retired Codex materialization proof");
|
|
50673
|
-
const cache =
|
|
50905
|
+
const cache = dirname16(dirname16(controls[0].pluginParent)), config2 = join26(dirname16(dirname16(cache)), "config.toml");
|
|
50674
50906
|
const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
50675
50907
|
if (!source || projected(source) !== source.sha256)
|
|
50676
50908
|
throw new Error("Missing current retired Codex configuration witness");
|
|
@@ -50701,7 +50933,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
50701
50933
|
safe4(root);
|
|
50702
50934
|
if (lstatSync18(root, { throwIfNoEntry: false }))
|
|
50703
50935
|
continue;
|
|
50704
|
-
const claude =
|
|
50936
|
+
const claude = dirname16(dirname16(cache)), settings = join26(claude, "settings.json"), registry2 = join26(claude, "plugins/installed_plugins.json");
|
|
50705
50937
|
const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
|
|
50706
50938
|
const configSource = full(settings), registrySource = full(registry2);
|
|
50707
50939
|
if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
|
|
@@ -50718,7 +50950,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
50718
50950
|
if (!Array.isArray(rows) || rows.length !== 1 || rows[0]?.scope !== "user" || typeof rows[0]?.installPath !== "string")
|
|
50719
50951
|
continue;
|
|
50720
50952
|
const active = rows[0].installPath;
|
|
50721
|
-
if (rows[0].version !==
|
|
50953
|
+
if (rows[0].version !== basename9(active) || resolve17(active) !== active || dirname16(active) !== dirname16(root) || active === root || !lstatSync18(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync5(active) !== active)
|
|
50722
50954
|
continue;
|
|
50723
50955
|
const activeManifest = full(join26(active, ".claude-plugin/plugin.json"));
|
|
50724
50956
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
@@ -50769,7 +51001,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
50769
51001
|
assertMarketplaceBinding(binding, source);
|
|
50770
51002
|
if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
|
|
50771
51003
|
throw new Error("Managed Claude registry witnesses cannot apply to another agent");
|
|
50772
|
-
if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((
|
|
51004
|
+
if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((field3) => typeof field3 !== "string" || !field3)))
|
|
50773
51005
|
throw new Error("Invalid native discovery projection");
|
|
50774
51006
|
if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
50775
51007
|
throw new Error("Invalid native discovery digest");
|
|
@@ -50799,13 +51031,13 @@ function codexInstallationRoots(binding) {
|
|
|
50799
51031
|
return [];
|
|
50800
51032
|
if (binding.agent !== "codex" || binding.method !== "reviewed" || !supportsCodexNativeCapability(proof.version, "installed-plugin-review") || !/^[a-f0-9]{64}$/.test(proof.catalogSha256) || !Array.isArray(proof.plugins) || !proof.plugins.length)
|
|
50801
51033
|
throw new Error("Invalid native installation input proof");
|
|
50802
|
-
const cache =
|
|
50803
|
-
const config2 = join26(
|
|
51034
|
+
const cache = dirname16(dirname16(proof.plugins[0].pluginParent));
|
|
51035
|
+
const config2 = join26(dirname16(dirname16(cache)), "config.toml"), home = dirname16(dirname16(dirname16(cache)));
|
|
50804
51036
|
const configSource = binding.sources.find((source) => source.path === config2 && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
|
|
50805
51037
|
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join26(home, path));
|
|
50806
|
-
if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep6) || input2.sourceRoot.startsWith(root + sep6)) || binding.sources.some((source) =>
|
|
51038
|
+
if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep6) || input2.sourceRoot.startsWith(root + sep6)) || binding.sources.some((source) => basename9(source.path) === "config.toml" && (source.path === input2.sourceRoot || source.path.startsWith(input2.sourceRoot + sep6)))))
|
|
50807
51039
|
throw new Error("Native installation input overlaps configuration or loading roots");
|
|
50808
|
-
if (proof.plugins.some((input2) =>
|
|
51040
|
+
if (proof.plugins.some((input2) => dirname16(dirname16(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join26(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
|
|
50809
51041
|
throw new Error("Missing native installation input source witness");
|
|
50810
51042
|
return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
|
|
50811
51043
|
const text2 = read(path);
|
|
@@ -50815,16 +51047,18 @@ function codexInstallationRoots(binding) {
|
|
|
50815
51047
|
});
|
|
50816
51048
|
}
|
|
50817
51049
|
function assertMarketplaceBinding(binding, source) {
|
|
50818
|
-
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" ||
|
|
51050
|
+
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json"))))
|
|
50819
51051
|
throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
|
|
50820
|
-
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" ||
|
|
51052
|
+
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename9(source.path) !== "sumi.json"))
|
|
50821
51053
|
throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
|
|
50822
|
-
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" ||
|
|
51054
|
+
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
|
|
50823
51055
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
50824
|
-
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" ||
|
|
51056
|
+
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4")) && (binding.agent !== "claude" || binding.method !== "reviewed" || basename9(source.path) !== "settings.json"))
|
|
50825
51057
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
50826
51058
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
50827
51059
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
51060
|
+
if (source.hashMode === "claude-marketplace-entry-v1" && (binding.agent !== "claude" || binding.method !== "reviewed" || !claudeMarketplaceEntrySourceValid(source)))
|
|
51061
|
+
throw new Error("Claude marketplace entry witnesses require explicit reviewed Claude discovery of one named entry");
|
|
50828
51062
|
}
|
|
50829
51063
|
function agentDiscoveryConfigPath(home, agent) {
|
|
50830
51064
|
if (agent === "sumi")
|
|
@@ -50832,10 +51066,10 @@ function agentDiscoveryConfigPath(home, agent) {
|
|
|
50832
51066
|
return join26(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
|
|
50833
51067
|
}
|
|
50834
51068
|
function resolveAgentDiscovery(options) {
|
|
50835
|
-
const
|
|
51069
|
+
const canonical8 = options.canonical ?? resolve17, home = resolve17(options.home), agent = options.agent;
|
|
50836
51070
|
const sources = [], roots = new Set, builtinNames = [];
|
|
50837
51071
|
const witness = (path, format, fields2, hashMode) => {
|
|
50838
|
-
const source = { path:
|
|
51072
|
+
const source = { path: canonical8(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
|
|
50839
51073
|
source.sha256 = projected(source);
|
|
50840
51074
|
sources.push(source);
|
|
50841
51075
|
return read(source.path);
|
|
@@ -50857,13 +51091,13 @@ function resolveAgentDiscovery(options) {
|
|
|
50857
51091
|
unresolved("JSONC configuration requires a supported format adapter");
|
|
50858
51092
|
for (const root of [directory, join26(home, ".claude"), join26(home, ".agents")])
|
|
50859
51093
|
for (const name of ["skill", "skills"])
|
|
50860
|
-
roots.add(
|
|
51094
|
+
roots.add(canonical8(join26(root, name)));
|
|
50861
51095
|
if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
|
|
50862
51096
|
unresolved("skills must be a string array");
|
|
50863
51097
|
for (const value of config2.skills ?? []) {
|
|
50864
|
-
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(
|
|
51098
|
+
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute15(value) || value.startsWith("~/")))
|
|
50865
51099
|
unresolved("remote or relative skill sources need a dedicated discovery adapter");
|
|
50866
|
-
roots.add(
|
|
51100
|
+
roots.add(canonical8(value.startsWith("~/") ? join26(home, value.slice(2)) : value));
|
|
50867
51101
|
}
|
|
50868
51102
|
for (const key of ["plugin", "plugins"])
|
|
50869
51103
|
if (config2[key] !== undefined && !Array.isArray(config2[key]))
|
|
@@ -50902,23 +51136,23 @@ function resolveAgentDiscovery(options) {
|
|
|
50902
51136
|
continue;
|
|
50903
51137
|
if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
|
|
50904
51138
|
unresolved("user-specific tilde expansion requires a separate discovery adapter");
|
|
50905
|
-
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join26(home, normalized.slice(2)) :
|
|
51139
|
+
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join26(home, normalized.slice(2)) : resolve17(home, ".hermes", normalized);
|
|
50906
51140
|
safe4(path);
|
|
50907
51141
|
roots.add(path);
|
|
50908
51142
|
}
|
|
50909
51143
|
}
|
|
50910
51144
|
if (agent === "gemini") {
|
|
50911
|
-
const executable =
|
|
51145
|
+
const executable = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
|
|
50912
51146
|
if (executable) {
|
|
50913
51147
|
let packageRoot;
|
|
50914
|
-
for (let directory =
|
|
51148
|
+
for (let directory = dirname16(executable.target), depth = 0;depth < 8; directory = dirname16(directory), depth++) {
|
|
50915
51149
|
const path = join26(directory, "package.json"), raw = read(path);
|
|
50916
51150
|
if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
|
|
50917
51151
|
packageRoot = directory;
|
|
50918
51152
|
witness(path);
|
|
50919
51153
|
break;
|
|
50920
51154
|
}
|
|
50921
|
-
if (
|
|
51155
|
+
if (dirname16(directory) === directory)
|
|
50922
51156
|
break;
|
|
50923
51157
|
}
|
|
50924
51158
|
if (!packageRoot)
|
|
@@ -50941,11 +51175,11 @@ function resolveAgentDiscovery(options) {
|
|
|
50941
51175
|
if (retained.agent !== agent || retained.method !== "reviewed")
|
|
50942
51176
|
unresolved("invalid retained review");
|
|
50943
51177
|
verifyAgentDiscovery(retained);
|
|
50944
|
-
if (!retained.sources.some((source) => source.path ===
|
|
51178
|
+
if (!retained.sources.some((source) => source.path === canonical8(configPath) && source.format === undefined && source.fields === undefined))
|
|
50945
51179
|
unresolved("retained review is missing the full agent configuration source");
|
|
50946
|
-
if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !==
|
|
51180
|
+
if (retained.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical8(configPath)))
|
|
50947
51181
|
unresolved("retained settings witness names another configuration source");
|
|
50948
|
-
const covered = supersedesSettingsProjection(agent, retained.sources,
|
|
51182
|
+
const covered = supersedesSettingsProjection(agent, retained.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
|
|
50949
51183
|
if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual4(saved, source))) || [...roots].some((root) => !retained.roots.includes(root)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
|
|
50950
51184
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
50951
51185
|
return retained;
|
|
@@ -50957,15 +51191,15 @@ function resolveAgentDiscovery(options) {
|
|
|
50957
51191
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
50958
51192
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
50959
51193
|
verifyAgentDiscovery(supplied);
|
|
50960
|
-
if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !==
|
|
51194
|
+
if (review.sources.some((source) => (source.hashMode === "sumi-settings-v1" || source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4")))) && source.path !== canonical8(configPath)))
|
|
50961
51195
|
throw new Error("Semantic settings witnesses must name the configured agent configuration source");
|
|
50962
|
-
if (!review.sources.some((source) => source.path ===
|
|
51196
|
+
if (!review.sources.some((source) => source.path === canonical8(configPath)))
|
|
50963
51197
|
throw new Error("Discovery review must include the agent configuration source");
|
|
50964
|
-
const reviewedSources = supersedesSettingsProjection(agent, review.sources,
|
|
51198
|
+
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
|
|
50965
51199
|
const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
|
|
50966
|
-
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" ||
|
|
51200
|
+
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename9(source.path) !== "plugin.json" || !source.path.endsWith(join26(sep6, ".claude-plugin", "plugin.json")))
|
|
50967
51201
|
return source;
|
|
50968
|
-
const pluginRoot =
|
|
51202
|
+
const pluginRoot = dirname16(dirname16(source.path)), hooksPath = join26(pluginRoot, "hooks/hooks.json");
|
|
50969
51203
|
const hookStat = lstatSync18(hooksPath, { throwIfNoEntry: false });
|
|
50970
51204
|
const text2 = read(source.path);
|
|
50971
51205
|
if (text2 === null)
|
|
@@ -50980,13 +51214,13 @@ function resolveAgentDiscovery(options) {
|
|
|
50980
51214
|
if (manifest.hooks !== undefined) {
|
|
50981
51215
|
if (typeof manifest.hooks !== "string")
|
|
50982
51216
|
throw new Error("Reviewed Claude plugin manifest has an unsupported hooks target");
|
|
50983
|
-
const declaredHookPath =
|
|
51217
|
+
const declaredHookPath = resolve17(pluginRoot, manifest.hooks);
|
|
50984
51218
|
if (!declaredHookPath.startsWith(pluginRoot + sep6))
|
|
50985
51219
|
throw new Error("Reviewed Claude plugin hooks target escapes its root");
|
|
50986
51220
|
reviewedHookPaths.add(declaredHookPath);
|
|
50987
51221
|
}
|
|
50988
51222
|
for (const hooksFile of reviewedHookPaths)
|
|
50989
|
-
if (!review.sources.some((hook) => hook.path ===
|
|
51223
|
+
if (!review.sources.some((hook) => hook.path === canonical8(hooksFile) && hook.sha256 !== null && hook.format === undefined && hook.fields === undefined && hook.managedPlugins === undefined && (hook.hashMode === undefined || hook.hashMode === "bytes")))
|
|
50990
51224
|
throw new Error("Reviewed Claude plugin manifest requires separately reviewed exact hook file sources");
|
|
50991
51225
|
return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
|
|
50992
51226
|
});
|
|
@@ -50995,7 +51229,7 @@ function resolveAgentDiscovery(options) {
|
|
|
50995
51229
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
|
|
50996
51230
|
}
|
|
50997
51231
|
function plugin(root) {
|
|
50998
|
-
root =
|
|
51232
|
+
root = canonical8(root);
|
|
50999
51233
|
safe4(root);
|
|
51000
51234
|
const manifestPath = join26(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
51001
51235
|
const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
|
|
@@ -51018,16 +51252,16 @@ function resolveAgentDiscovery(options) {
|
|
|
51018
51252
|
if (agent === "claude")
|
|
51019
51253
|
roots.add(join26(root, "skills"));
|
|
51020
51254
|
for (const value of declared) {
|
|
51021
|
-
const path =
|
|
51255
|
+
const path = resolve17(root, value);
|
|
51022
51256
|
if (path !== root && !path.startsWith(root + sep6))
|
|
51023
51257
|
unresolved("plugin skill path escapes its root");
|
|
51024
|
-
roots.add(path.endsWith(`${sep6}SKILL.md`) ?
|
|
51258
|
+
roots.add(path.endsWith(`${sep6}SKILL.md`) ? dirname16(path) : path);
|
|
51025
51259
|
}
|
|
51026
51260
|
}
|
|
51027
51261
|
if (agent === "claude") {
|
|
51028
51262
|
const registrations = witness(join26(home, ".claude/plugins/installed_plugins.json"));
|
|
51029
51263
|
const installed = registrations === null ? {} : parseConfig(registrations, join26(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
51030
|
-
const commands =
|
|
51264
|
+
const commands = canonical8(join26(home, ".claude/commands"));
|
|
51031
51265
|
safe4(commands);
|
|
51032
51266
|
if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
51033
51267
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
@@ -51049,7 +51283,7 @@ function resolveAgentDiscovery(options) {
|
|
|
51049
51283
|
unresolved("unsupported plugin enablement");
|
|
51050
51284
|
const split = id.lastIndexOf("@"), name = id.slice(0, split), marketplace = id.slice(split + 1);
|
|
51051
51285
|
const market = config2.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
|
|
51052
|
-
if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !
|
|
51286
|
+
if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute15(market.source))
|
|
51053
51287
|
unresolved("enabled plugin marketplace is not an explicit local source");
|
|
51054
51288
|
const catalogText = witness(join26(market.source, ".agents/plugins/marketplace.json"));
|
|
51055
51289
|
if (catalogText === null)
|
|
@@ -51057,7 +51291,7 @@ function resolveAgentDiscovery(options) {
|
|
|
51057
51291
|
const catalog = parseConfig(catalogText, join26(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
51058
51292
|
if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
|
|
51059
51293
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
51060
|
-
plugin(
|
|
51294
|
+
plugin(resolve17(market.source, matches[0].source.path));
|
|
51061
51295
|
}
|
|
51062
51296
|
} else if (agent === "opencode") {
|
|
51063
51297
|
if (witness(join26(home, ".config/opencode/opencode.jsonc")) !== null || witness(join26(home, ".config/opencode/config.json")) !== null)
|
|
@@ -51065,7 +51299,7 @@ function resolveAgentDiscovery(options) {
|
|
|
51065
51299
|
if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
|
|
51066
51300
|
unresolved("external plugin or remote skill source");
|
|
51067
51301
|
for (const path of config2.skills?.paths ?? []) {
|
|
51068
|
-
if (typeof path !== "string" || !
|
|
51302
|
+
if (typeof path !== "string" || !isAbsolute15(path))
|
|
51069
51303
|
unresolved("relative or malformed added skill root");
|
|
51070
51304
|
roots.add(path);
|
|
51071
51305
|
}
|
|
@@ -51074,7 +51308,7 @@ function resolveAgentDiscovery(options) {
|
|
|
51074
51308
|
if (lstatSync18(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
51075
51309
|
unresolved("additional local plugin hooks require review");
|
|
51076
51310
|
} else if (agent === "sumi") {
|
|
51077
|
-
if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !==
|
|
51311
|
+
if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical8(configPath) && source.path !== canonical8(join26(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
|
|
51078
51312
|
unresolved("external or foreign local plugins require review");
|
|
51079
51313
|
} else if (agent === "hermes") {
|
|
51080
51314
|
for (const directory of [join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")]) {
|
|
@@ -51104,9 +51338,15 @@ function resolveAgentDiscovery(options) {
|
|
|
51104
51338
|
roots.add(join26(root, "skills"));
|
|
51105
51339
|
}
|
|
51106
51340
|
}
|
|
51107
|
-
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")].map((path) =>
|
|
51341
|
+
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")].map((path) => canonical8(path))) } : {} };
|
|
51108
51342
|
}
|
|
51109
|
-
var
|
|
51343
|
+
var DISCOVERY_RUNTIME_COMMANDS, realpathOrNull = (path) => {
|
|
51344
|
+
try {
|
|
51345
|
+
return realpathSync5(path);
|
|
51346
|
+
} catch {
|
|
51347
|
+
return null;
|
|
51348
|
+
}
|
|
51349
|
+
}, digest = (text2) => createHash18("sha256").update(text2).digest("hex");
|
|
51110
51350
|
var init_agent_discovery = __esm(() => {
|
|
51111
51351
|
init_sumi_settings_witness();
|
|
51112
51352
|
init_agent_policy_limits();
|
|
@@ -51118,6 +51358,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
51118
51358
|
init_plugin_discovery();
|
|
51119
51359
|
init_plugin_admission();
|
|
51120
51360
|
init_claude_marketplace_registry();
|
|
51361
|
+
init_claude_marketplace_entry_witness();
|
|
51121
51362
|
init_claude_settings_witness();
|
|
51122
51363
|
init_codex_hook_discovery_recovery();
|
|
51123
51364
|
init_codex_settings_witness();
|
|
@@ -51126,14 +51367,15 @@ var init_agent_discovery = __esm(() => {
|
|
|
51126
51367
|
init_native_discovery_roots();
|
|
51127
51368
|
init_codex_native_compatibility();
|
|
51128
51369
|
init_agent_discovery_directories();
|
|
51370
|
+
DISCOVERY_RUNTIME_COMMANDS = Object.freeze({ gemini: "gemini" });
|
|
51129
51371
|
});
|
|
51130
51372
|
|
|
51131
51373
|
// src/lib/authoring-path.ts
|
|
51132
51374
|
import { lstatSync as lstatSync19, realpathSync as realpathSync6 } from "fs";
|
|
51133
51375
|
import { homedir as homedir3 } from "os";
|
|
51134
|
-
import { basename as
|
|
51376
|
+
import { basename as basename10, dirname as dirname17, join as join27, resolve as resolve18, sep as sep7 } from "path";
|
|
51135
51377
|
function pathParts(path) {
|
|
51136
|
-
return
|
|
51378
|
+
return resolve18(path).split(sep7).filter(Boolean);
|
|
51137
51379
|
}
|
|
51138
51380
|
function nativeRootMatch(path) {
|
|
51139
51381
|
const parts = pathParts(path);
|
|
@@ -51147,16 +51389,16 @@ function nativeRootMatch(path) {
|
|
|
51147
51389
|
return;
|
|
51148
51390
|
}
|
|
51149
51391
|
function physicalPath(path) {
|
|
51150
|
-
let cursor =
|
|
51392
|
+
let cursor = resolve18(path);
|
|
51151
51393
|
const suffix = [];
|
|
51152
51394
|
while (!lstatSync19(cursor, { throwIfNoEntry: false })) {
|
|
51153
|
-
suffix.unshift(
|
|
51154
|
-
const parent =
|
|
51395
|
+
suffix.unshift(basename10(cursor));
|
|
51396
|
+
const parent = dirname17(cursor);
|
|
51155
51397
|
if (parent === cursor)
|
|
51156
|
-
return
|
|
51398
|
+
return resolve18(path);
|
|
51157
51399
|
cursor = parent;
|
|
51158
51400
|
}
|
|
51159
|
-
return
|
|
51401
|
+
return resolve18(realpathSync6(cursor), ...suffix);
|
|
51160
51402
|
}
|
|
51161
51403
|
function contains(root, path) {
|
|
51162
51404
|
return path === root || path.startsWith(root + sep7);
|
|
@@ -51164,7 +51406,7 @@ function contains(root, path) {
|
|
|
51164
51406
|
function configuredRoots(home, explicitHome) {
|
|
51165
51407
|
const homeData = join27(home, ".hasna", "skills");
|
|
51166
51408
|
const homePolicy = readManagedSkillPolicySnapshot(homeData);
|
|
51167
|
-
const configuredPolicy = !explicitHome &&
|
|
51409
|
+
const configuredPolicy = !explicitHome && resolve18(getDataDirReadOnly()) !== resolve18(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
|
|
51168
51410
|
const policy = homePolicy ?? configuredPolicy;
|
|
51169
51411
|
const bridge = policy?.value.bridge;
|
|
51170
51412
|
if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
|
|
@@ -51203,22 +51445,22 @@ function configuredRoots(home, explicitHome) {
|
|
|
51203
51445
|
function assertPortableAuthoringPath(path, options = {}) {
|
|
51204
51446
|
if (typeof path !== "string" || !path || path.includes("\x00"))
|
|
51205
51447
|
throw new Error("Invalid portable authoring path");
|
|
51206
|
-
const lexical =
|
|
51448
|
+
const lexical = resolve18(path);
|
|
51207
51449
|
const physical = physicalPath(lexical);
|
|
51208
51450
|
const candidates = [lexical, physical];
|
|
51209
51451
|
let native = candidates.map(nativeRootMatch).find(Boolean);
|
|
51210
|
-
const home =
|
|
51452
|
+
const home = resolve18(options.homeDir ?? homedir3());
|
|
51211
51453
|
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join27(home, ...parts));
|
|
51212
51454
|
defaults.push(join27(home, ".codex/plugins/cache"), join27(home, ".claude/plugins/cache"), join27(home, ".claude/plugins/synced"), join27(home, ".gemini/extensions"));
|
|
51213
51455
|
for (const root of defaults) {
|
|
51214
|
-
if (candidates.some((candidate) => contains(
|
|
51456
|
+
if (candidates.some((candidate) => contains(resolve18(root), candidate) || contains(physicalPath(root), candidate)))
|
|
51215
51457
|
native ??= root;
|
|
51216
51458
|
}
|
|
51217
51459
|
if (native) {
|
|
51218
51460
|
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.`);
|
|
51219
51461
|
}
|
|
51220
51462
|
for (const root of configuredRoots(home, options.homeDir !== undefined)) {
|
|
51221
|
-
if (candidates.some((candidate) => contains(
|
|
51463
|
+
if (candidates.some((candidate) => contains(resolve18(root), candidate) || contains(physicalPath(root), candidate))) {
|
|
51222
51464
|
throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
|
|
51223
51465
|
}
|
|
51224
51466
|
}
|
|
@@ -51245,7 +51487,7 @@ import {
|
|
|
51245
51487
|
statSync as statSync7,
|
|
51246
51488
|
writeFileSync as writeFileSync6
|
|
51247
51489
|
} from "fs";
|
|
51248
|
-
import { basename as
|
|
51490
|
+
import { basename as basename11, dirname as dirname18, isAbsolute as isAbsolute16, join as join28, normalize as normalize3, relative as relative5, resolve as resolve19, sep as sep8 } from "path";
|
|
51249
51491
|
function getPortableSkillsRoot(options = {}) {
|
|
51250
51492
|
return resolvePortableSkillsRoot(options, true);
|
|
51251
51493
|
}
|
|
@@ -51340,20 +51582,20 @@ function scaffoldPortableSkill(name, options = {}) {
|
|
|
51340
51582
|
return { name: skillName, path: skillPath, manifest, created: true };
|
|
51341
51583
|
}
|
|
51342
51584
|
function physicalImportPath(path) {
|
|
51343
|
-
let ancestor =
|
|
51585
|
+
let ancestor = resolve19(path);
|
|
51344
51586
|
const suffix = [];
|
|
51345
51587
|
while (!existsSync12(ancestor)) {
|
|
51346
|
-
suffix.unshift(
|
|
51347
|
-
ancestor =
|
|
51588
|
+
suffix.unshift(basename11(ancestor));
|
|
51589
|
+
ancestor = dirname18(ancestor);
|
|
51348
51590
|
}
|
|
51349
51591
|
return join28(realpathSync7(ancestor), ...suffix);
|
|
51350
51592
|
}
|
|
51351
51593
|
function assertDisjointImportPaths(source, destination) {
|
|
51352
51594
|
const sourcePath = realpathSync7(source);
|
|
51353
51595
|
const destinationPath = physicalImportPath(destination);
|
|
51354
|
-
const contains2 = (parent,
|
|
51355
|
-
const path = relative5(parent,
|
|
51356
|
-
return path === "" || !
|
|
51596
|
+
const contains2 = (parent, child2) => {
|
|
51597
|
+
const path = relative5(parent, child2);
|
|
51598
|
+
return path === "" || !isAbsolute16(path) && path !== ".." && !path.startsWith(`..${sep8}`);
|
|
51357
51599
|
};
|
|
51358
51600
|
if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
|
|
51359
51601
|
throw new Error("Source and destination skill directories must not overlap");
|
|
@@ -51368,8 +51610,8 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
51368
51610
|
const explicitName = options.name != null;
|
|
51369
51611
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
51370
51612
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
51371
|
-
const sourceSlug = safeNormalizeName(
|
|
51372
|
-
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${
|
|
51613
|
+
const sourceSlug = safeNormalizeName(basename11(absoluteSource));
|
|
51614
|
+
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename11(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
51373
51615
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
51374
51616
|
}
|
|
51375
51617
|
const readOnlyDestination = join28(resolvePortableSkillsRoot(options, false), skillName);
|
|
@@ -51384,7 +51626,7 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
51384
51626
|
throw new Error(`Skill '${skillName}' already exists at ${destination}`);
|
|
51385
51627
|
rmSync3(destination, { recursive: true, force: true });
|
|
51386
51628
|
}
|
|
51387
|
-
mkdirSync7(
|
|
51629
|
+
mkdirSync7(dirname18(destination), { recursive: true });
|
|
51388
51630
|
copySkillDirectory(absoluteSource, destination);
|
|
51389
51631
|
const base = {
|
|
51390
51632
|
...inferred,
|
|
@@ -51518,7 +51760,7 @@ function safeIsDirectory(path) {
|
|
|
51518
51760
|
}
|
|
51519
51761
|
}
|
|
51520
51762
|
function isSafeRelativePath2(value) {
|
|
51521
|
-
if (!value.trim() ||
|
|
51763
|
+
if (!value.trim() || isAbsolute16(value))
|
|
51522
51764
|
return false;
|
|
51523
51765
|
const normalized = normalize3(value).replace(/\\/g, "/");
|
|
51524
51766
|
return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
|
|
@@ -52147,11 +52389,14 @@ var init_skill_context = __esm(() => {
|
|
|
52147
52389
|
});
|
|
52148
52390
|
|
|
52149
52391
|
// src/lib/session-reconciliation.ts
|
|
52150
|
-
var SESSION_RECONCILIATION_PLAN_TTL_MS;
|
|
52392
|
+
var SESSION_RECONCILIATION_PLAN_TTL_MS, SESSION_RENEWAL_REFUSAL_TTL_MS, SESSION_RENEWAL_REFUSAL_MAX_BYTES;
|
|
52151
52393
|
var init_session_reconciliation = __esm(() => {
|
|
52152
52394
|
init_profile_client();
|
|
52395
|
+
init_skill_bundle();
|
|
52153
52396
|
init_selection_cache();
|
|
52154
52397
|
SESSION_RECONCILIATION_PLAN_TTL_MS = 5 * 60 * 1000;
|
|
52398
|
+
SESSION_RENEWAL_REFUSAL_TTL_MS = 5 * 60 * 1000;
|
|
52399
|
+
SESSION_RENEWAL_REFUSAL_MAX_BYTES = 4 * 1024;
|
|
52155
52400
|
});
|
|
52156
52401
|
|
|
52157
52402
|
// src/cli/commands/context.ts
|
|
@@ -52189,7 +52434,7 @@ var init_remote_customer_operations = __esm(() => {
|
|
|
52189
52434
|
});
|
|
52190
52435
|
|
|
52191
52436
|
// src/lib/canonical-json.ts
|
|
52192
|
-
import { createHash as
|
|
52437
|
+
import { createHash as createHash19 } from "crypto";
|
|
52193
52438
|
function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
|
|
52194
52439
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
52195
52440
|
}
|
|
@@ -52233,7 +52478,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
52233
52478
|
return visit3(value, 0);
|
|
52234
52479
|
}
|
|
52235
52480
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
52236
|
-
return
|
|
52481
|
+
return createHash19("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
|
|
52237
52482
|
}
|
|
52238
52483
|
var init_canonical_json = () => {};
|
|
52239
52484
|
|
|
@@ -52984,13 +53229,13 @@ var init_remote_workspace_leave = __esm(() => {
|
|
|
52984
53229
|
|
|
52985
53230
|
// src/lib/auth-store.ts
|
|
52986
53231
|
import { chmodSync, existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync17, renameSync as renameSync4, statSync as statSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
52987
|
-
import { basename as
|
|
53232
|
+
import { basename as basename12, dirname as dirname19, join as join30 } from "path";
|
|
52988
53233
|
function getAuthFilePath(env = process.env) {
|
|
52989
53234
|
return skillsCredentialFilePath(env);
|
|
52990
53235
|
}
|
|
52991
53236
|
function getIdentityFilePath(env = process.env) {
|
|
52992
53237
|
const file2 = skillsCredentialFilePath(env);
|
|
52993
|
-
return join30(
|
|
53238
|
+
return join30(dirname19(file2), basename12(file2).replace(/^credentials/, "identity") + ".json");
|
|
52994
53239
|
}
|
|
52995
53240
|
function getApiUrl(action, env = process.env, options = {}) {
|
|
52996
53241
|
return requireSkillsApiOrigin(action, env, options);
|
|
@@ -53072,17 +53317,17 @@ function runQuoteReceipt(value) {
|
|
|
53072
53317
|
return value;
|
|
53073
53318
|
}
|
|
53074
53319
|
function parseRemoteRunQuote(value) {
|
|
53075
|
-
const
|
|
53076
|
-
runQuoteReceipt(
|
|
53077
|
-
const pricing = object7(
|
|
53078
|
-
if (typeof
|
|
53320
|
+
const quote3 = object7(value);
|
|
53321
|
+
runQuoteReceipt(quote3.quoteReceipt);
|
|
53322
|
+
const pricing = object7(quote3.pricing);
|
|
53323
|
+
if (typeof quote3.skill !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(quote3.skill))
|
|
53079
53324
|
throw new Error("Invalid quoted skill");
|
|
53080
53325
|
const costCents = creditCount(pricing.costCredits ?? pricing.costCents);
|
|
53081
53326
|
if (pricing.costCredits !== undefined && pricing.costCents !== undefined && pricing.costCents !== costCents)
|
|
53082
53327
|
throw new Error("Inconsistent quoted credit count");
|
|
53083
|
-
if (
|
|
53328
|
+
if (quote3.availability && object7(quote3.availability).status !== "available")
|
|
53084
53329
|
throw new Error("This skill is unavailable for remote execution");
|
|
53085
|
-
return { ...
|
|
53330
|
+
return { ...quote3, skill: quote3.skill, pricing: { ...pricing, costCredits: costCents, costCents, formattedCost: `${costCents} credits` } };
|
|
53086
53331
|
}
|
|
53087
53332
|
function parseRemoteCreditPacks(value) {
|
|
53088
53333
|
if (!Array.isArray(value))
|
|
@@ -53174,14 +53419,14 @@ var init_remote_credit_checkout = __esm(() => {
|
|
|
53174
53419
|
});
|
|
53175
53420
|
|
|
53176
53421
|
// src/lib/remote-profile.ts
|
|
53177
|
-
function customerNamePatch(input2,
|
|
53178
|
-
if (!isRecord5(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2,
|
|
53422
|
+
function customerNamePatch(input2, field3) {
|
|
53423
|
+
if (!isRecord5(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field3))
|
|
53179
53424
|
throw new Error("Provide only the requested name field.");
|
|
53180
|
-
const value = input2[
|
|
53425
|
+
const value = input2[field3];
|
|
53181
53426
|
if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
|
|
53182
53427
|
throw new Error("Use a name of 1\u2013100 characters without control characters or newlines.");
|
|
53183
53428
|
}
|
|
53184
|
-
return { [
|
|
53429
|
+
return { [field3]: value.trim() };
|
|
53185
53430
|
}
|
|
53186
53431
|
function isRecord5(value) {
|
|
53187
53432
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -53218,10 +53463,10 @@ async function readQuoteUnavailableCode(response) {
|
|
|
53218
53463
|
let timer;
|
|
53219
53464
|
let deadlineExceeded = false;
|
|
53220
53465
|
const expired = Symbol("quote body deadline");
|
|
53221
|
-
const deadline = new Promise((
|
|
53466
|
+
const deadline = new Promise((resolve20) => {
|
|
53222
53467
|
timer = setTimeout(() => {
|
|
53223
53468
|
deadlineExceeded = true;
|
|
53224
|
-
|
|
53469
|
+
resolve20(expired);
|
|
53225
53470
|
reader.cancel().catch(() => {});
|
|
53226
53471
|
}, 1500);
|
|
53227
53472
|
});
|
|
@@ -53504,18 +53749,18 @@ class RemoteSkillsClient {
|
|
|
53504
53749
|
const maximum = creditCount(approval.maxCredits ?? approval.maxCostCents ?? 0);
|
|
53505
53750
|
if (approval.maxCostCents !== undefined && approval.maxCostCents !== maximum)
|
|
53506
53751
|
throw new Error("Credit approval fields disagree");
|
|
53507
|
-
const
|
|
53508
|
-
if (
|
|
53509
|
-
throw new RemoteCreditApprovalError(
|
|
53752
|
+
const quote3 = approval.quoteReceipt === undefined ? await this.quoteRun(slug2, input2, args, approval.inputFiles?.length ? approval.inputFiles : undefined) : undefined;
|
|
53753
|
+
if (quote3 && quote3.pricing.costCents > maximum)
|
|
53754
|
+
throw new RemoteCreditApprovalError(quote3.pricing.costCents, maximum);
|
|
53510
53755
|
const capabilities = await this.getCapabilities();
|
|
53511
53756
|
if (!capabilities.capabilities.includes("runs.submit") || capabilities.billing?.boundedRunApproval !== true || capabilities.billing.unit !== "credits") {
|
|
53512
53757
|
throw new Error("The configured server does not support bounded credit approval; refusing remote submission");
|
|
53513
53758
|
}
|
|
53514
|
-
return this.submitRun(
|
|
53759
|
+
return this.submitRun(quote3?.skill ?? slug2, input2, args, {
|
|
53515
53760
|
...approval,
|
|
53516
53761
|
maxCredits: maximum,
|
|
53517
53762
|
maxCostCents: maximum,
|
|
53518
|
-
...(
|
|
53763
|
+
...(quote3?.quoteReceipt ?? approval.quoteReceipt) === undefined ? {} : { quoteReceipt: quote3?.quoteReceipt ?? approval.quoteReceipt }
|
|
53519
53764
|
});
|
|
53520
53765
|
}
|
|
53521
53766
|
async getIdentity() {
|
|
@@ -54116,13 +54361,13 @@ class RemoteSkillsClient {
|
|
|
54116
54361
|
return normalizeUpdatedSincePage(await response.json());
|
|
54117
54362
|
}
|
|
54118
54363
|
}
|
|
54119
|
-
function requireOptionalString(record9,
|
|
54120
|
-
if (record9[
|
|
54364
|
+
function requireOptionalString(record9, field3) {
|
|
54365
|
+
if (record9[field3] === undefined)
|
|
54121
54366
|
return;
|
|
54122
|
-
if (typeof record9[
|
|
54123
|
-
throw new Error(`Remote payload did not match the expected contract (${
|
|
54367
|
+
if (typeof record9[field3] !== "string") {
|
|
54368
|
+
throw new Error(`Remote payload did not match the expected contract (${field3} must be a string when present)`);
|
|
54124
54369
|
}
|
|
54125
|
-
return record9[
|
|
54370
|
+
return record9[field3];
|
|
54126
54371
|
}
|
|
54127
54372
|
function isVersionRecord(value) {
|
|
54128
54373
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -54459,7 +54704,7 @@ var init_remote_invitation_recovery = __esm(() => {
|
|
|
54459
54704
|
});
|
|
54460
54705
|
|
|
54461
54706
|
// src/lib/remote-private-publications.ts
|
|
54462
|
-
import { createHash as
|
|
54707
|
+
import { createHash as createHash20 } from "crypto";
|
|
54463
54708
|
function checkedPublicationDeclaration(value) {
|
|
54464
54709
|
if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
|
|
54465
54710
|
return bad();
|
|
@@ -54704,12 +54949,12 @@ class RemotePrivatePublicationsClient {
|
|
|
54704
54949
|
previous = view;
|
|
54705
54950
|
if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
|
|
54706
54951
|
return view;
|
|
54707
|
-
await new Promise((
|
|
54952
|
+
await new Promise((resolve20) => {
|
|
54708
54953
|
const timer = setTimeout(done, Math.min(1000, until - Date.now()));
|
|
54709
54954
|
function done() {
|
|
54710
54955
|
clearTimeout(timer);
|
|
54711
54956
|
options.signal?.removeEventListener("abort", done);
|
|
54712
|
-
|
|
54957
|
+
resolve20();
|
|
54713
54958
|
}
|
|
54714
54959
|
options.signal?.addEventListener("abort", done, { once: true });
|
|
54715
54960
|
});
|
|
@@ -54720,7 +54965,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
|
|
|
54720
54965
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
54721
54966
|
}, invalid4 = () => {
|
|
54722
54967
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
54723
|
-
}, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys) => record10(v) && Object.keys(v).sort().join(",") === keys.sort().join(","), date6 = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) =>
|
|
54968
|
+
}, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys) => record10(v) && Object.keys(v).sort().join(",") === keys.sort().join(","), date6 = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) => createHash20("sha256").update(bytes).digest("hex");
|
|
54724
54969
|
var init_remote_private_publications = __esm(() => {
|
|
54725
54970
|
init_fleet_credentials();
|
|
54726
54971
|
init_remote_workspace_selection();
|
|
@@ -55230,7 +55475,7 @@ var init_recurring_customer = __esm(() => {
|
|
|
55230
55475
|
|
|
55231
55476
|
// src/lib/recurring-recovery.ts
|
|
55232
55477
|
import { constants as constants12, closeSync as closeSync15, fsyncSync as fsyncSync4, fstatSync as fstatSync15, lstatSync as lstatSync21, mkdirSync as mkdirSync10, openSync as openSync15, readSync as readSync10, realpathSync as realpathSync8, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
55233
|
-
import { dirname as
|
|
55478
|
+
import { dirname as dirname20, isAbsolute as isAbsolute17, join as join31, resolve as resolve20 } from "path";
|
|
55234
55479
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
55235
55480
|
|
|
55236
55481
|
class RecoveryOwner {
|
|
@@ -55238,14 +55483,14 @@ class RecoveryOwner {
|
|
|
55238
55483
|
parents = [];
|
|
55239
55484
|
constructor(directory) {
|
|
55240
55485
|
this.directory = directory;
|
|
55241
|
-
if (!
|
|
55486
|
+
if (!isAbsolute17(directory) || resolve20(directory) !== directory || realpathSync8(directory) !== directory)
|
|
55242
55487
|
invalid5();
|
|
55243
|
-
for (let path = directory;; path =
|
|
55488
|
+
for (let path = directory;; path = dirname20(path)) {
|
|
55244
55489
|
const stat3 = lstatSync21(path);
|
|
55245
55490
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
55246
55491
|
invalid5();
|
|
55247
55492
|
this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
|
|
55248
|
-
if (path ===
|
|
55493
|
+
if (path === dirname20(path))
|
|
55249
55494
|
break;
|
|
55250
55495
|
}
|
|
55251
55496
|
this.assert();
|
|
@@ -55373,7 +55618,7 @@ function base(customer, organizationId) {
|
|
|
55373
55618
|
};
|
|
55374
55619
|
}
|
|
55375
55620
|
function create(directory, intent) {
|
|
55376
|
-
if (!
|
|
55621
|
+
if (!isAbsolute17(directory) || resolve20(directory) !== directory || realpathSync8(dirname20(directory)) !== dirname20(directory))
|
|
55377
55622
|
invalid5();
|
|
55378
55623
|
mkdirSync10(directory, { mode: 448 });
|
|
55379
55624
|
const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
|
|
@@ -55536,7 +55781,7 @@ var init_recurring_recovery = __esm(() => {
|
|
|
55536
55781
|
});
|
|
55537
55782
|
|
|
55538
55783
|
// src/lib/recurring-surface.ts
|
|
55539
|
-
import { isAbsolute as
|
|
55784
|
+
import { isAbsolute as isAbsolute18 } from "path";
|
|
55540
55785
|
function recurringMcpSchema(action) {
|
|
55541
55786
|
return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
|
|
55542
55787
|
}
|
|
@@ -55641,7 +55886,7 @@ var init_recurring_surface = __esm(() => {
|
|
|
55641
55886
|
uuid13 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
|
|
55642
55887
|
context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
|
|
55643
55888
|
page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
|
|
55644
|
-
directory = exports_external.string().max(4096).refine(
|
|
55889
|
+
directory = exports_external.string().max(4096).refine(isAbsolute18, "Use an absolute recovery directory");
|
|
55645
55890
|
email4 = exports_external.string().trim().toLowerCase().email().max(254);
|
|
55646
55891
|
code = exports_external.string().regex(/^\d{6}$/);
|
|
55647
55892
|
recurringSurfaceSchemas = {
|
|
@@ -57470,7 +57715,7 @@ var init_credential_state = __esm(() => {
|
|
|
57470
57715
|
});
|
|
57471
57716
|
|
|
57472
57717
|
// src/lib/run-state.ts
|
|
57473
|
-
import { createHash as
|
|
57718
|
+
import { createHash as createHash21, randomBytes } from "crypto";
|
|
57474
57719
|
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync19, readdirSync as readdirSync10, statSync as statSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
57475
57720
|
import { extname, join as join32, relative as relative6 } from "path";
|
|
57476
57721
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
@@ -57585,7 +57830,7 @@ function collectRunArtifacts(context2) {
|
|
|
57585
57830
|
artifacts.push({
|
|
57586
57831
|
path: toProjectRelative(context2.targetDir, path),
|
|
57587
57832
|
mime: mimeForPath(path),
|
|
57588
|
-
sha256:
|
|
57833
|
+
sha256: createHash21("sha256").update(bytes).digest("hex"),
|
|
57589
57834
|
sizeBytes: stat3.size
|
|
57590
57835
|
});
|
|
57591
57836
|
}
|
|
@@ -57831,12 +58076,12 @@ function parseExecution(value) {
|
|
|
57831
58076
|
].includes(v.status) || typeof v.skill !== "string" || typeof v.version !== "string" || !Array.isArray(v.artifacts))
|
|
57832
58077
|
throw Error("Unsupported cloud execution response");
|
|
57833
58078
|
runId(v.id);
|
|
57834
|
-
for (const
|
|
58079
|
+
for (const field3 of [
|
|
57835
58080
|
"bundleDigest",
|
|
57836
58081
|
"inputDigest",
|
|
57837
58082
|
"runtimeImageDigest"
|
|
57838
58083
|
])
|
|
57839
|
-
if (typeof v[
|
|
58084
|
+
if (typeof v[field3] !== "string" || !/^(sha256:)?[a-f0-9]{64}$/.test(v[field3]))
|
|
57840
58085
|
throw Error("Invalid cloud execution integrity receipt");
|
|
57841
58086
|
return v;
|
|
57842
58087
|
}
|
|
@@ -57861,7 +58106,7 @@ import { closeSync as closeSync16, fstatSync as fstatSync16, openSync as openSyn
|
|
|
57861
58106
|
import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
|
|
57862
58107
|
import { createRequire as createRequire2 } from "module";
|
|
57863
58108
|
import { hostname as osHostname2 } from "os";
|
|
57864
|
-
import { isAbsolute as
|
|
58109
|
+
import { isAbsolute as isAbsolute19, join as join33 } from "path";
|
|
57865
58110
|
import { createRequire as createRequire22 } from "module";
|
|
57866
58111
|
function envToken2(name) {
|
|
57867
58112
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -57885,7 +58130,7 @@ function homeDir2(env) {
|
|
|
57885
58130
|
}
|
|
57886
58131
|
function absoluteOverride2(env, key) {
|
|
57887
58132
|
const value = env[key]?.trim();
|
|
57888
|
-
return value &&
|
|
58133
|
+
return value && isAbsolute19(value) ? value : null;
|
|
57889
58134
|
}
|
|
57890
58135
|
function hasnaHomeDir2(env) {
|
|
57891
58136
|
const override = absoluteOverride2(env, HASNA_HOME_ENV_KEY2);
|
|
@@ -57931,9 +58176,9 @@ function parseEnvFile2(text3) {
|
|
|
57931
58176
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
|
|
57932
58177
|
continue;
|
|
57933
58178
|
let value = withoutExport.slice(equals + 1).trim();
|
|
57934
|
-
const
|
|
57935
|
-
if (
|
|
57936
|
-
if (value.length < 2 || !value.endsWith(
|
|
58179
|
+
const quote3 = value[0];
|
|
58180
|
+
if (quote3 === '"' || quote3 === "'") {
|
|
58181
|
+
if (value.length < 2 || !value.endsWith(quote3)) {
|
|
57937
58182
|
unusable.add(key);
|
|
57938
58183
|
continue;
|
|
57939
58184
|
}
|
|
@@ -57957,8 +58202,8 @@ function configFileReadsCoherent2(before, after) {
|
|
|
57957
58202
|
return before.dev === after.dev && before.ino === after.ino && before.size === after.size && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs;
|
|
57958
58203
|
}
|
|
57959
58204
|
function readAppConfigFile2(path) {
|
|
57960
|
-
const unsafe = (
|
|
57961
|
-
throw new CredentialFileUnsafeError2(path,
|
|
58205
|
+
const unsafe = (reason2) => {
|
|
58206
|
+
throw new CredentialFileUnsafeError2(path, reason2);
|
|
57962
58207
|
};
|
|
57963
58208
|
let fd = -1;
|
|
57964
58209
|
try {
|
|
@@ -58177,8 +58422,8 @@ function readKeychainItem2(name, env, kind, options) {
|
|
|
58177
58422
|
try {
|
|
58178
58423
|
result = run(["find-generic-password", "-a", account, "-s", service, "-w"]);
|
|
58179
58424
|
} catch (error61) {
|
|
58180
|
-
const
|
|
58181
|
-
throw new CredentialResolutionError2(name, `The Keychain lookup for ${source} could not run${
|
|
58425
|
+
const reason2 = keychainFailureHint2(error61 instanceof Error ? error61.message : String(error61));
|
|
58426
|
+
throw new CredentialResolutionError2(name, `The Keychain lookup for ${source} could not run${reason2}. A Keychain failure is never resolved ` + `around: fix the keychain, or delete the item to fall through to the credential on disk.`, [source]);
|
|
58182
58427
|
}
|
|
58183
58428
|
if (result.status === KEYCHAIN_ITEM_NOT_FOUND_STATUS2)
|
|
58184
58429
|
return null;
|
|
@@ -59022,7 +59267,7 @@ function createSecretsClientFromEnv(env = process.env, overrides = {}) {
|
|
|
59022
59267
|
});
|
|
59023
59268
|
return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
|
|
59024
59269
|
}
|
|
59025
|
-
var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((
|
|
59270
|
+
var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((resolve21) => setTimeout(resolve21, ms)), init_transport2, MAX_CREDENTIAL_FILE_BYTES22, INSPECT_CUSTOM22, CREDENTIAL_SEAL22, AMBIENT_ENVIRONMENT22, SECRETS_PACKAGE_SPECIFIER2, requireSecretsSdk22, IDEMPOTENT_METHODS22, AUTHORITY_OVERRIDE_HEADERS22, init_storage, PATHS_RESOLVER_APP_SLUG_RE2, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
|
|
59026
59271
|
var init_sdk = __esm(() => {
|
|
59027
59272
|
init_transport2 = __esm2(() => {
|
|
59028
59273
|
CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
|
|
@@ -59037,8 +59282,8 @@ var init_sdk = __esm(() => {
|
|
|
59037
59282
|
};
|
|
59038
59283
|
CredentialFileUnsafeError2 = class CredentialFileUnsafeError3 extends Error {
|
|
59039
59284
|
path;
|
|
59040
|
-
constructor(path,
|
|
59041
|
-
super(`Refusing unsafe credential/config file ${path}: ${
|
|
59285
|
+
constructor(path, reason2) {
|
|
59286
|
+
super(`Refusing unsafe credential/config file ${path}: ${reason2}.`);
|
|
59042
59287
|
this.name = "CredentialFileUnsafeError";
|
|
59043
59288
|
this.path = path;
|
|
59044
59289
|
}
|
|
@@ -59399,10 +59644,10 @@ __export(exports_selected_run, {
|
|
|
59399
59644
|
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
59400
59645
|
executeSelectedLocal: () => executeSelectedLocal
|
|
59401
59646
|
});
|
|
59402
|
-
import { createHash as
|
|
59647
|
+
import { createHash as createHash22 } from "crypto";
|
|
59403
59648
|
import { spawn } from "child_process";
|
|
59404
59649
|
import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync10 } from "fs";
|
|
59405
|
-
import { dirname as
|
|
59650
|
+
import { dirname as dirname21, join as join34, resolve as resolve21 } from "path";
|
|
59406
59651
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
59407
59652
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
59408
59653
|
const context2 = await resolveSelectionContext(profileId, options);
|
|
@@ -59491,11 +59736,11 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
59491
59736
|
throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
|
|
59492
59737
|
});
|
|
59493
59738
|
const destination = join34(runDirectory, entry.path);
|
|
59494
|
-
mkdirSync12(
|
|
59739
|
+
mkdirSync12(dirname21(destination), { recursive: true, mode: 448 });
|
|
59495
59740
|
writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
|
|
59496
59741
|
}
|
|
59497
59742
|
env.SKILLS_INPUT_JSON = input2;
|
|
59498
|
-
env.SKILLS_WORKSPACE_DIR =
|
|
59743
|
+
env.SKILLS_WORKSPACE_DIR = resolve21(options.cwd ?? process.cwd());
|
|
59499
59744
|
env.SKILLS_RUN_DIR = runDirectory;
|
|
59500
59745
|
if (runtime.version) {
|
|
59501
59746
|
const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
|
|
@@ -59525,7 +59770,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
59525
59770
|
selection: selection2,
|
|
59526
59771
|
target: "local",
|
|
59527
59772
|
runtime: runtimeName,
|
|
59528
|
-
inputDigest: `sha256:${
|
|
59773
|
+
inputDigest: `sha256:${createHash22("sha256").update(input2).digest("hex")}`,
|
|
59529
59774
|
runDirectory,
|
|
59530
59775
|
...executionGrant ? { executionGrant } : {},
|
|
59531
59776
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
@@ -59536,17 +59781,17 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
59536
59781
|
}
|
|
59537
59782
|
async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
59538
59783
|
return new Promise((resolveResult) => {
|
|
59539
|
-
const
|
|
59784
|
+
const child2 = spawn(command[0], command.slice(1), { cwd, env, shell: false, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
59540
59785
|
let outputBytes = 0, error61, ended = false;
|
|
59541
59786
|
const stdout = [], stderr = [];
|
|
59542
59787
|
const kill = () => {
|
|
59543
59788
|
try {
|
|
59544
|
-
if (process.platform !== "win32" &&
|
|
59545
|
-
process.kill(-
|
|
59789
|
+
if (process.platform !== "win32" && child2.pid)
|
|
59790
|
+
process.kill(-child2.pid, "SIGKILL");
|
|
59546
59791
|
else
|
|
59547
|
-
|
|
59792
|
+
child2.kill("SIGKILL");
|
|
59548
59793
|
} catch {
|
|
59549
|
-
|
|
59794
|
+
child2.kill("SIGKILL");
|
|
59550
59795
|
}
|
|
59551
59796
|
};
|
|
59552
59797
|
const timer = setTimeout(() => {
|
|
@@ -59562,8 +59807,8 @@ async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
|
59562
59807
|
}
|
|
59563
59808
|
target.push(chunk);
|
|
59564
59809
|
};
|
|
59565
|
-
|
|
59566
|
-
|
|
59810
|
+
child2.stdout.on("data", capture2(stdout));
|
|
59811
|
+
child2.stderr.on("data", capture2(stderr));
|
|
59567
59812
|
const finish = (code2) => {
|
|
59568
59813
|
if (ended)
|
|
59569
59814
|
return;
|
|
@@ -59571,13 +59816,13 @@ async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
|
59571
59816
|
clearTimeout(timer);
|
|
59572
59817
|
resolveResult({ exitCode: error61 === "LOCAL_RUN_TIMEOUT" ? 124 : error61 ? 1 : code2, stdout: Buffer.concat(stdout).toString("utf8"), stderr: Buffer.concat(stderr).toString("utf8"), ...error61 ? { error: error61 } : {} });
|
|
59573
59818
|
};
|
|
59574
|
-
|
|
59819
|
+
child2.on("error", () => {
|
|
59575
59820
|
error61 = "LOCAL_RUNTIME_START_FAILED";
|
|
59576
59821
|
finish(127);
|
|
59577
59822
|
});
|
|
59578
|
-
|
|
59579
|
-
|
|
59580
|
-
|
|
59823
|
+
child2.on("close", (code2) => finish(code2 ?? 1));
|
|
59824
|
+
child2.stdin.on("error", () => {});
|
|
59825
|
+
child2.stdin.end(input2);
|
|
59581
59826
|
});
|
|
59582
59827
|
}
|
|
59583
59828
|
var init_selected_run = __esm(() => {
|
|
@@ -60094,9 +60339,9 @@ function registerOperationTools(server) {
|
|
|
60094
60339
|
}
|
|
60095
60340
|
}, async ({ run_id, detail }) => {
|
|
60096
60341
|
const { skillsCredentialOrReason: skillsCredentialOrReason2 } = await Promise.resolve().then(() => (init_fleet_credentials(), exports_fleet_credentials));
|
|
60097
|
-
const { apiKey, apiOrigin, reason } = await skillsCredentialOrReason2();
|
|
60342
|
+
const { apiKey, apiOrigin, reason: reason2 } = await skillsCredentialOrReason2();
|
|
60098
60343
|
if (!apiKey) {
|
|
60099
|
-
return mcpError("AUTH_REQUIRED",
|
|
60344
|
+
return mcpError("AUTH_REQUIRED", reason2 ?? "Remote run status requires API access. Run: skills auth login", ["skills auth login"]);
|
|
60100
60345
|
}
|
|
60101
60346
|
const localRun = findSkillRun(run_id);
|
|
60102
60347
|
const remoteRunId = localRun?.remoteRunId || run_id;
|
|
@@ -60266,14 +60511,14 @@ var init_operation_tools = __esm(() => {
|
|
|
60266
60511
|
|
|
60267
60512
|
// src/lib/feedback.ts
|
|
60268
60513
|
import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync13 } from "fs";
|
|
60269
|
-
import { dirname as
|
|
60514
|
+
import { dirname as dirname22, join as join36 } from "path";
|
|
60270
60515
|
import { Database } from "bun:sqlite";
|
|
60271
60516
|
function getFeedbackDbPath() {
|
|
60272
60517
|
return join36(getDataDir(), "skills.db");
|
|
60273
60518
|
}
|
|
60274
60519
|
function getFeedbackDb() {
|
|
60275
60520
|
const dbPath = getFeedbackDbPath();
|
|
60276
|
-
const dir =
|
|
60521
|
+
const dir = dirname22(dbPath);
|
|
60277
60522
|
if (!existsSync17(dir))
|
|
60278
60523
|
mkdirSync13(dir, { recursive: true });
|
|
60279
60524
|
const db = new Database(dbPath);
|
|
@@ -60302,7 +60547,7 @@ function saveFeedback(input2) {
|
|
|
60302
60547
|
const category = input2.category ?? "general";
|
|
60303
60548
|
if (isApiMode()) {
|
|
60304
60549
|
const path = join36(getDataDir(), "feedback.jsonl");
|
|
60305
|
-
const dir =
|
|
60550
|
+
const dir = dirname22(path);
|
|
60306
60551
|
if (!existsSync17(dir))
|
|
60307
60552
|
mkdirSync13(dir, { recursive: true });
|
|
60308
60553
|
appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
|
|
@@ -60753,7 +60998,7 @@ var init_schedule_tools = __esm(() => {
|
|
|
60753
60998
|
});
|
|
60754
60999
|
|
|
60755
61000
|
// src/lib/native-storage.ts
|
|
60756
|
-
import { createHash as
|
|
61001
|
+
import { createHash as createHash23, createHmac } from "crypto";
|
|
60757
61002
|
import {
|
|
60758
61003
|
existsSync as existsSync19,
|
|
60759
61004
|
mkdirSync as mkdirSync15,
|
|
@@ -60762,7 +61007,7 @@ import {
|
|
|
60762
61007
|
statSync as statSync11,
|
|
60763
61008
|
writeFileSync as writeFileSync13
|
|
60764
61009
|
} from "fs";
|
|
60765
|
-
import { dirname as
|
|
61010
|
+
import { dirname as dirname23, join as join38, normalize as normalize4, relative as relative7, sep as sep9 } from "path";
|
|
60766
61011
|
function resolveSkillsNativeStorageConfig(env = process.env) {
|
|
60767
61012
|
assertNoRetiredModeEnvVars(env, {
|
|
60768
61013
|
app: SKILLS_ENV_NAMESPACE,
|
|
@@ -60830,7 +61075,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
60830
61075
|
files.push({
|
|
60831
61076
|
path: relativePath,
|
|
60832
61077
|
sizeBytes: bytes.byteLength,
|
|
60833
|
-
sha256:
|
|
61078
|
+
sha256: createHash23("sha256").update(bytes).digest("hex"),
|
|
60834
61079
|
...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
|
|
60835
61080
|
});
|
|
60836
61081
|
}
|
|
@@ -61123,16 +61368,16 @@ var init_private_publication_customer = __esm(() => {
|
|
|
61123
61368
|
|
|
61124
61369
|
// src/lib/private-publication-recovery.ts
|
|
61125
61370
|
import { constants as constants14, closeSync as closeSync18, fsyncSync as fsyncSync5, fstatSync as fstatSync18, lstatSync as lstatSync22, mkdirSync as mkdirSync16, openSync as openSync18, readSync as readSync12, realpathSync as realpathSync11, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
|
|
61126
|
-
import { dirname as
|
|
61371
|
+
import { dirname as dirname24, isAbsolute as isAbsolute20, join as join39, resolve as resolve22 } from "path";
|
|
61127
61372
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
61128
61373
|
function safeDirectory(directory2) {
|
|
61129
|
-
if (!
|
|
61374
|
+
if (!isAbsolute20(directory2) || directory2 !== resolve22(directory2) || realpathSync11(directory2) !== directory2)
|
|
61130
61375
|
return fail2();
|
|
61131
|
-
for (let path = directory2;; path =
|
|
61376
|
+
for (let path = directory2;; path = dirname24(path)) {
|
|
61132
61377
|
const stat3 = lstatSync22(path);
|
|
61133
61378
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
61134
61379
|
return fail2();
|
|
61135
|
-
if (path ===
|
|
61380
|
+
if (path === dirname24(path))
|
|
61136
61381
|
break;
|
|
61137
61382
|
}
|
|
61138
61383
|
const own2 = lstatSync22(directory2);
|
|
@@ -61264,11 +61509,11 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
|
|
|
61264
61509
|
phase: "prepared",
|
|
61265
61510
|
intent: null
|
|
61266
61511
|
};
|
|
61267
|
-
if (!
|
|
61512
|
+
if (!isAbsolute20(recoveryDirectory) || resolve22(recoveryDirectory) !== recoveryDirectory || realpathSync11(dirname24(recoveryDirectory)) !== dirname24(recoveryDirectory))
|
|
61268
61513
|
return fail2();
|
|
61269
61514
|
mkdirSync16(recoveryDirectory, { mode: 448 });
|
|
61270
61515
|
safeDirectory(recoveryDirectory);
|
|
61271
|
-
const parent = openSync18(
|
|
61516
|
+
const parent = openSync18(dirname24(recoveryDirectory), constants14.O_RDONLY | constants14.O_NOFOLLOW);
|
|
61272
61517
|
try {
|
|
61273
61518
|
fsyncSync5(parent);
|
|
61274
61519
|
} finally {
|
|
@@ -61365,10 +61610,10 @@ var init_private_publication_recovery = __esm(() => {
|
|
|
61365
61610
|
});
|
|
61366
61611
|
|
|
61367
61612
|
// src/mcp/private-publication-tools.ts
|
|
61368
|
-
import { isAbsolute as
|
|
61613
|
+
import { isAbsolute as isAbsolute21 } from "path";
|
|
61369
61614
|
function registerPrivatePublicationTools(server) {
|
|
61370
61615
|
const uuid9 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
|
|
61371
|
-
const directory2 = exports_external.string().max(4096).refine(
|
|
61616
|
+
const directory2 = exports_external.string().max(4096).refine(isAbsolute21, "Use an absolute local directory");
|
|
61372
61617
|
const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
|
|
61373
61618
|
const description = "Manage a private source publication using fresh workspace-bound verification and a host-local recovery directory. Publishing requires explicit UUID current-version comparison and upload consent. Resume reuses immutable saved bytes and intent; an uncertain PUT is finalized for server verification, never uploaded twice. Sessions and signed URLs are not returned or persisted. Private execution is unavailable. Host request history may contain the supplied verification code.";
|
|
61374
61619
|
const handler = (action) => async (value) => {
|
|
@@ -61780,8 +62025,8 @@ var WSContext = class {
|
|
|
61780
62025
|
}
|
|
61781
62026
|
url;
|
|
61782
62027
|
protocol;
|
|
61783
|
-
close(code2,
|
|
61784
|
-
this.#init.close(code2,
|
|
62028
|
+
close(code2, reason2) {
|
|
62029
|
+
this.#init.close(code2, reason2);
|
|
61785
62030
|
}
|
|
61786
62031
|
}, defineWebSocketHelper = (handler) => {
|
|
61787
62032
|
return (...args) => {
|
|
@@ -62061,9 +62306,9 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62061
62306
|
}, normalizeAbortError = (request2, incoming) => {
|
|
62062
62307
|
if (incoming.errored)
|
|
62063
62308
|
return incoming.errored;
|
|
62064
|
-
const
|
|
62065
|
-
if (
|
|
62066
|
-
return
|
|
62309
|
+
const reason2 = request2[abortReasonKey];
|
|
62310
|
+
if (reason2 !== undefined)
|
|
62311
|
+
return reason2 instanceof Error ? reason2 : new Error(String(reason2));
|
|
62067
62312
|
return /* @__PURE__ */ new Error("Client connection prematurely closed.");
|
|
62068
62313
|
}, readBodyDirect = (request2) => {
|
|
62069
62314
|
if (request2[bodyBufferKey])
|
|
@@ -62080,7 +62325,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62080
62325
|
request2[bodyBufferKey] = buffered;
|
|
62081
62326
|
return Promise.resolve(buffered);
|
|
62082
62327
|
}
|
|
62083
|
-
const promise3 = new Promise((
|
|
62328
|
+
const promise3 = new Promise((resolve23, reject) => {
|
|
62084
62329
|
const chunks = [];
|
|
62085
62330
|
let settled = false;
|
|
62086
62331
|
const finish = (callback) => {
|
|
@@ -62102,7 +62347,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62102
62347
|
reject(error61 ?? normalizeAbortError(request2, incoming));
|
|
62103
62348
|
else {
|
|
62104
62349
|
request2[bodyBufferKey] = recovered;
|
|
62105
|
-
|
|
62350
|
+
resolve23(recovered);
|
|
62106
62351
|
}
|
|
62107
62352
|
});
|
|
62108
62353
|
return true;
|
|
@@ -62114,7 +62359,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62114
62359
|
finish(() => {
|
|
62115
62360
|
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
|
|
62116
62361
|
request2[bodyBufferKey] = buffer;
|
|
62117
|
-
|
|
62362
|
+
resolve23(buffer);
|
|
62118
62363
|
});
|
|
62119
62364
|
};
|
|
62120
62365
|
const onError = (error61) => {
|
|
@@ -62388,7 +62633,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62388
62633
|
});
|
|
62389
62634
|
if (!chunk) {
|
|
62390
62635
|
if (i === 1) {
|
|
62391
|
-
await new Promise((
|
|
62636
|
+
await new Promise((resolve23) => setTimeout(resolve23));
|
|
62392
62637
|
maxReadCount = 3;
|
|
62393
62638
|
continue;
|
|
62394
62639
|
}
|
|
@@ -62689,12 +62934,12 @@ var init_dist2 = __esm(() => {
|
|
|
62689
62934
|
get headers() {
|
|
62690
62935
|
return this[headersKey] ||= newHeadersFromIncoming(this[incomingKey]);
|
|
62691
62936
|
},
|
|
62692
|
-
[abortRequest](
|
|
62937
|
+
[abortRequest](reason2) {
|
|
62693
62938
|
if (this[abortReasonKey] === undefined)
|
|
62694
|
-
this[abortReasonKey] =
|
|
62939
|
+
this[abortReasonKey] = reason2;
|
|
62695
62940
|
const abortController = this[abortControllerKey];
|
|
62696
62941
|
if (abortController && !abortController.signal.aborted)
|
|
62697
|
-
abortController.abort(
|
|
62942
|
+
abortController.abort(reason2);
|
|
62698
62943
|
},
|
|
62699
62944
|
[getAbortController]() {
|
|
62700
62945
|
this[abortControllerKey] ||= new AbortController;
|
|
@@ -63018,8 +63263,8 @@ var init_dist2 = __esm(() => {
|
|
|
63018
63263
|
ws.on("message", bufferMessage);
|
|
63019
63264
|
const ctx = {
|
|
63020
63265
|
binaryType: "arraybuffer",
|
|
63021
|
-
close(code2,
|
|
63022
|
-
ws.close(code2,
|
|
63266
|
+
close(code2, reason2) {
|
|
63267
|
+
ws.close(code2, reason2);
|
|
63023
63268
|
},
|
|
63024
63269
|
protocol: ws.protocol,
|
|
63025
63270
|
raw: ws,
|
|
@@ -63051,11 +63296,11 @@ var init_dist2 = __esm(() => {
|
|
|
63051
63296
|
ws.on("message", (data, isBinary) => {
|
|
63052
63297
|
handleMessage(data, isBinary);
|
|
63053
63298
|
});
|
|
63054
|
-
ws.on("close", (code2,
|
|
63299
|
+
ws.on("close", (code2, reason2) => {
|
|
63055
63300
|
try {
|
|
63056
63301
|
events2?.onClose?.(new CloseEvent("close", {
|
|
63057
63302
|
code: code2,
|
|
63058
|
-
reason:
|
|
63303
|
+
reason: reason2.toString()
|
|
63059
63304
|
}), ctx);
|
|
63060
63305
|
} catch (e2) {
|
|
63061
63306
|
(options?.onError ?? console.error)(e2);
|
|
@@ -63618,9 +63863,9 @@ data:
|
|
|
63618
63863
|
const initRequest = messages.find((m) => isInitializeRequest(m));
|
|
63619
63864
|
const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
|
63620
63865
|
if (this._enableJsonResponse) {
|
|
63621
|
-
return new Promise((
|
|
63866
|
+
return new Promise((resolve23) => {
|
|
63622
63867
|
this._streamMapping.set(streamId, {
|
|
63623
|
-
resolveJson:
|
|
63868
|
+
resolveJson: resolve23,
|
|
63624
63869
|
cleanup: () => {
|
|
63625
63870
|
this._streamMapping.delete(streamId);
|
|
63626
63871
|
}
|
|
@@ -63989,19 +64234,19 @@ async function connectMcpForNode() {
|
|
|
63989
64234
|
return { server: server2, transport };
|
|
63990
64235
|
}
|
|
63991
64236
|
function readBody(req) {
|
|
63992
|
-
return new Promise((
|
|
64237
|
+
return new Promise((resolve23, reject) => {
|
|
63993
64238
|
const chunks = [];
|
|
63994
64239
|
req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
63995
64240
|
req.on("end", () => {
|
|
63996
64241
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
63997
64242
|
if (!raw.trim()) {
|
|
63998
|
-
|
|
64243
|
+
resolve23(undefined);
|
|
63999
64244
|
return;
|
|
64000
64245
|
}
|
|
64001
64246
|
try {
|
|
64002
|
-
|
|
64247
|
+
resolve23(JSON.parse(raw));
|
|
64003
64248
|
} catch {
|
|
64004
|
-
|
|
64249
|
+
resolve23(undefined);
|
|
64005
64250
|
}
|
|
64006
64251
|
});
|
|
64007
64252
|
req.on("error", reject);
|
|
@@ -64043,9 +64288,9 @@ async function startSkillsMcpHttpServer(options = {}) {
|
|
|
64043
64288
|
}
|
|
64044
64289
|
}
|
|
64045
64290
|
});
|
|
64046
|
-
await new Promise((
|
|
64291
|
+
await new Promise((resolve23, reject) => {
|
|
64047
64292
|
httpServer.once("error", reject);
|
|
64048
|
-
httpServer.listen(port, hostname4, () =>
|
|
64293
|
+
httpServer.listen(port, hostname4, () => resolve23());
|
|
64049
64294
|
});
|
|
64050
64295
|
const address = httpServer.address();
|
|
64051
64296
|
const listenPort = typeof address === "object" && address ? address.port : port;
|