@hasna/skills 0.10.50 → 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 +86 -5
- package/bin/index.js +1827 -1374
- package/bin/maintenance.js +199 -2
- package/bin/mcp.js +730 -482
- 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 +1052 -704
- package/dist/lib/agent-discovery.d.ts +38 -2
- 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/codex-native-compatibility.d.ts +4 -1
- package/dist/lib/selection-cache.d.ts +2 -2
- package/dist/lib/session-reconciliation.d.ts +9 -0
- package/dist/sdk/index.js +1001 -658
- package/dist/server/maintenance-entry.d.ts +14 -0
- package/dist/server/schema-census.d.ts +77 -0
- package/docs/plugin-admission.md +190 -3
- 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) };
|
|
@@ -38538,8 +38542,216 @@ var init_sumi_settings_witness = __esm(() => {
|
|
|
38538
38542
|
SUMI_DISCOVERY_PROJECTION_FIELDS = ["skills", "plugin", "plugins", "permissions"];
|
|
38539
38543
|
});
|
|
38540
38544
|
|
|
38545
|
+
// src/lib/codex-native-compatibility.ts
|
|
38546
|
+
function supportsCodexNativeCapability(version2, capability) {
|
|
38547
|
+
return typeof version2 === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version2) && MEASURED_CODEX_CAPABILITIES[version2].includes(capability);
|
|
38548
|
+
}
|
|
38549
|
+
var MEASURED_CODEX_CAPABILITIES, SUPPORTED_CODEX_HOOK_VERSIONS;
|
|
38550
|
+
var init_codex_native_compatibility = __esm(() => {
|
|
38551
|
+
MEASURED_CODEX_CAPABILITIES = {
|
|
38552
|
+
"codex-cli 0.153.0": ["hooks"],
|
|
38553
|
+
"codex-cli 0.154.0": ["hooks"],
|
|
38554
|
+
"codex-cli 0.155.0": ["hooks"],
|
|
38555
|
+
"codex-cli 0.155.1": ["hooks"],
|
|
38556
|
+
"codex-cli 0.156.1": ["hooks"],
|
|
38557
|
+
"codex-cli 0.157.0": ["hooks"],
|
|
38558
|
+
"codex-cli 0.157.1": ["hooks"],
|
|
38559
|
+
"codex-cli 0.158.0": ["hooks"],
|
|
38560
|
+
"codex-cli 0.159.0": ["hooks"],
|
|
38561
|
+
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
38562
|
+
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog", "installed-plugin-review"],
|
|
38563
|
+
"codex-cli 0.160.1": ["hooks", "qualified-skill-catalog", "installed-plugin-review"]
|
|
38564
|
+
};
|
|
38565
|
+
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version2) => supportsCodexNativeCapability(version2, "hooks")));
|
|
38566
|
+
});
|
|
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
|
+
|
|
38541
38753
|
// src/lib/agent-policy-limits.ts
|
|
38542
|
-
import { basename as
|
|
38754
|
+
import { basename as basename5, isAbsolute as isAbsolute5, join as join10, resolve as resolve4, sep as sep3 } from "path";
|
|
38543
38755
|
function object4(value) {
|
|
38544
38756
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
38545
38757
|
}
|
|
@@ -38592,7 +38804,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38592
38804
|
text(control.pluginId, 1024);
|
|
38593
38805
|
text(control.namespace, 64);
|
|
38594
38806
|
text(control.pluginParent);
|
|
38595
|
-
requireBound(
|
|
38807
|
+
requireBound(isAbsolute5(control.pluginParent) && resolve4(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
|
|
38596
38808
|
if (control.remotePluginId !== undefined)
|
|
38597
38809
|
requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
|
|
38598
38810
|
if (control.skillsOnly !== undefined)
|
|
@@ -38604,16 +38816,24 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38604
38816
|
}
|
|
38605
38817
|
if (bridge.codexInactivePlugins !== undefined) {
|
|
38606
38818
|
const controls = array3(bridge.codexInactivePlugins, 4096), ids = new Set;
|
|
38607
|
-
requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version
|
|
38819
|
+
requireBound(controls.length === 0 || object4(bridge.codexPluginSkillReview) && supportsCodexNativeCapability(bridge.codexPluginSkillReview.version, "installed-plugin-review") && typeof bridge.codexPluginSkillReview.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(bridge.codexPluginSkillReview.catalogSha256));
|
|
38608
38820
|
for (const control of controls) {
|
|
38609
38821
|
requireBound(object4(control) && Object.keys(control).every((key) => ["pluginId", "namespace", "pluginParent", "sourceType", "sourceSha256"].includes(key)));
|
|
38610
38822
|
text(control.pluginId, 1024);
|
|
38611
38823
|
text(control.namespace, 64);
|
|
38612
38824
|
text(control.pluginParent);
|
|
38613
|
-
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));
|
|
38614
38826
|
ids.add(control.pluginId);
|
|
38615
38827
|
}
|
|
38616
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
|
+
}
|
|
38617
38837
|
if (bridge.disabledBuiltins !== undefined)
|
|
38618
38838
|
for (const builtin of array3(bridge.disabledBuiltins, AGENT_POLICY_LIMITS.builtinNames)) {
|
|
38619
38839
|
requireBound(object4(builtin));
|
|
@@ -38639,11 +38859,11 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38639
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);
|
|
38640
38860
|
for (const root of roots) {
|
|
38641
38861
|
text(root);
|
|
38642
|
-
requireBound(
|
|
38862
|
+
requireBound(isAbsolute5(root) && resolve4(root) === root);
|
|
38643
38863
|
}
|
|
38644
38864
|
for (const parent of parents2) {
|
|
38645
38865
|
text(parent);
|
|
38646
|
-
requireBound(
|
|
38866
|
+
requireBound(isAbsolute5(parent) && resolve4(parent) === parent);
|
|
38647
38867
|
}
|
|
38648
38868
|
for (const directory of array3(proof.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
|
|
38649
38869
|
requireBound(object4(directory));
|
|
@@ -38656,14 +38876,14 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38656
38876
|
}
|
|
38657
38877
|
if (value.codexInstallationInputs !== undefined) {
|
|
38658
38878
|
const proof = record3(value.codexInstallationInputs, 4), inputs = array3(proof.plugins, 4096), ids = new Set;
|
|
38659
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && proof.version
|
|
38879
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && supportsCodexNativeCapability(proof.version, "installed-plugin-review") && typeof proof.catalogSha256 === "string" && /^[a-f0-9]{64}$/.test(proof.catalogSha256) && inputs.length > 0 && object4(bridge.codexPluginSkillReview) && bridge.codexPluginSkillReview.version === proof.version && bridge.codexPluginSkillReview.catalogSha256 === proof.catalogSha256);
|
|
38660
38880
|
for (const input2 of inputs) {
|
|
38661
38881
|
requireBound(object4(input2) && Object.keys(input2).every((key) => ["pluginId", "namespace", "pluginParent", "sourceRoot", "sourceSha256"].includes(key)));
|
|
38662
38882
|
text(input2.pluginId, 1024);
|
|
38663
38883
|
text(input2.namespace, 64);
|
|
38664
38884
|
text(input2.pluginParent);
|
|
38665
38885
|
text(input2.sourceRoot);
|
|
38666
|
-
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));
|
|
38667
38887
|
ids.add(input2.pluginId);
|
|
38668
38888
|
}
|
|
38669
38889
|
if (proof.directories !== undefined)
|
|
@@ -38680,17 +38900,19 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38680
38900
|
text(source.path);
|
|
38681
38901
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
38682
38902
|
if (source.hashMode !== undefined)
|
|
38683
|
-
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));
|
|
38684
38904
|
if (source.hashMode === "claude-plugin-manifest-v1")
|
|
38685
|
-
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);
|
|
38686
38906
|
if (source.hashMode === "sumi-settings-v1")
|
|
38687
|
-
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");
|
|
38688
38908
|
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4"))
|
|
38689
|
-
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");
|
|
38690
38910
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "claude-settings-v4"))
|
|
38691
|
-
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");
|
|
38692
38912
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
|
|
38693
|
-
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));
|
|
38694
38916
|
if (source.hashMode === "claude-plugin-registry") {
|
|
38695
38917
|
requireBound(agent === "claude");
|
|
38696
38918
|
const managed = array3(source.managedPlugins, 64);
|
|
@@ -38705,8 +38927,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38705
38927
|
if (source.format !== undefined)
|
|
38706
38928
|
requireBound(["json", "toml", "yaml"].includes(source.format));
|
|
38707
38929
|
if (source.fields !== undefined)
|
|
38708
|
-
for (const
|
|
38709
|
-
text(
|
|
38930
|
+
for (const field2 of array3(source.fields, AGENT_POLICY_LIMITS.fields))
|
|
38931
|
+
text(field2, 256);
|
|
38710
38932
|
}
|
|
38711
38933
|
if (value.directories !== undefined)
|
|
38712
38934
|
for (const directory of array3(value.directories, AGENT_POLICY_LIMITS.discoveryDirectories)) {
|
|
@@ -38721,6 +38943,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38721
38943
|
}
|
|
38722
38944
|
var AGENT_POLICY_LIMITS;
|
|
38723
38945
|
var init_agent_policy_limits = __esm(() => {
|
|
38946
|
+
init_codex_native_compatibility();
|
|
38947
|
+
init_claude_marketplace_entry_witness();
|
|
38724
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 });
|
|
38725
38949
|
});
|
|
38726
38950
|
|
|
@@ -43945,8 +44169,8 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
43945
44169
|
visit2.REMOVE = REMOVE;
|
|
43946
44170
|
visit2.itemAtPath = (cst, path) => {
|
|
43947
44171
|
let item = cst;
|
|
43948
|
-
for (const [
|
|
43949
|
-
const tok = item?.[
|
|
44172
|
+
for (const [field2, index] of path) {
|
|
44173
|
+
const tok = item?.[field2];
|
|
43950
44174
|
if (tok && "items" in tok) {
|
|
43951
44175
|
item = tok.items[index];
|
|
43952
44176
|
} else
|
|
@@ -43956,8 +44180,8 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
43956
44180
|
};
|
|
43957
44181
|
visit2.parentCollection = (cst, path) => {
|
|
43958
44182
|
const parent = visit2.itemAtPath(cst, path.slice(0, -1));
|
|
43959
|
-
const
|
|
43960
|
-
const coll = parent?.[
|
|
44183
|
+
const field2 = path[path.length - 1][0];
|
|
44184
|
+
const coll = parent?.[field2];
|
|
43961
44185
|
if (coll && "items" in coll)
|
|
43962
44186
|
return coll;
|
|
43963
44187
|
throw new Error("Parent collection not found");
|
|
@@ -43966,11 +44190,11 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
43966
44190
|
let ctrl = visitor(item, path);
|
|
43967
44191
|
if (typeof ctrl === "symbol")
|
|
43968
44192
|
return ctrl;
|
|
43969
|
-
for (const
|
|
43970
|
-
const token = item[
|
|
44193
|
+
for (const field2 of ["key", "value"]) {
|
|
44194
|
+
const token = item[field2];
|
|
43971
44195
|
if (token && "items" in token) {
|
|
43972
44196
|
for (let i = 0;i < token.items.length; ++i) {
|
|
43973
|
-
const ci = _visit(Object.freeze(path.concat([[
|
|
44197
|
+
const ci = _visit(Object.freeze(path.concat([[field2, i]])), token.items[i], visitor);
|
|
43974
44198
|
if (typeof ci === "number")
|
|
43975
44199
|
i = ci - 1;
|
|
43976
44200
|
else if (ci === BREAK)
|
|
@@ -43980,7 +44204,7 @@ var require_cst_visit = __commonJS((exports) => {
|
|
|
43980
44204
|
i -= 1;
|
|
43981
44205
|
}
|
|
43982
44206
|
}
|
|
43983
|
-
if (typeof ctrl === "function" &&
|
|
44207
|
+
if (typeof ctrl === "function" && field2 === "key")
|
|
43984
44208
|
ctrl = ctrl(item, path);
|
|
43985
44209
|
}
|
|
43986
44210
|
}
|
|
@@ -44406,9 +44630,9 @@ var require_lexer = __commonJS((exports) => {
|
|
|
44406
44630
|
}
|
|
44407
44631
|
}
|
|
44408
44632
|
*parseQuotedScalar() {
|
|
44409
|
-
const
|
|
44410
|
-
let end = this.buffer.indexOf(
|
|
44411
|
-
if (
|
|
44633
|
+
const quote2 = this.charAt(0);
|
|
44634
|
+
let end = this.buffer.indexOf(quote2, this.pos + 1);
|
|
44635
|
+
if (quote2 === "'") {
|
|
44412
44636
|
while (end !== -1 && this.buffer[end + 1] === "'")
|
|
44413
44637
|
end = this.buffer.indexOf("'", end + 2);
|
|
44414
44638
|
} else {
|
|
@@ -45715,7 +45939,7 @@ var init_dist = __esm(() => {
|
|
|
45715
45939
|
});
|
|
45716
45940
|
|
|
45717
45941
|
// src/lib/agent-hermes.ts
|
|
45718
|
-
import { dirname as
|
|
45942
|
+
import { dirname as dirname6, isAbsolute as isAbsolute6, join as join11, resolve as resolve5 } from "path";
|
|
45719
45943
|
function object5(value) {
|
|
45720
45944
|
return Boolean(value && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null));
|
|
45721
45945
|
}
|
|
@@ -45749,7 +45973,7 @@ function assertHermesEnvironment(home) {
|
|
|
45749
45973
|
throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
|
|
45750
45974
|
}
|
|
45751
45975
|
const selected = process.env.HERMES_HOME?.trim();
|
|
45752
|
-
if (selected && (!
|
|
45976
|
+
if (selected && (!isAbsolute6(selected) || resolve5(selected) !== join11(resolve5(home), ".hermes")))
|
|
45753
45977
|
throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
|
|
45754
45978
|
if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
|
|
45755
45979
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
|
|
@@ -45759,18 +45983,18 @@ var init_agent_hermes = __esm(() => {
|
|
|
45759
45983
|
});
|
|
45760
45984
|
|
|
45761
45985
|
// src/lib/agent-discovery-directories.ts
|
|
45762
|
-
import { createHash as
|
|
45986
|
+
import { createHash as createHash4 } from "crypto";
|
|
45763
45987
|
import { lstatSync as lstatSync6, opendirSync } from "fs";
|
|
45764
|
-
import { dirname as
|
|
45765
|
-
function
|
|
45988
|
+
import { dirname as dirname7, isAbsolute as isAbsolute7, join as join12, resolve as resolve6 } from "path";
|
|
45989
|
+
function need3(value, message) {
|
|
45766
45990
|
if (!value)
|
|
45767
45991
|
throw new Error(message);
|
|
45768
45992
|
}
|
|
45769
45993
|
function safe(path) {
|
|
45770
|
-
|
|
45771
|
-
for (let cursor = path;; cursor =
|
|
45772
|
-
|
|
45773
|
-
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)
|
|
45774
45998
|
break;
|
|
45775
45999
|
}
|
|
45776
46000
|
}
|
|
@@ -45784,45 +46008,45 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
|
|
|
45784
46008
|
const root = lstatSync6(path, { throwIfNoEntry: false });
|
|
45785
46009
|
if (!root)
|
|
45786
46010
|
return { path, sha256: null };
|
|
45787
|
-
|
|
45788
|
-
const hash2 =
|
|
46011
|
+
need3(root.isDirectory(), "Unsupported native discovery directory input");
|
|
46012
|
+
const hash2 = createHash4("sha256");
|
|
45789
46013
|
function walk(current, relative3, before, depth) {
|
|
45790
|
-
|
|
46014
|
+
need3(depth <= 64, "Native discovery directory depth limit exceeded");
|
|
45791
46015
|
const names = [], directory = opendirSync(current);
|
|
45792
46016
|
try {
|
|
45793
46017
|
for (let entry = directory.readSync();entry; entry = directory.readSync()) {
|
|
45794
|
-
|
|
46018
|
+
need3(++budget2.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
|
|
45795
46019
|
names.push(entry.name);
|
|
45796
46020
|
}
|
|
45797
46021
|
} finally {
|
|
45798
46022
|
directory.closeSync();
|
|
45799
46023
|
}
|
|
45800
|
-
|
|
46024
|
+
need3(new Set(names).size === names.length, "Ambiguous native discovery directory names");
|
|
45801
46025
|
for (const name of names.sort()) {
|
|
45802
|
-
const
|
|
45803
|
-
if (omittedRoots.includes(
|
|
46026
|
+
const child2 = join12(current, name), childRelative = relative3 ? `${relative3}/${name}` : name;
|
|
46027
|
+
if (omittedRoots.includes(child2))
|
|
45804
46028
|
continue;
|
|
45805
|
-
|
|
45806
|
-
const stat = lstatSync6(
|
|
45807
|
-
|
|
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");
|
|
45808
46032
|
const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
|
|
45809
46033
|
`;
|
|
45810
46034
|
budget2.bytes += Buffer.byteLength(row);
|
|
45811
|
-
|
|
46035
|
+
need3(budget2.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
|
|
45812
46036
|
hash2.update(row);
|
|
45813
46037
|
rows?.push(row);
|
|
45814
|
-
if (stat.isDirectory() && !excludedRoots.includes(
|
|
45815
|
-
walk(
|
|
46038
|
+
if (stat.isDirectory() && !excludedRoots.includes(child2))
|
|
46039
|
+
walk(child2, childRelative, stat, depth + 1);
|
|
45816
46040
|
}
|
|
45817
|
-
|
|
46041
|
+
need3(same(before, lstatSync6(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
|
|
45818
46042
|
}
|
|
45819
46043
|
walk(path, "", root, 0);
|
|
45820
46044
|
safe(path);
|
|
45821
46045
|
return { path, sha256: hash2.digest("hex") };
|
|
45822
46046
|
}
|
|
45823
46047
|
function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
|
|
45824
|
-
|
|
45825
|
-
|
|
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");
|
|
45826
46050
|
for (const root of omittedRoots)
|
|
45827
46051
|
safe(root);
|
|
45828
46052
|
const budget2 = { entries: 0, bytes: 0 };
|
|
@@ -45832,65 +46056,65 @@ function captureDiscoveryDirectoryProjection(paths, omittedRoots) {
|
|
|
45832
46056
|
});
|
|
45833
46057
|
}
|
|
45834
46058
|
function verifyDiscoveryDirectoryProjection(directories, omittedRoots) {
|
|
45835
|
-
|
|
46059
|
+
need3(directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid projected discovery directory collection");
|
|
45836
46060
|
let count = 0, bytes = 0;
|
|
45837
46061
|
const expected = directories.map((directory) => {
|
|
45838
46062
|
safe(directory.path);
|
|
45839
|
-
|
|
45840
|
-
const hash2 =
|
|
46063
|
+
need3(Array.isArray(directory.entries), "Missing reviewed directory membership inventory");
|
|
46064
|
+
const hash2 = createHash4("sha256");
|
|
45841
46065
|
const kept = [];
|
|
45842
46066
|
for (const row of directory.entries) {
|
|
45843
|
-
|
|
46067
|
+
need3(typeof row === "string" && ++count <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Invalid reviewed directory membership rows");
|
|
45844
46068
|
bytes += Buffer.byteLength(row);
|
|
45845
|
-
|
|
46069
|
+
need3(bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Reviewed directory membership byte limit exceeded");
|
|
45846
46070
|
const value = JSON.parse(row);
|
|
45847
|
-
|
|
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) + `
|
|
45848
46072
|
`, "Invalid reviewed directory member");
|
|
45849
46073
|
hash2.update(row);
|
|
45850
46074
|
const path = join12(directory.path, value[0]);
|
|
45851
46075
|
if (!omittedRoots.some((root) => path === root || path.startsWith(root + "/")))
|
|
45852
46076
|
kept.push(row);
|
|
45853
46077
|
}
|
|
45854
|
-
|
|
46078
|
+
need3(directory.sha256 === null ? directory.entries.length === 0 : hash2.digest("hex") === directory.sha256, "Reviewed directory inventory does not match its fingerprint");
|
|
45855
46079
|
const absent = omittedRoots.some((root) => directory.path === root || directory.path.startsWith(root + "/"));
|
|
45856
|
-
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") };
|
|
45857
46081
|
});
|
|
45858
46082
|
const current = captureDiscoveryDirectoryProjection(directories.map((item) => item.path), omittedRoots);
|
|
45859
|
-
|
|
46083
|
+
need3(current.every((item, index) => item.sha256 === expected[index].sha256), "Native discovery directory membership changed outside retired Codex roots");
|
|
45860
46084
|
}
|
|
45861
46085
|
function captureDiscoveryDirectories(paths, excludedRoots = []) {
|
|
45862
|
-
|
|
46086
|
+
need3(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
|
|
45863
46087
|
const budget2 = { entries: 0, bytes: 0 };
|
|
45864
46088
|
for (const root of excludedRoots)
|
|
45865
46089
|
safe(root);
|
|
45866
46090
|
return paths.map((path) => capture(path, budget2, excludedRoots));
|
|
45867
46091
|
}
|
|
45868
46092
|
function verifyDiscoveryDirectories(directories, excludedRoots = []) {
|
|
45869
|
-
|
|
46093
|
+
need3(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
|
|
45870
46094
|
for (const directory of directories)
|
|
45871
|
-
|
|
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");
|
|
45872
46096
|
const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
|
|
45873
46097
|
for (let i = 0;i < directories.length; i++)
|
|
45874
|
-
|
|
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}`);
|
|
45875
46099
|
}
|
|
45876
46100
|
var init_agent_discovery_directories = __esm(() => {
|
|
45877
46101
|
init_agent_policy_limits();
|
|
45878
46102
|
});
|
|
45879
46103
|
|
|
45880
46104
|
// src/lib/agent-discovery-bytes.ts
|
|
45881
|
-
import { createHash as
|
|
46105
|
+
import { createHash as createHash5 } from "crypto";
|
|
45882
46106
|
import { closeSync as closeSync6, constants as constants3, fstatSync as fstatSync6, lstatSync as lstatSync7, openSync as openSync6, readSync as readSync3 } from "fs";
|
|
45883
|
-
import { dirname as
|
|
46107
|
+
import { dirname as dirname8, isAbsolute as isAbsolute8, resolve as resolve7 } from "path";
|
|
45884
46108
|
function discoveryByteBudget() {
|
|
45885
46109
|
return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
|
|
45886
46110
|
}
|
|
45887
46111
|
function safe2(path) {
|
|
45888
|
-
if (typeof path !== "string" || !
|
|
46112
|
+
if (typeof path !== "string" || !isAbsolute8(path) || path !== resolve7(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
|
|
45889
46113
|
throw new Error("Expected a canonical absolute raw discovery path");
|
|
45890
|
-
for (let cursor = path;; cursor =
|
|
46114
|
+
for (let cursor = path;; cursor = dirname8(cursor)) {
|
|
45891
46115
|
if (lstatSync7(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
45892
46116
|
throw new Error("Refusing symlink raw discovery input");
|
|
45893
|
-
if (
|
|
46117
|
+
if (dirname8(cursor) === cursor)
|
|
45894
46118
|
break;
|
|
45895
46119
|
}
|
|
45896
46120
|
}
|
|
@@ -45909,7 +46133,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
|
|
|
45909
46133
|
if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
|
|
45910
46134
|
throw new Error("Raw discovery file byte limit exceeded");
|
|
45911
46135
|
consume(budget2, bytes);
|
|
45912
|
-
return
|
|
46136
|
+
return createHash5("sha256").update(text2).digest("hex");
|
|
45913
46137
|
}
|
|
45914
46138
|
const initial = lstatSync7(path, { throwIfNoEntry: false });
|
|
45915
46139
|
if (!initial)
|
|
@@ -45923,7 +46147,7 @@ function hashRawDiscoveryFile(path, budget2, changes) {
|
|
|
45923
46147
|
const opened = fstatSync6(fd);
|
|
45924
46148
|
if (!opened.isFile() || !same2(initial, opened))
|
|
45925
46149
|
throw new Error("Raw discovery input changed during open");
|
|
45926
|
-
const hash2 =
|
|
46150
|
+
const hash2 = createHash5("sha256"), buffer = Buffer.alloc(64 * 1024);
|
|
45927
46151
|
let bytes = 0;
|
|
45928
46152
|
while (true) {
|
|
45929
46153
|
const count = readSync3(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
|
|
@@ -45949,9 +46173,9 @@ var init_agent_discovery_bytes = __esm(() => {
|
|
|
45949
46173
|
});
|
|
45950
46174
|
|
|
45951
46175
|
// src/lib/agent-discovery-path-bytes.ts
|
|
45952
|
-
import { createHash as
|
|
46176
|
+
import { createHash as createHash6 } from "crypto";
|
|
45953
46177
|
import { lstatSync as lstatSync8, readlinkSync } from "fs";
|
|
45954
|
-
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";
|
|
45955
46179
|
function identity2(stat, mutable = false) {
|
|
45956
46180
|
return {
|
|
45957
46181
|
dev: String(stat.dev),
|
|
@@ -45962,12 +46186,12 @@ function identity2(stat, mutable = false) {
|
|
|
45962
46186
|
...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
|
|
45963
46187
|
};
|
|
45964
46188
|
}
|
|
45965
|
-
function
|
|
45966
|
-
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)
|
|
45967
46191
|
throw new Error("Expected a canonical absolute discovery path");
|
|
45968
46192
|
}
|
|
45969
46193
|
function trace(path) {
|
|
45970
|
-
|
|
46194
|
+
canonical3(path);
|
|
45971
46195
|
const rows = [], paths = [];
|
|
45972
46196
|
let metadataBytes = 0, steps = 0, links = 0, cursor = parse7(path).root, pending = path.slice(cursor.length).split(sep4);
|
|
45973
46197
|
function record4(path2, row) {
|
|
@@ -45992,7 +46216,7 @@ function trace(path) {
|
|
|
45992
46216
|
if (!component || component === ".")
|
|
45993
46217
|
continue;
|
|
45994
46218
|
if (component === "..") {
|
|
45995
|
-
cursor =
|
|
46219
|
+
cursor = dirname9(cursor);
|
|
45996
46220
|
continue;
|
|
45997
46221
|
}
|
|
45998
46222
|
const candidate = join13(cursor, component);
|
|
@@ -46012,11 +46236,11 @@ function trace(path) {
|
|
|
46012
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)))
|
|
46013
46237
|
throw new Error("Discovery link changed during read");
|
|
46014
46238
|
record4(candidate, { type: "link", target, ...identity2(stat, true) });
|
|
46015
|
-
if (
|
|
46239
|
+
if (isAbsolute9(target)) {
|
|
46016
46240
|
cursor = parse7(target).root;
|
|
46017
46241
|
root();
|
|
46018
46242
|
}
|
|
46019
|
-
const remainder =
|
|
46243
|
+
const remainder = isAbsolute9(target) ? target.slice(parse7(target).root.length) : target;
|
|
46020
46244
|
pending = [...remainder.split(sep4), ...pending];
|
|
46021
46245
|
if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
|
|
46022
46246
|
throw new Error("Discovery path step limit exceeded");
|
|
@@ -46059,7 +46283,7 @@ function hashDiscoveryPathFile(path, budget2, changes) {
|
|
|
46059
46283
|
const after = trace(path);
|
|
46060
46284
|
if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
|
|
46061
46285
|
throw new Error("Discovery path input changed during read");
|
|
46062
|
-
return
|
|
46286
|
+
return createHash6("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
|
|
46063
46287
|
}
|
|
46064
46288
|
var init_agent_discovery_path_bytes = __esm(() => {
|
|
46065
46289
|
init_agent_policy_limits();
|
|
@@ -46067,10 +46291,10 @@ var init_agent_discovery_path_bytes = __esm(() => {
|
|
|
46067
46291
|
});
|
|
46068
46292
|
|
|
46069
46293
|
// src/lib/claude-plugin-manifest-witness.ts
|
|
46070
|
-
import { createHash as
|
|
46071
|
-
function requireValue(value,
|
|
46294
|
+
import { createHash as createHash7 } from "crypto";
|
|
46295
|
+
function requireValue(value, reason2) {
|
|
46072
46296
|
if (!value)
|
|
46073
|
-
throw new Error("Claude plugin manifest " +
|
|
46297
|
+
throw new Error("Claude plugin manifest " + reason2);
|
|
46074
46298
|
}
|
|
46075
46299
|
function parse8(text2) {
|
|
46076
46300
|
requireValue(Buffer.byteLength(text2, "utf8") <= CLAUDE_PLUGIN_MANIFEST_LIMITS.bytes, "exceeds its byte limit");
|
|
@@ -46146,7 +46370,7 @@ function parse8(text2) {
|
|
|
46146
46370
|
requireValue(at === text2.length && root.kind === "object", "requires a JSON object without trailing content");
|
|
46147
46371
|
return root;
|
|
46148
46372
|
}
|
|
46149
|
-
function
|
|
46373
|
+
function canonical4(value) {
|
|
46150
46374
|
if (value.kind === "string")
|
|
46151
46375
|
return JSON.stringify(value.value);
|
|
46152
46376
|
if (value.kind === "number")
|
|
@@ -46154,18 +46378,18 @@ function canonical3(value) {
|
|
|
46154
46378
|
if (value.kind === "literal")
|
|
46155
46379
|
return value.value;
|
|
46156
46380
|
if (value.kind === "array")
|
|
46157
|
-
return "[" + value.items.map(
|
|
46158
|
-
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(",") + "}";
|
|
46159
46383
|
}
|
|
46160
|
-
function validateText(value,
|
|
46161
|
-
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");
|
|
46162
46386
|
}
|
|
46163
46387
|
function validateDescriptiveFields(manifest) {
|
|
46164
46388
|
const values = new Map(manifest.entries);
|
|
46165
|
-
for (const
|
|
46166
|
-
const value = values.get(
|
|
46389
|
+
for (const field2 of ["description", "version", "homepage", "license"]) {
|
|
46390
|
+
const value = values.get(field2);
|
|
46167
46391
|
if (value !== undefined)
|
|
46168
|
-
validateText(value,
|
|
46392
|
+
validateText(value, field2);
|
|
46169
46393
|
}
|
|
46170
46394
|
const author = values.get("author");
|
|
46171
46395
|
if (author !== undefined) {
|
|
@@ -46190,10 +46414,10 @@ function hashClaudePluginManifest(text2) {
|
|
|
46190
46414
|
const manifest = parse8(text2);
|
|
46191
46415
|
validateDescriptiveFields(manifest);
|
|
46192
46416
|
const discovery = { kind: "object", entries: manifest.entries.filter(([key]) => !DESCRIPTIVE_FIELDS.has(key)) };
|
|
46193
|
-
return
|
|
46417
|
+
return createHash7("sha256").update(canonical4(discovery)).digest("hex");
|
|
46194
46418
|
}
|
|
46195
46419
|
function projectReviewedClaudePluginManifest(text2, reviewedSha256) {
|
|
46196
|
-
if (!/^[a-f0-9]{64}$/.test(reviewedSha256) ||
|
|
46420
|
+
if (!/^[a-f0-9]{64}$/.test(reviewedSha256) || createHash7("sha256").update(text2).digest("hex") !== reviewedSha256) {
|
|
46197
46421
|
throw new Error("Reviewed Claude plugin manifest changed before semantic projection");
|
|
46198
46422
|
}
|
|
46199
46423
|
return hashClaudePluginManifest(text2);
|
|
@@ -46205,7 +46429,7 @@ var init_claude_plugin_manifest_witness = __esm(() => {
|
|
|
46205
46429
|
});
|
|
46206
46430
|
|
|
46207
46431
|
// src/lib/skill-bundle.ts
|
|
46208
|
-
import { createHash as
|
|
46432
|
+
import { createHash as createHash8 } from "crypto";
|
|
46209
46433
|
import { readFileSync as readFileSync9, readdirSync as readdirSync4, statSync as statSync6 } from "fs";
|
|
46210
46434
|
import { join as join14, relative as relative3 } from "path";
|
|
46211
46435
|
import { createGunzip } from "zlib";
|
|
@@ -46237,7 +46461,7 @@ function ownBytes(view) {
|
|
|
46237
46461
|
return out;
|
|
46238
46462
|
}
|
|
46239
46463
|
function sha256Hex(bytes) {
|
|
46240
|
-
return
|
|
46464
|
+
return createHash8("sha256").update(bytes).digest("hex");
|
|
46241
46465
|
}
|
|
46242
46466
|
function collectSkillBundleEntries(dir) {
|
|
46243
46467
|
const entries = [];
|
|
@@ -46365,12 +46589,12 @@ function inspectionLimits(options) {
|
|
|
46365
46589
|
for (const key of Object.keys(options.limits ?? {})) {
|
|
46366
46590
|
if (!Object.hasOwn(limits, key))
|
|
46367
46591
|
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Unknown bundle limit");
|
|
46368
|
-
const
|
|
46369
|
-
const value = options.limits[
|
|
46370
|
-
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]) {
|
|
46371
46595
|
throw new SkillBundleInspectionError("BUNDLE_LIMIT", "Bundle limits must be positive integers within the hard ceilings");
|
|
46372
46596
|
}
|
|
46373
|
-
limits[
|
|
46597
|
+
limits[field2] = value;
|
|
46374
46598
|
}
|
|
46375
46599
|
return limits;
|
|
46376
46600
|
}
|
|
@@ -46400,7 +46624,14 @@ async function inspectSkillBundle(bundle, options = {}) {
|
|
|
46400
46624
|
decoder.destroy(terminalError);
|
|
46401
46625
|
};
|
|
46402
46626
|
const onAbort = () => stop("BUNDLE_ABORTED");
|
|
46403
|
-
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())));
|
|
46404
46635
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
46405
46636
|
let decompressedByteSize = 0;
|
|
46406
46637
|
let bytesSinceYield = 0;
|
|
@@ -46415,7 +46646,7 @@ async function inspectSkillBundle(bundle, options = {}) {
|
|
|
46415
46646
|
parser2.push(chunk);
|
|
46416
46647
|
bytesSinceYield += chunk.byteLength;
|
|
46417
46648
|
if (bytesSinceYield >= 256 * 1024) {
|
|
46418
|
-
await new Promise((
|
|
46649
|
+
await new Promise((resolve9) => setTimeout(resolve9, 0));
|
|
46419
46650
|
bytesSinceYield = 0;
|
|
46420
46651
|
check2();
|
|
46421
46652
|
}
|
|
@@ -46552,8 +46783,8 @@ class BoundedTarReader {
|
|
|
46552
46783
|
}
|
|
46553
46784
|
}
|
|
46554
46785
|
}
|
|
46555
|
-
function tarOctal(
|
|
46556
|
-
const text2 = new TextDecoder().decode(
|
|
46786
|
+
function tarOctal(field2) {
|
|
46787
|
+
const text2 = new TextDecoder().decode(field2);
|
|
46557
46788
|
if (!/^[0-7]+[\0 ]*$/.test(text2))
|
|
46558
46789
|
invalidBundle("Invalid tar octal field");
|
|
46559
46790
|
const value = Number.parseInt(text2, 8);
|
|
@@ -46772,21 +47003,21 @@ var init_profile_limits = __esm(() => {
|
|
|
46772
47003
|
});
|
|
46773
47004
|
|
|
46774
47005
|
// src/lib/selection-cache.ts
|
|
46775
|
-
import { createHash as
|
|
47006
|
+
import { createHash as createHash9, randomUUID } from "crypto";
|
|
46776
47007
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
46777
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";
|
|
46778
47009
|
import { hostname as hostname3 } from "os";
|
|
46779
|
-
import { dirname as
|
|
47010
|
+
import { dirname as dirname10, join as join15, parse as parse9, resolve as resolve9 } from "path";
|
|
46780
47011
|
import { isDeepStrictEqual } from "util";
|
|
46781
47012
|
function selectionCacheRoot(options = {}) {
|
|
46782
|
-
return
|
|
47013
|
+
return resolve9(options.cacheDir ?? join15(getDataDirReadOnly(), "selection-cache"));
|
|
46783
47014
|
}
|
|
46784
47015
|
function selectionKey(selection) {
|
|
46785
47016
|
validateSelection(selection);
|
|
46786
47017
|
return hash2([selection.authority, selection.workspaceId, selection.slug, selection.version, selection.bundleDigest]);
|
|
46787
47018
|
}
|
|
46788
47019
|
function hash2(value) {
|
|
46789
|
-
return
|
|
47020
|
+
return createHash9("sha256").update(JSON.stringify(value)).digest("hex");
|
|
46790
47021
|
}
|
|
46791
47022
|
function validateSelection(selection) {
|
|
46792
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()) {
|
|
@@ -46826,7 +47057,7 @@ function selectionBundlePath(selection, options = {}) {
|
|
|
46826
47057
|
return join15(selectionCacheRoot(options), "objects", hash2(selection.authority), hash2(selection.workspaceId), `${selection.bundleDigest.slice(7)}.tar.gz`);
|
|
46827
47058
|
}
|
|
46828
47059
|
function assertRegularPath(path, createParents = false) {
|
|
46829
|
-
const absolute =
|
|
47060
|
+
const absolute = resolve9(path);
|
|
46830
47061
|
const root = parse9(absolute).root;
|
|
46831
47062
|
let cursor = root;
|
|
46832
47063
|
const segments = absolute.slice(root.length).split("/");
|
|
@@ -46883,7 +47114,7 @@ function writeSelectionJson(path, value) {
|
|
|
46883
47114
|
}
|
|
46884
47115
|
function atomicWrite(path, bytes, mode, durable = false) {
|
|
46885
47116
|
assertRegularPath(path, true);
|
|
46886
|
-
const temporary = join15(
|
|
47117
|
+
const temporary = join15(dirname10(path), `.selection-${randomUUID()}.tmp`);
|
|
46887
47118
|
try {
|
|
46888
47119
|
const fd = openSync7(temporary, constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW, mode);
|
|
46889
47120
|
try {
|
|
@@ -46895,7 +47126,7 @@ function atomicWrite(path, bytes, mode, durable = false) {
|
|
|
46895
47126
|
}
|
|
46896
47127
|
renameSync(temporary, path);
|
|
46897
47128
|
if (durable)
|
|
46898
|
-
syncDirectory(
|
|
47129
|
+
syncDirectory(dirname10(path));
|
|
46899
47130
|
} finally {
|
|
46900
47131
|
try {
|
|
46901
47132
|
unlinkSync(temporary);
|
|
@@ -46905,8 +47136,8 @@ function atomicWrite(path, bytes, mode, durable = false) {
|
|
|
46905
47136
|
}
|
|
46906
47137
|
}
|
|
46907
47138
|
}
|
|
46908
|
-
function readSelectionJson(path) {
|
|
46909
|
-
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));
|
|
46910
47141
|
if (!bytes)
|
|
46911
47142
|
return null;
|
|
46912
47143
|
try {
|
|
@@ -46918,10 +47149,10 @@ function readSelectionJson(path) {
|
|
|
46918
47149
|
async function verifiedEntries(selection, bytes, signal, deadline) {
|
|
46919
47150
|
if (`sha256:${sha256Hex(bytes)}` !== selection.bundleDigest)
|
|
46920
47151
|
throw new SkillSelectionError("BUNDLE_DIGEST_MISMATCH", "The skill bundle does not match its selected digest.");
|
|
46921
|
-
const remaining = deadline === undefined ? undefined : Math.
|
|
47152
|
+
const remaining = deadline === undefined ? undefined : Math.ceil(deadline - performance.now());
|
|
46922
47153
|
signal?.throwIfAborted();
|
|
46923
47154
|
if (remaining !== undefined && remaining <= 0)
|
|
46924
|
-
throw new
|
|
47155
|
+
throw new SkillBundleInspectionError("BUNDLE_TIMEOUT", "Bundle inspection deadline exceeded");
|
|
46925
47156
|
const bundle = await inspectSkillBundle(bytes, { signal, ...remaining === undefined ? {} : { limits: { timeoutMs: remaining } } });
|
|
46926
47157
|
return bundle.entries;
|
|
46927
47158
|
}
|
|
@@ -47021,7 +47252,7 @@ function assertFreshCachedProfile(receipt, options = {}) {
|
|
|
47021
47252
|
}
|
|
47022
47253
|
}
|
|
47023
47254
|
function projectSelectionLockPath(projectDir) {
|
|
47024
|
-
return join15(
|
|
47255
|
+
return join15(resolve9(projectDir), ".skills", SELECTION_LOCK_FILE);
|
|
47025
47256
|
}
|
|
47026
47257
|
function readProjectSelection(projectDir) {
|
|
47027
47258
|
const receipt = readSelectionJson(projectSelectionLockPath(projectDir));
|
|
@@ -47172,13 +47403,13 @@ function publishSessionLock(path, marker) {
|
|
|
47172
47403
|
fsyncSync(fd);
|
|
47173
47404
|
linkSync(stagingPath, path);
|
|
47174
47405
|
published = true;
|
|
47175
|
-
syncDirectory(
|
|
47406
|
+
syncDirectory(dirname10(path));
|
|
47176
47407
|
const staged = lstatSync9(stagingPath);
|
|
47177
47408
|
if (!staged.isFile() || staged.dev !== stat.dev || staged.ino !== stat.ino) {
|
|
47178
47409
|
throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "The initialized lock staging inode changed before publication completed.");
|
|
47179
47410
|
}
|
|
47180
47411
|
unlinkSync(stagingPath);
|
|
47181
|
-
syncDirectory(
|
|
47412
|
+
syncDirectory(dirname10(path));
|
|
47182
47413
|
handedOff = true;
|
|
47183
47414
|
return { path, stagingPath, fd, dev: stat.dev, ino: stat.ino };
|
|
47184
47415
|
} finally {
|
|
@@ -47223,14 +47454,14 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
47223
47454
|
writeFileSync3(guardFd, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, operationId: randomUUID() })}
|
|
47224
47455
|
`);
|
|
47225
47456
|
fsyncSync(guardFd);
|
|
47226
|
-
const cacheOptions = { cacheDir:
|
|
47457
|
+
const cacheOptions = { cacheDir: dirname10(dirname10(lock.path)) };
|
|
47227
47458
|
const current = readSessionLock(lock.marker.sessionId, cacheOptions);
|
|
47228
47459
|
if (!current || current.dev !== lock.dev || current.ino !== lock.ino || current.sha256 !== lock.sha256 || current.mtimeMs !== lock.mtimeMs || !writerIsGone(current, explicitLocalHost))
|
|
47229
47460
|
return null;
|
|
47230
47461
|
const currentReceipt = readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions);
|
|
47231
47462
|
if (currentReceipt?.sha256 !== receipt?.sha256 || currentReceipt?.generation !== receipt?.generation)
|
|
47232
47463
|
return null;
|
|
47233
|
-
const directory = join15(
|
|
47464
|
+
const directory = join15(dirname10(dirname10(lock.path)), "session-lock-recoveries", randomUUID());
|
|
47234
47465
|
const archivePath = join15(directory, "original.write-lock");
|
|
47235
47466
|
const recordPath = join15(directory, "recovery.json");
|
|
47236
47467
|
assertRegularPath(archivePath, true);
|
|
@@ -47247,7 +47478,7 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
47247
47478
|
})}
|
|
47248
47479
|
`));
|
|
47249
47480
|
syncDirectory(directory);
|
|
47250
|
-
syncDirectory(
|
|
47481
|
+
syncDirectory(dirname10(directory));
|
|
47251
47482
|
const finalLock = readSessionLock(lock.marker.sessionId, cacheOptions);
|
|
47252
47483
|
if (!finalLock || finalLock.dev !== lock.dev || finalLock.ino !== lock.ino || finalLock.sha256 !== lock.sha256 || readSkillSessionSnapshotIfExists(lock.marker.sessionId, cacheOptions)?.sha256 !== receipt?.sha256)
|
|
47253
47484
|
return null;
|
|
@@ -47262,7 +47493,7 @@ function archiveSessionLock(lock, receipt, explicitLocalHost) {
|
|
|
47262
47493
|
archivedPaths.push(publicationPath);
|
|
47263
47494
|
}
|
|
47264
47495
|
syncDirectory(directory);
|
|
47265
|
-
syncDirectory(
|
|
47496
|
+
syncDirectory(dirname10(lock.path));
|
|
47266
47497
|
for (const path of archivedPaths) {
|
|
47267
47498
|
const before = lstatSync9(path, { throwIfNoEntry: false });
|
|
47268
47499
|
const bytes = readRegularFile(path, SESSION_LOCK_MAX_BYTES);
|
|
@@ -47413,8 +47644,8 @@ var init_selection_cache = __esm(() => {
|
|
|
47413
47644
|
init_profile_limits();
|
|
47414
47645
|
SkillSelectionError = class SkillSelectionError extends Error {
|
|
47415
47646
|
code;
|
|
47416
|
-
constructor(code, message) {
|
|
47417
|
-
super(message);
|
|
47647
|
+
constructor(code, message, options) {
|
|
47648
|
+
super(message, options);
|
|
47418
47649
|
this.code = code;
|
|
47419
47650
|
this.name = "SkillSelectionError";
|
|
47420
47651
|
}
|
|
@@ -47431,7 +47662,7 @@ __export(exports_remote_files, {
|
|
|
47431
47662
|
decodeRemoteFiles: () => decodeRemoteFiles,
|
|
47432
47663
|
MAX_REMOTE_FILE_BYTES: () => MAX_REMOTE_FILE_BYTES
|
|
47433
47664
|
});
|
|
47434
|
-
import { createHash as
|
|
47665
|
+
import { createHash as createHash10 } from "crypto";
|
|
47435
47666
|
function describeRemoteFiles(files) {
|
|
47436
47667
|
if (files.length > 10)
|
|
47437
47668
|
throw new Error("At most 10 input files are supported");
|
|
@@ -47448,7 +47679,7 @@ function describeRemoteFiles(files) {
|
|
|
47448
47679
|
});
|
|
47449
47680
|
}
|
|
47450
47681
|
function sha256(bytes) {
|
|
47451
|
-
return
|
|
47682
|
+
return createHash10("sha256").update(bytes).digest("hex");
|
|
47452
47683
|
}
|
|
47453
47684
|
async function readBoundedResponse(response, maximum, signal) {
|
|
47454
47685
|
if (!Number.isSafeInteger(maximum) || maximum < 0 || maximum > MAX_REMOTE_FILE_BYTES)
|
|
@@ -47524,6 +47755,10 @@ function identifier(value) {
|
|
|
47524
47755
|
function invalid() {
|
|
47525
47756
|
throw new Error("The Skills API returned an invalid profile response");
|
|
47526
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
|
+
}
|
|
47527
47762
|
function validateSelection2(value) {
|
|
47528
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))
|
|
47529
47764
|
invalid();
|
|
@@ -47571,8 +47806,8 @@ class HttpProfileClient {
|
|
|
47571
47806
|
...init.headers
|
|
47572
47807
|
}
|
|
47573
47808
|
});
|
|
47574
|
-
} catch {
|
|
47575
|
-
throw
|
|
47809
|
+
} catch (error61) {
|
|
47810
|
+
throw unavailable(error61, "Unable to reach the configured Skills API");
|
|
47576
47811
|
}
|
|
47577
47812
|
if (!response.ok) {
|
|
47578
47813
|
response.body?.cancel().catch(() => {});
|
|
@@ -47589,7 +47824,9 @@ class HttpProfileClient {
|
|
|
47589
47824
|
async read(response, limit = MAX_PROFILE_DOCUMENT_BYTES) {
|
|
47590
47825
|
try {
|
|
47591
47826
|
return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit, this.signal)));
|
|
47592
|
-
} catch {
|
|
47827
|
+
} catch (error61) {
|
|
47828
|
+
if (this.signal?.aborted)
|
|
47829
|
+
throw unavailable(this.signal.reason ?? error61, "The Skills API response was cut short");
|
|
47593
47830
|
invalid();
|
|
47594
47831
|
}
|
|
47595
47832
|
}
|
|
@@ -47679,17 +47916,17 @@ var init_profile_client = __esm(() => {
|
|
|
47679
47916
|
});
|
|
47680
47917
|
|
|
47681
47918
|
// src/lib/preparation-process.ts
|
|
47682
|
-
function capturePreparationProcess(
|
|
47919
|
+
function capturePreparationProcess(child2, platform = process.platform, signalGroup = (pid, signal) => process.kill(pid, signal)) {
|
|
47683
47920
|
let spawnedPid;
|
|
47684
47921
|
try {
|
|
47685
|
-
spawnedPid =
|
|
47922
|
+
spawnedPid = child2.pid;
|
|
47686
47923
|
} catch {}
|
|
47687
47924
|
const groupId = typeof spawnedPid === "number" && Number.isSafeInteger(spawnedPid) && spawnedPid > 1 ? spawnedPid : undefined;
|
|
47688
47925
|
const canSignalGroup = platform !== "win32" && groupId !== undefined;
|
|
47689
47926
|
const killLiveChild = () => {
|
|
47690
|
-
if (
|
|
47927
|
+
if (child2.exitCode === null && child2.signalCode === null) {
|
|
47691
47928
|
try {
|
|
47692
|
-
|
|
47929
|
+
child2.kill("SIGKILL");
|
|
47693
47930
|
} catch {}
|
|
47694
47931
|
}
|
|
47695
47932
|
};
|
|
@@ -47952,28 +48189,6 @@ function isCodexLocalStdioMcpServer(name, server) {
|
|
|
47952
48189
|
}
|
|
47953
48190
|
}
|
|
47954
48191
|
|
|
47955
|
-
// src/lib/codex-native-compatibility.ts
|
|
47956
|
-
function supportsCodexNativeCapability(version2, capability) {
|
|
47957
|
-
return typeof version2 === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version2) && MEASURED_CODEX_CAPABILITIES[version2].includes(capability);
|
|
47958
|
-
}
|
|
47959
|
-
var MEASURED_CODEX_CAPABILITIES, SUPPORTED_CODEX_HOOK_VERSIONS;
|
|
47960
|
-
var init_codex_native_compatibility = __esm(() => {
|
|
47961
|
-
MEASURED_CODEX_CAPABILITIES = {
|
|
47962
|
-
"codex-cli 0.153.0": ["hooks"],
|
|
47963
|
-
"codex-cli 0.154.0": ["hooks"],
|
|
47964
|
-
"codex-cli 0.155.0": ["hooks"],
|
|
47965
|
-
"codex-cli 0.155.1": ["hooks"],
|
|
47966
|
-
"codex-cli 0.156.1": ["hooks"],
|
|
47967
|
-
"codex-cli 0.157.0": ["hooks"],
|
|
47968
|
-
"codex-cli 0.157.1": ["hooks"],
|
|
47969
|
-
"codex-cli 0.158.0": ["hooks"],
|
|
47970
|
-
"codex-cli 0.159.0": ["hooks"],
|
|
47971
|
-
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
47972
|
-
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
|
|
47973
|
-
};
|
|
47974
|
-
SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version2) => supportsCodexNativeCapability(version2, "hooks")));
|
|
47975
|
-
});
|
|
47976
|
-
|
|
47977
48192
|
// src/lib/codex-hook-rpc.ts
|
|
47978
48193
|
var init_codex_hook_rpc = __esm(() => {
|
|
47979
48194
|
init_codex_corpus_write();
|
|
@@ -47994,7 +48209,7 @@ var init_codex_native_skill_catalog = __esm(() => {
|
|
|
47994
48209
|
});
|
|
47995
48210
|
|
|
47996
48211
|
// src/lib/codex-plugin-skill-controls.ts
|
|
47997
|
-
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";
|
|
47998
48213
|
import { lstatSync as lstatSync11, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync3 } from "fs";
|
|
47999
48214
|
function refuse() {
|
|
48000
48215
|
throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
|
|
@@ -48058,7 +48273,7 @@ function mcpControls(path, read) {
|
|
|
48058
48273
|
function isBundledCleanupHooks(root, namespace, value) {
|
|
48059
48274
|
const object7 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
|
|
48060
48275
|
const exactKeys = (v, keys) => Object.keys(v).length === keys.length && keys.every((key) => Object.hasOwn(v, key));
|
|
48061
|
-
if (
|
|
48276
|
+
if (basename6(dirname11(root)) !== namespace || basename6(dirname11(dirname11(root))) !== "openai-bundled")
|
|
48062
48277
|
return false;
|
|
48063
48278
|
const server = namespace === "unified-computer-use" ? "cua_repl" : ["browser", "chrome", "chrome-dev", "chrome-internal", "computer-use"].includes(namespace) ? "node_repl" : undefined;
|
|
48064
48279
|
if (!server || !object7(value) || !exactKeys(value, ["hooks"]) || !object7(value.hooks))
|
|
@@ -48092,7 +48307,7 @@ function rootControls(root, read) {
|
|
|
48092
48307
|
}
|
|
48093
48308
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
|
|
48094
48309
|
refuse();
|
|
48095
|
-
const cacheVersion =
|
|
48310
|
+
const cacheVersion = basename6(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
48096
48311
|
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
48097
48312
|
refuse();
|
|
48098
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 }))
|
|
@@ -48116,13 +48331,13 @@ function rootControls(root, read) {
|
|
|
48116
48331
|
function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
48117
48332
|
try {
|
|
48118
48333
|
const parts = relative4(cache, parent).split(sep5), enrolled = controls.filter((control) => control.pluginParent === parent);
|
|
48119
|
-
if (
|
|
48334
|
+
if (resolve10(parent) !== parent || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !enrolled.length || !Array.isArray(rules))
|
|
48120
48335
|
return false;
|
|
48121
|
-
for (let cursor = parent;; cursor =
|
|
48336
|
+
for (let cursor = parent;; cursor = dirname11(cursor)) {
|
|
48122
48337
|
const stat = lstatSync11(cursor, { throwIfNoEntry: false });
|
|
48123
48338
|
if (stat && (!stat.isDirectory() || stat.isSymbolicLink()))
|
|
48124
48339
|
return false;
|
|
48125
|
-
if (
|
|
48340
|
+
if (dirname11(cursor) === cursor)
|
|
48126
48341
|
break;
|
|
48127
48342
|
}
|
|
48128
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));
|
|
@@ -48135,14 +48350,14 @@ function absentDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
|
48135
48350
|
}
|
|
48136
48351
|
function reviewedRetiredCodexRoot(cache, root, controls, rules, read, allowAbsent = false) {
|
|
48137
48352
|
try {
|
|
48138
|
-
const parent =
|
|
48139
|
-
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))
|
|
48140
48355
|
return false;
|
|
48141
|
-
for (let cursor = root;; cursor =
|
|
48356
|
+
for (let cursor = root;; cursor = dirname11(cursor)) {
|
|
48142
48357
|
const stat = lstatSync11(cursor, { throwIfNoEntry: false });
|
|
48143
48358
|
if (stat && (!stat.isDirectory() || stat.isSymbolicLink()))
|
|
48144
48359
|
return false;
|
|
48145
|
-
if (
|
|
48360
|
+
if (dirname11(cursor) === cursor)
|
|
48146
48361
|
break;
|
|
48147
48362
|
}
|
|
48148
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)))
|
|
@@ -48189,8 +48404,8 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
48189
48404
|
for (const name of names) {
|
|
48190
48405
|
let root = join17(parent, name), stat = lstatSync11(root);
|
|
48191
48406
|
if (stat.isSymbolicLink()) {
|
|
48192
|
-
const target =
|
|
48193
|
-
if (name !== "latest" ||
|
|
48407
|
+
const target = resolve10(parent, readlinkSync3(root));
|
|
48408
|
+
if (name !== "latest" || dirname11(target) !== parent || !lstatSync11(target).isDirectory() || realpathSync3(target) !== target)
|
|
48194
48409
|
return false;
|
|
48195
48410
|
root = target;
|
|
48196
48411
|
stat = lstatSync11(root);
|
|
@@ -48210,7 +48425,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
48210
48425
|
function sourceInputUnchanged(input2, cache, read) {
|
|
48211
48426
|
try {
|
|
48212
48427
|
const parts = relative4(cache, input2.pluginParent).split(sep5);
|
|
48213
|
-
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))
|
|
48214
48429
|
return false;
|
|
48215
48430
|
const path = join17(input2.sourceRoot, ".codex-plugin/plugin.json"), stat = lstatSync11(path);
|
|
48216
48431
|
if (!stat.isFile() || stat.size > 1024 * 1024 || realpathSync3(path) !== path)
|
|
@@ -48248,8 +48463,8 @@ var init_codex_native_skill_policy = __esm(() => {
|
|
|
48248
48463
|
});
|
|
48249
48464
|
|
|
48250
48465
|
// src/lib/codex-settings-witness-v1.ts
|
|
48251
|
-
import { createHash as
|
|
48252
|
-
function
|
|
48466
|
+
import { createHash as createHash11 } from "crypto";
|
|
48467
|
+
function need4(value) {
|
|
48253
48468
|
if (!value)
|
|
48254
48469
|
throw new Error("Invalid Codex settings witness");
|
|
48255
48470
|
}
|
|
@@ -48264,14 +48479,14 @@ function numericTokens(text2) {
|
|
|
48264
48479
|
continue;
|
|
48265
48480
|
}
|
|
48266
48481
|
if (char === '"' || char === "'") {
|
|
48267
|
-
const
|
|
48482
|
+
const quote2 = char, triple = text2.slice(at, at + 3) === quote2.repeat(3);
|
|
48268
48483
|
at += triple ? 3 : 1;
|
|
48269
48484
|
while (at < text2.length) {
|
|
48270
|
-
if (
|
|
48485
|
+
if (quote2 === '"' && text2[at] === "\\") {
|
|
48271
48486
|
at += 2;
|
|
48272
48487
|
continue;
|
|
48273
48488
|
}
|
|
48274
|
-
if (text2.slice(at, at + (triple ? 3 : 1)) ===
|
|
48489
|
+
if (text2.slice(at, at + (triple ? 3 : 1)) === quote2.repeat(triple ? 3 : 1)) {
|
|
48275
48490
|
at += triple ? 3 : 1;
|
|
48276
48491
|
break;
|
|
48277
48492
|
}
|
|
@@ -48292,8 +48507,8 @@ function numericTokens(text2) {
|
|
|
48292
48507
|
}
|
|
48293
48508
|
return result;
|
|
48294
48509
|
}
|
|
48295
|
-
function
|
|
48296
|
-
|
|
48510
|
+
function canonical5(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
48511
|
+
need4(depth <= 32 && --budget2.remaining >= 0);
|
|
48297
48512
|
if (value === null)
|
|
48298
48513
|
return ["null"];
|
|
48299
48514
|
if (typeof value === "string")
|
|
@@ -48301,20 +48516,20 @@ function canonical4(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
|
48301
48516
|
if (typeof value === "boolean")
|
|
48302
48517
|
return ["boolean", value];
|
|
48303
48518
|
if (typeof value === "number") {
|
|
48304
|
-
|
|
48519
|
+
need4(Number.isFinite(value));
|
|
48305
48520
|
return ["number", String(value)];
|
|
48306
48521
|
}
|
|
48307
48522
|
if (value instanceof Date) {
|
|
48308
|
-
|
|
48523
|
+
need4(Number.isFinite(value.getTime()));
|
|
48309
48524
|
return ["date", value.toISOString()];
|
|
48310
48525
|
}
|
|
48311
48526
|
if (Array.isArray(value))
|
|
48312
|
-
return ["array", value.map((
|
|
48313
|
-
|
|
48314
|
-
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)])];
|
|
48315
48530
|
}
|
|
48316
48531
|
function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48317
|
-
|
|
48532
|
+
need4(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48318
48533
|
budget2.remaining -= Buffer.byteLength(text2);
|
|
48319
48534
|
let config2;
|
|
48320
48535
|
try {
|
|
@@ -48322,23 +48537,23 @@ function hashCodexSettingsReplacement(text2, budget2 = { remaining: 256 * 1024 *
|
|
|
48322
48537
|
} catch {
|
|
48323
48538
|
throw new Error("Invalid Codex settings witness");
|
|
48324
48539
|
}
|
|
48325
|
-
|
|
48540
|
+
need4(config2 && typeof config2 === "object" && !Array.isArray(config2));
|
|
48326
48541
|
if (Object.hasOwn(config2, "model")) {
|
|
48327
|
-
|
|
48542
|
+
need4(typeof config2.model === "string" && /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/.test(config2.model));
|
|
48328
48543
|
delete config2.model;
|
|
48329
48544
|
}
|
|
48330
48545
|
for (const [key, values] of [["model_reasoning_effort", EFFORT], ["model_verbosity", VERBOSITY]])
|
|
48331
48546
|
if (Object.hasOwn(config2, key)) {
|
|
48332
|
-
|
|
48547
|
+
need4(typeof config2[key] === "string" && values.has(config2[key]));
|
|
48333
48548
|
delete config2[key];
|
|
48334
48549
|
}
|
|
48335
|
-
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)])}`);
|
|
48336
48551
|
}
|
|
48337
48552
|
function captureCodexSettings(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48338
48553
|
const text2 = readNativeSettingsWitnessFile(path, budget2, "config.toml");
|
|
48339
48554
|
return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text2) };
|
|
48340
48555
|
}
|
|
48341
|
-
var sha = (text2) =>
|
|
48556
|
+
var sha = (text2) => createHash11("sha256").update(text2).digest("hex"), EFFORT, VERBOSITY;
|
|
48342
48557
|
var init_codex_settings_witness_v1 = __esm(() => {
|
|
48343
48558
|
init_claude_settings_witness();
|
|
48344
48559
|
EFFORT = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
|
|
@@ -48411,9 +48626,9 @@ function projectRegularCodexMcp(config2, source) {
|
|
|
48411
48626
|
var init_codex_mcp_discovery_projection = () => {};
|
|
48412
48627
|
|
|
48413
48628
|
// src/lib/codex-settings-witness.ts
|
|
48414
|
-
import { createHash as
|
|
48629
|
+
import { createHash as createHash12 } from "crypto";
|
|
48415
48630
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
48416
|
-
function
|
|
48631
|
+
function need5(value) {
|
|
48417
48632
|
if (!value)
|
|
48418
48633
|
throw new Error("Invalid Codex settings witness");
|
|
48419
48634
|
}
|
|
@@ -48434,14 +48649,14 @@ function numericTokens2(text2) {
|
|
|
48434
48649
|
continue;
|
|
48435
48650
|
}
|
|
48436
48651
|
if (char === '"' || char === "'") {
|
|
48437
|
-
const
|
|
48652
|
+
const quote2 = char, triple = text2.slice(at, at + 3) === quote2.repeat(3);
|
|
48438
48653
|
at += triple ? 3 : 1;
|
|
48439
48654
|
while (at < text2.length) {
|
|
48440
|
-
if (
|
|
48655
|
+
if (quote2 === '"' && text2[at] === "\\") {
|
|
48441
48656
|
at += 2;
|
|
48442
48657
|
continue;
|
|
48443
48658
|
}
|
|
48444
|
-
if (text2.slice(at, at + (triple ? 3 : 1)) ===
|
|
48659
|
+
if (text2.slice(at, at + (triple ? 3 : 1)) === quote2.repeat(triple ? 3 : 1)) {
|
|
48445
48660
|
at += triple ? 3 : 1;
|
|
48446
48661
|
break;
|
|
48447
48662
|
}
|
|
@@ -48462,8 +48677,8 @@ function numericTokens2(text2) {
|
|
|
48462
48677
|
}
|
|
48463
48678
|
return result.sort();
|
|
48464
48679
|
}
|
|
48465
|
-
function
|
|
48466
|
-
|
|
48680
|
+
function canonical6(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
48681
|
+
need5(depth <= 32 && --budget2.remaining >= 0);
|
|
48467
48682
|
if (value === null)
|
|
48468
48683
|
return ["null"];
|
|
48469
48684
|
if (typeof value === "string")
|
|
@@ -48471,17 +48686,17 @@ function canonical5(value, depth = 0, budget2 = { remaining: 65536 }) {
|
|
|
48471
48686
|
if (typeof value === "boolean")
|
|
48472
48687
|
return ["boolean", value];
|
|
48473
48688
|
if (typeof value === "number") {
|
|
48474
|
-
|
|
48689
|
+
need5(Number.isFinite(value));
|
|
48475
48690
|
return ["number", String(value)];
|
|
48476
48691
|
}
|
|
48477
48692
|
if (isDate(value)) {
|
|
48478
|
-
|
|
48693
|
+
need5(Number.isFinite(value.getTime()));
|
|
48479
48694
|
return ["date", value.toISOString()];
|
|
48480
48695
|
}
|
|
48481
48696
|
if (Array.isArray(value))
|
|
48482
|
-
return ["array", value.map((
|
|
48483
|
-
|
|
48484
|
-
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)])];
|
|
48485
48700
|
}
|
|
48486
48701
|
function normalize2(config2, version2 = 2) {
|
|
48487
48702
|
if (isRecord3(config2.hooks)) {
|
|
@@ -48523,15 +48738,15 @@ function inference(target, version2) {
|
|
|
48523
48738
|
if (Object.hasOwn(target, key)) {
|
|
48524
48739
|
const value = target[key];
|
|
48525
48740
|
if (key === "model")
|
|
48526
|
-
|
|
48741
|
+
need5(typeof value === "string" && MODEL.test(value));
|
|
48527
48742
|
else if (key === "personality")
|
|
48528
|
-
|
|
48743
|
+
need5(typeof value === "string" && ["none", "friendly", "pragmatic"].includes(value));
|
|
48529
48744
|
else if (version2 >= 3 && key !== "model_verbosity") {
|
|
48530
|
-
|
|
48745
|
+
need5(typeof value === "string" && value.length <= 128 && !/[\x00-\x1f\x7f]/.test(value));
|
|
48531
48746
|
if (key !== "service_tier")
|
|
48532
|
-
|
|
48747
|
+
need5(value.length > 0);
|
|
48533
48748
|
} else
|
|
48534
|
-
|
|
48749
|
+
need5(typeof value === "string" && (key === "model_reasoning_effort" ? EFFORT2.has(value) : VERBOSITY2.has(value)));
|
|
48535
48750
|
delete target[key];
|
|
48536
48751
|
}
|
|
48537
48752
|
}
|
|
@@ -48564,14 +48779,14 @@ function projectModelAvailabilityNux(config2, text2) {
|
|
|
48564
48779
|
continue;
|
|
48565
48780
|
}
|
|
48566
48781
|
if (char === '"' || char === "'") {
|
|
48567
|
-
const
|
|
48782
|
+
const quote2 = char;
|
|
48568
48783
|
at++;
|
|
48569
48784
|
while (at < span.length) {
|
|
48570
|
-
if (
|
|
48785
|
+
if (quote2 === '"' && span[at] === "\\") {
|
|
48571
48786
|
at += 2;
|
|
48572
48787
|
continue;
|
|
48573
48788
|
}
|
|
48574
|
-
if (span[at++] ===
|
|
48789
|
+
if (span[at++] === quote2)
|
|
48575
48790
|
break;
|
|
48576
48791
|
}
|
|
48577
48792
|
continue;
|
|
@@ -48651,14 +48866,14 @@ function settingsDigest2(text2, version2 = 2) {
|
|
|
48651
48866
|
} catch {
|
|
48652
48867
|
throw new Error("Invalid Codex settings witness");
|
|
48653
48868
|
}
|
|
48654
|
-
|
|
48869
|
+
need5(isRecord3(config2));
|
|
48655
48870
|
const mcp = version2 >= 3 ? projectRegularCodexMcp(config2, text2) : { config: config2, numericSource: text2 };
|
|
48656
48871
|
const projected = version2 === 4 ? projectModelAvailabilityNux(mcp.config, mcp.numericSource) : mcp;
|
|
48657
48872
|
normalize2(projected.config, version2);
|
|
48658
|
-
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)])}`);
|
|
48659
48874
|
}
|
|
48660
48875
|
function hashCodexSettingsReplacementV2(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48661
|
-
|
|
48876
|
+
need5(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48662
48877
|
budget2.remaining -= Buffer.byteLength(text2);
|
|
48663
48878
|
return settingsDigest2(text2);
|
|
48664
48879
|
}
|
|
@@ -48667,7 +48882,7 @@ function captureCodexSettingsV2(path, budget2 = { remaining: 256 * 1024 * 1024 }
|
|
|
48667
48882
|
return { path, hashMode: "codex-settings-v2", sha256: settingsDigest2(text2) };
|
|
48668
48883
|
}
|
|
48669
48884
|
function hashCodexSettingsReplacementV3(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48670
|
-
|
|
48885
|
+
need5(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48671
48886
|
budget2.remaining -= Buffer.byteLength(text2);
|
|
48672
48887
|
return settingsDigest2(text2, 3);
|
|
48673
48888
|
}
|
|
@@ -48675,14 +48890,14 @@ function captureCodexSettingsV3(path, budget2 = { remaining: 256 * 1024 * 1024 }
|
|
|
48675
48890
|
return { path, hashMode: "codex-settings-v3", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 3) };
|
|
48676
48891
|
}
|
|
48677
48892
|
function hashCodexSettingsReplacementV4(text2, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48678
|
-
|
|
48893
|
+
need5(Buffer.byteLength(text2) <= 1024 * 1024 && budget2.remaining >= Buffer.byteLength(text2));
|
|
48679
48894
|
budget2.remaining -= Buffer.byteLength(text2);
|
|
48680
48895
|
return settingsDigest2(text2, 4);
|
|
48681
48896
|
}
|
|
48682
48897
|
function captureCodexSettingsV4(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
48683
48898
|
return { path, hashMode: "codex-settings-v4", sha256: settingsDigest2(readNativeSettingsWitnessFile(path, budget2, "config.toml"), 4) };
|
|
48684
48899
|
}
|
|
48685
|
-
var sha2 = (text2) =>
|
|
48900
|
+
var sha2 = (text2) => createHash12("sha256").update(text2).digest("hex"), EFFORT2, VERBOSITY2, MODEL, CODEX_DISCOVERY_PROJECTION_FIELDS, INFERENCE;
|
|
48686
48901
|
var init_codex_settings_witness = __esm(() => {
|
|
48687
48902
|
init_codex_settings_witness_v1();
|
|
48688
48903
|
init_codex_settings_witness_v1();
|
|
@@ -48698,8 +48913,8 @@ var init_codex_settings_witness = __esm(() => {
|
|
|
48698
48913
|
// src/lib/managed-policy.ts
|
|
48699
48914
|
import { closeSync as closeSync9, constants as constants6, fstatSync as fstatSync9, lstatSync as lstatSync12, openSync as openSync9, readSync as readSync5 } from "fs";
|
|
48700
48915
|
import { join as join18 } from "path";
|
|
48701
|
-
function refusal(
|
|
48702
|
-
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.`);
|
|
48703
48918
|
}
|
|
48704
48919
|
function parseManagedSkillPolicy(text2) {
|
|
48705
48920
|
if (Buffer.byteLength(text2) > AGENT_POLICY_LIMITS.bytes)
|
|
@@ -48775,7 +48990,7 @@ var init_managed_policy = __esm(() => {
|
|
|
48775
48990
|
});
|
|
48776
48991
|
|
|
48777
48992
|
// src/lib/agent-bridge.ts
|
|
48778
|
-
import { createHash as
|
|
48993
|
+
import { createHash as createHash13 } from "crypto";
|
|
48779
48994
|
var CLI_BRIDGE_VERSION = 1, markdown = `---
|
|
48780
48995
|
name: skills-cli
|
|
48781
48996
|
description: Discover, load, author, and run versioned skills through the Skills CLI when a task needs reusable instructions or an executable skill.
|
|
@@ -48791,7 +49006,7 @@ Use the Skills CLI as the skill authority for this station.
|
|
|
48791
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.
|
|
48792
49007
|
`, CLI_BRIDGE_DIGEST, CLI_BRIDGE_FILES;
|
|
48793
49008
|
var init_agent_bridge = __esm(() => {
|
|
48794
|
-
CLI_BRIDGE_DIGEST =
|
|
49009
|
+
CLI_BRIDGE_DIGEST = createHash13("sha256").update(markdown).digest("hex");
|
|
48795
49010
|
CLI_BRIDGE_FILES = Object.freeze({
|
|
48796
49011
|
"SKILL.md": markdown,
|
|
48797
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)}
|
|
@@ -48804,28 +49019,28 @@ var init_agent_codex = () => {};
|
|
|
48804
49019
|
|
|
48805
49020
|
// src/lib/agent-sumi.ts
|
|
48806
49021
|
import { existsSync as existsSync8, lstatSync as lstatSync13, realpathSync as realpathSync4 } from "fs";
|
|
48807
|
-
import { join as join19, resolve as
|
|
49022
|
+
import { join as join19, resolve as resolve11 } from "path";
|
|
48808
49023
|
function sumiConfigDirectory(home, env = process.env) {
|
|
48809
49024
|
for (const key of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
|
|
48810
49025
|
if (env[key] !== undefined)
|
|
48811
49026
|
throw new Error(`Sumi ${key} requires a dedicated discovery adapter; unset it before Skills integration`);
|
|
48812
49027
|
const selected = (key) => env[key]?.trim() ? env[key] : undefined;
|
|
48813
|
-
const expand = (value) =>
|
|
49028
|
+
const expand = (value) => resolve11(value === "~" ? home : value.startsWith("~/") ? join19(home, value.slice(2)) : value);
|
|
48814
49029
|
const explicit = selected("SUMI_CONFIG_DIR");
|
|
48815
49030
|
const xdg = selected("XDG_CONFIG_HOME");
|
|
48816
49031
|
const custom2 = selected("SUMI_HOME");
|
|
48817
|
-
const
|
|
49032
|
+
const canonical7 = explicit ? expand(explicit) : xdg ? join19(expand(xdg), "sumi") : join19(custom2 ? expand(custom2) : join19(home, ".hasna-internal/sumi"), "config");
|
|
48818
49033
|
if (explicit || xdg || custom2)
|
|
48819
|
-
return
|
|
49034
|
+
return canonical7;
|
|
48820
49035
|
const legacy = join19(home, ".config/sumi");
|
|
48821
|
-
const a = lstatSync13(
|
|
48822
|
-
if (a && b && realpathSync4(
|
|
49036
|
+
const a = lstatSync13(canonical7, { throwIfNoEntry: false }), b = lstatSync13(legacy, { throwIfNoEntry: false });
|
|
49037
|
+
if (a && b && realpathSync4(canonical7) !== realpathSync4(legacy))
|
|
48823
49038
|
throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
|
|
48824
|
-
const path = a ?
|
|
49039
|
+
const path = a ? canonical7 : b ? legacy : canonical7;
|
|
48825
49040
|
if (!existsSync8(path))
|
|
48826
49041
|
return path;
|
|
48827
49042
|
const physical = realpathSync4(path);
|
|
48828
|
-
if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![
|
|
49043
|
+
if ((a?.isSymbolicLink() || b?.isSymbolicLink()) && ![canonical7, legacy].includes(physical))
|
|
48829
49044
|
throw new Error("Sumi config alias must resolve to its canonical or legacy root");
|
|
48830
49045
|
return physical;
|
|
48831
49046
|
}
|
|
@@ -48835,19 +49050,22 @@ function sumiConfigPath(home) {
|
|
|
48835
49050
|
var init_agent_sumi = () => {};
|
|
48836
49051
|
|
|
48837
49052
|
// src/lib/codex-hook-trust-files.ts
|
|
48838
|
-
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";
|
|
48839
|
-
import { createHash as
|
|
48840
|
-
import { dirname as
|
|
48841
|
-
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) {
|
|
48842
49057
|
if (!value)
|
|
48843
49058
|
throw new Error(`CODEX_HOOK_TRUST_${code}`);
|
|
48844
49059
|
}
|
|
49060
|
+
function trustedAncestorOwner(uid) {
|
|
49061
|
+
return BigInt(uid) === 0n || BigInt(uid) === BigInt(process.getuid());
|
|
49062
|
+
}
|
|
48845
49063
|
function safeParents(file2) {
|
|
48846
|
-
for (let p =
|
|
49064
|
+
for (let p = dirname12(file2);; p = dirname12(p)) {
|
|
48847
49065
|
const s = lstatSync14(p);
|
|
48848
|
-
|
|
48849
|
-
|
|
48850
|
-
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)
|
|
48851
49069
|
break;
|
|
48852
49070
|
}
|
|
48853
49071
|
}
|
|
@@ -48855,12 +49073,12 @@ function snapshot(file2, privateFile = false, options = {}) {
|
|
|
48855
49073
|
const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
|
|
48856
49074
|
safeParents(file2);
|
|
48857
49075
|
const initial = lstatSync14(file2, { bigint: true });
|
|
48858
|
-
|
|
48859
|
-
|
|
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");
|
|
48860
49078
|
const fd = openSync10(file2, constants7.O_RDONLY | constants7.O_NOFOLLOW | constants7.O_NONBLOCK);
|
|
48861
49079
|
try {
|
|
48862
49080
|
const before = fstatSync10(fd, { bigint: true });
|
|
48863
|
-
|
|
49081
|
+
need6(sameStat(initial, before), "INPUT_CHANGED");
|
|
48864
49082
|
const bytes = Buffer.alloc(Number(before.size) + 1);
|
|
48865
49083
|
let length = 0;
|
|
48866
49084
|
while (length < bytes.length) {
|
|
@@ -48869,16 +49087,16 @@ function snapshot(file2, privateFile = false, options = {}) {
|
|
|
48869
49087
|
break;
|
|
48870
49088
|
length += n2;
|
|
48871
49089
|
}
|
|
48872
|
-
|
|
49090
|
+
need6(length === Number(before.size) && sameStat(before, fstatSync10(fd, { bigint: true })) && sameStat(before, lstatSync14(file2, { bigint: true })), "INPUT_CHANGED");
|
|
48873
49091
|
const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
48874
|
-
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") };
|
|
48875
49093
|
} finally {
|
|
48876
49094
|
closeSync10(fd);
|
|
48877
49095
|
}
|
|
48878
49096
|
}
|
|
48879
49097
|
function unchanged2(before) {
|
|
48880
49098
|
const after = snapshot(before.file, before.privateFile, before.readOnlyPackage ? { readOnlyPackage: true } : {});
|
|
48881
|
-
|
|
49099
|
+
need6(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
|
|
48882
49100
|
}
|
|
48883
49101
|
var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
|
|
48884
49102
|
var init_codex_hook_trust_files = () => {};
|
|
@@ -49620,7 +49838,7 @@ var init_selection_resolver = __esm(() => {
|
|
|
49620
49838
|
});
|
|
49621
49839
|
|
|
49622
49840
|
// src/lib/plugin-projection.ts
|
|
49623
|
-
import { createHash as
|
|
49841
|
+
import { createHash as createHash15 } from "crypto";
|
|
49624
49842
|
function pluginRefusal(message) {
|
|
49625
49843
|
throw new SkillSelectionError("PLUGIN_ADMISSION_REFUSED", message);
|
|
49626
49844
|
}
|
|
@@ -49698,7 +49916,7 @@ function pluginFileWitnesses(entries) {
|
|
|
49698
49916
|
return { path: item.path, mode: item.mode, size: item.bytes.byteLength, sha256: pluginHash(item.bytes) };
|
|
49699
49917
|
});
|
|
49700
49918
|
}
|
|
49701
|
-
var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) =>
|
|
49919
|
+
var PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash15("sha256").update(bytes).digest("hex");
|
|
49702
49920
|
var init_plugin_projection = __esm(() => {
|
|
49703
49921
|
init_selection_cache();
|
|
49704
49922
|
PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
|
|
@@ -49706,7 +49924,7 @@ var init_plugin_projection = __esm(() => {
|
|
|
49706
49924
|
|
|
49707
49925
|
// src/lib/plugin-projection-store.ts
|
|
49708
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";
|
|
49709
|
-
import { dirname as
|
|
49927
|
+
import { dirname as dirname13, isAbsolute as isAbsolute11, join as join23, parse as parse10, resolve as resolve13 } from "path";
|
|
49710
49928
|
function stat(path) {
|
|
49711
49929
|
try {
|
|
49712
49930
|
return lstatSync15(path, { bigint: true });
|
|
@@ -49716,8 +49934,8 @@ function stat(path) {
|
|
|
49716
49934
|
return pluginRefusal("Cannot inspect plugin filesystem entry");
|
|
49717
49935
|
}
|
|
49718
49936
|
}
|
|
49719
|
-
function
|
|
49720
|
-
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");
|
|
49721
49939
|
}
|
|
49722
49940
|
function owner(stats, system = false) {
|
|
49723
49941
|
const current = uid();
|
|
@@ -49727,8 +49945,8 @@ function same3(left, right, identityOnly = false) {
|
|
|
49727
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");
|
|
49728
49946
|
}
|
|
49729
49947
|
function ancestors(path, create = false) {
|
|
49730
|
-
|
|
49731
|
-
const result = [], parent =
|
|
49948
|
+
canonical7(path);
|
|
49949
|
+
const result = [], parent = dirname13(path), filesystemRoot = parse10(parent).root;
|
|
49732
49950
|
let current = filesystemRoot;
|
|
49733
49951
|
for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
|
|
49734
49952
|
if (segment)
|
|
@@ -49954,7 +50172,7 @@ var init_selected_manifest = __esm(() => {
|
|
|
49954
50172
|
});
|
|
49955
50173
|
|
|
49956
50174
|
// src/lib/plugin-admission.ts
|
|
49957
|
-
import { isAbsolute as
|
|
50175
|
+
import { isAbsolute as isAbsolute12, join as join24, resolve as resolve14 } from "path";
|
|
49958
50176
|
function validatePluginTarget(value) {
|
|
49959
50177
|
pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
|
|
49960
50178
|
pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
|
|
@@ -49964,7 +50182,7 @@ function validatePluginTarget(value) {
|
|
|
49964
50182
|
for (const registration of value.registrations) {
|
|
49965
50183
|
pluginKeys(registration, ["scope", "projectPath"]);
|
|
49966
50184
|
pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
|
|
49967
|
-
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");
|
|
49968
50186
|
const key = JSON.stringify([registration.scope, registration.projectPath]);
|
|
49969
50187
|
pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
|
|
49970
50188
|
scopes.add(key);
|
|
@@ -49972,7 +50190,7 @@ function validatePluginTarget(value) {
|
|
|
49972
50190
|
for (const key of ["native", "resolver"]) {
|
|
49973
50191
|
pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
|
|
49974
50192
|
pluginText(value[key].executable);
|
|
49975
|
-
pluginNeed(
|
|
50193
|
+
pluginNeed(isAbsolute12(value[key].executable) && resolve14(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
|
|
49976
50194
|
pluginDigest(value[key].digest);
|
|
49977
50195
|
}
|
|
49978
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)");
|
|
@@ -50111,7 +50329,7 @@ function validatePlan(value) {
|
|
|
50111
50329
|
pluginNeed(identityDigest(plan) === plan.planDigest, "Plugin receipt immutable identity changed");
|
|
50112
50330
|
}
|
|
50113
50331
|
function pluginResolverCommand(binding) {
|
|
50114
|
-
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))}`;
|
|
50115
50333
|
}
|
|
50116
50334
|
function pluginBindingPath(storeRoot, id) {
|
|
50117
50335
|
pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
|
|
@@ -50145,7 +50363,7 @@ function readPluginAdmissionReceipt(storeRoot, id, digest) {
|
|
|
50145
50363
|
pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
|
|
50146
50364
|
return receipt;
|
|
50147
50365
|
}
|
|
50148
|
-
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"';
|
|
50149
50367
|
var init_plugin_admission = __esm(() => {
|
|
50150
50368
|
init_profile_client();
|
|
50151
50369
|
init_skill_bundle();
|
|
@@ -50158,7 +50376,7 @@ var init_plugin_admission = __esm(() => {
|
|
|
50158
50376
|
|
|
50159
50377
|
// src/lib/plugin-discovery.ts
|
|
50160
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";
|
|
50161
|
-
import { basename as
|
|
50379
|
+
import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute13, join as join25, resolve as resolve15 } from "path";
|
|
50162
50380
|
function validateManagedPluginWitnesses(value) {
|
|
50163
50381
|
pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
|
|
50164
50382
|
const seen = new Set;
|
|
@@ -50167,15 +50385,15 @@ function validateManagedPluginWitnesses(value) {
|
|
|
50167
50385
|
pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
|
|
50168
50386
|
seen.add(item.bindingId);
|
|
50169
50387
|
pluginText(item.storeRoot);
|
|
50170
|
-
pluginNeed(
|
|
50388
|
+
pluginNeed(isAbsolute13(item.storeRoot) && resolve15(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
|
|
50171
50389
|
}
|
|
50172
50390
|
}
|
|
50173
50391
|
function safe3(path) {
|
|
50174
50392
|
pluginText(path);
|
|
50175
|
-
pluginNeed(
|
|
50176
|
-
for (let at = path;; at =
|
|
50393
|
+
pluginNeed(isAbsolute13(path) && resolve15(path) === path, "Invalid plugin registry path");
|
|
50394
|
+
for (let at = path;; at = dirname14(at)) {
|
|
50177
50395
|
pluginNeed(!lstatSync16(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
|
|
50178
|
-
if (at ===
|
|
50396
|
+
if (at === dirname14(at))
|
|
50179
50397
|
break;
|
|
50180
50398
|
}
|
|
50181
50399
|
}
|
|
@@ -50225,7 +50443,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
50225
50443
|
seen.add(target.pluginId);
|
|
50226
50444
|
const rows = plugins[target.pluginId];
|
|
50227
50445
|
pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
|
|
50228
|
-
const [name, market] = target.pluginId.split("@"), cacheRoot = join25(
|
|
50446
|
+
const [name, market] = target.pluginId.split("@"), cacheRoot = join25(dirname14(path), "cache", market, name);
|
|
50229
50447
|
const scopes = new Set, approvals = new Map, currentFiles = new Map;
|
|
50230
50448
|
plugins[target.pluginId] = rows.map((row) => {
|
|
50231
50449
|
pluginNeed(pluginObject(row), "Invalid managed plugin registration");
|
|
@@ -50241,7 +50459,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
50241
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");
|
|
50242
50460
|
const approval = (producer) => {
|
|
50243
50461
|
pluginText(producer);
|
|
50244
|
-
const digest = `sha256:${
|
|
50462
|
+
const digest = `sha256:${basename7(producer)}`;
|
|
50245
50463
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest);
|
|
50246
50464
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
50247
50465
|
if (!verified.has(producer)) {
|
|
@@ -50305,37 +50523,37 @@ var init_plugin_discovery = __esm(() => {
|
|
|
50305
50523
|
});
|
|
50306
50524
|
|
|
50307
50525
|
// src/lib/claude-marketplace-registry.ts
|
|
50308
|
-
import { createHash as
|
|
50526
|
+
import { createHash as createHash16 } from "crypto";
|
|
50309
50527
|
import { closeSync as closeSync13, constants as constants10, fstatSync as fstatSync13, lstatSync as lstatSync17, openSync as openSync13, readSync as readSync9 } from "fs";
|
|
50310
|
-
import { basename as
|
|
50311
|
-
function
|
|
50528
|
+
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute14, resolve as resolve16 } from "path";
|
|
50529
|
+
function need7(value, reason2) {
|
|
50312
50530
|
if (!value)
|
|
50313
|
-
throw new Error(`Claude marketplace registry ${
|
|
50531
|
+
throw new Error(`Claude marketplace registry ${reason2}`);
|
|
50314
50532
|
}
|
|
50315
50533
|
function absolutePath2(value) {
|
|
50316
|
-
|
|
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");
|
|
50317
50535
|
}
|
|
50318
50536
|
function parents2(path) {
|
|
50319
50537
|
const result = [];
|
|
50320
|
-
for (let at =
|
|
50538
|
+
for (let at = dirname15(path);; at = dirname15(at)) {
|
|
50321
50539
|
const stat2 = lstatSync17(at, { bigint: true });
|
|
50322
|
-
|
|
50540
|
+
need7(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
50323
50541
|
result.push([at, stat2]);
|
|
50324
|
-
if (at ===
|
|
50542
|
+
if (at === dirname15(at))
|
|
50325
50543
|
return result;
|
|
50326
50544
|
}
|
|
50327
50545
|
}
|
|
50328
50546
|
function readRegistry2(path, budget2) {
|
|
50329
50547
|
absolutePath2(path);
|
|
50330
|
-
|
|
50331
|
-
|
|
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");
|
|
50332
50550
|
const ancestors2 = parents2(path), initial = lstatSync17(path, { bigint: true });
|
|
50333
|
-
|
|
50334
|
-
|
|
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");
|
|
50335
50553
|
const fd = openSync13(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
|
|
50336
50554
|
try {
|
|
50337
50555
|
const opened = fstatSync13(fd, { bigint: true });
|
|
50338
|
-
|
|
50556
|
+
need7(opened.isFile() && sameFile2(initial, opened), "changed during open");
|
|
50339
50557
|
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
50340
50558
|
let length = 0;
|
|
50341
50559
|
while (length < bytes.length) {
|
|
@@ -50345,10 +50563,10 @@ function readRegistry2(path, budget2) {
|
|
|
50345
50563
|
length += count;
|
|
50346
50564
|
}
|
|
50347
50565
|
const after = fstatSync13(fd, { bigint: true }), current = lstatSync17(path, { bigint: true });
|
|
50348
|
-
|
|
50566
|
+
need7(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
|
|
50349
50567
|
for (const [ancestor, before] of ancestors2) {
|
|
50350
50568
|
const now = lstatSync17(ancestor, { bigint: true });
|
|
50351
|
-
|
|
50569
|
+
need7(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
50352
50570
|
}
|
|
50353
50571
|
budget2.remaining -= length;
|
|
50354
50572
|
try {
|
|
@@ -50368,7 +50586,7 @@ function parse11(text2) {
|
|
|
50368
50586
|
at++;
|
|
50369
50587
|
};
|
|
50370
50588
|
function string5() {
|
|
50371
|
-
|
|
50589
|
+
need7(text2[at] === '"', "contains invalid JSON");
|
|
50372
50590
|
const start = at++;
|
|
50373
50591
|
while (at < text2.length) {
|
|
50374
50592
|
const character = text2[at++];
|
|
@@ -50379,7 +50597,7 @@ function parse11(text2) {
|
|
|
50379
50597
|
} catch {
|
|
50380
50598
|
throw new Error("Claude marketplace registry contains invalid JSON string");
|
|
50381
50599
|
}
|
|
50382
|
-
|
|
50600
|
+
need7(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
|
|
50383
50601
|
return value2;
|
|
50384
50602
|
}
|
|
50385
50603
|
if (character === "\\")
|
|
@@ -50388,7 +50606,7 @@ function parse11(text2) {
|
|
|
50388
50606
|
throw new Error("Claude marketplace registry contains an unterminated JSON string");
|
|
50389
50607
|
}
|
|
50390
50608
|
function value(depth) {
|
|
50391
|
-
|
|
50609
|
+
need7(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
50392
50610
|
space();
|
|
50393
50611
|
const character = text2[at];
|
|
50394
50612
|
if (character === '"')
|
|
@@ -50402,17 +50620,17 @@ function parse11(text2) {
|
|
|
50402
50620
|
if (object7) {
|
|
50403
50621
|
space();
|
|
50404
50622
|
const key = string5();
|
|
50405
|
-
|
|
50623
|
+
need7(!keys.has(key), "contains a duplicate JSON key");
|
|
50406
50624
|
keys.add(key);
|
|
50407
50625
|
space();
|
|
50408
|
-
|
|
50626
|
+
need7(text2[at++] === ":", "contains invalid JSON");
|
|
50409
50627
|
entries.push([key, value(depth + 1)]);
|
|
50410
50628
|
} else
|
|
50411
50629
|
items.push(value(depth + 1));
|
|
50412
50630
|
space();
|
|
50413
50631
|
if (text2[at] === end)
|
|
50414
50632
|
break;
|
|
50415
|
-
|
|
50633
|
+
need7(text2[at++] === ",", "contains invalid JSON");
|
|
50416
50634
|
}
|
|
50417
50635
|
at++;
|
|
50418
50636
|
return object7 ? { kind: "object", entries } : { kind: "array", items };
|
|
@@ -50424,64 +50642,64 @@ function parse11(text2) {
|
|
|
50424
50642
|
}
|
|
50425
50643
|
numberPattern.lastIndex = at;
|
|
50426
50644
|
const number5 = numberPattern.exec(text2);
|
|
50427
|
-
|
|
50645
|
+
need7(number5, "contains invalid JSON");
|
|
50428
50646
|
at += number5[0].length;
|
|
50429
50647
|
return { kind: "number", value: number5[0] };
|
|
50430
50648
|
}
|
|
50431
50649
|
const root = value(0);
|
|
50432
50650
|
space();
|
|
50433
|
-
|
|
50434
|
-
|
|
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");
|
|
50435
50653
|
return root;
|
|
50436
50654
|
}
|
|
50437
50655
|
function exactKeys(value, keys) {
|
|
50438
50656
|
return value?.kind === "object" && value.entries.length === keys.length && value.entries.every(([key]) => keys.includes(key));
|
|
50439
50657
|
}
|
|
50440
50658
|
function textField(value) {
|
|
50441
|
-
|
|
50659
|
+
need7(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
|
|
50442
50660
|
return value.value;
|
|
50443
50661
|
}
|
|
50444
50662
|
function normalizeRow(row, version2 = 1) {
|
|
50445
50663
|
if (!exactKeys(row, ["source", "installLocation", "lastUpdated"])) {
|
|
50446
50664
|
if (version2 !== 2 || !exactKeys(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
|
|
50447
50665
|
return;
|
|
50448
|
-
const autoUpdate =
|
|
50449
|
-
|
|
50666
|
+
const autoUpdate = field2(row, "autoUpdate");
|
|
50667
|
+
need7(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
|
|
50450
50668
|
}
|
|
50451
|
-
const source =
|
|
50669
|
+
const source = field2(row, "source");
|
|
50452
50670
|
if (source?.kind !== "object")
|
|
50453
50671
|
return;
|
|
50454
|
-
const type =
|
|
50672
|
+
const type = field2(source, "source");
|
|
50455
50673
|
if (type?.kind !== "string" || !["github", "directory"].includes(type.value))
|
|
50456
50674
|
return;
|
|
50457
50675
|
const location = type.value === "github" ? "repo" : "path";
|
|
50458
50676
|
if (!exactKeys(source, ["source", location]))
|
|
50459
50677
|
return;
|
|
50460
|
-
const sourceLocation = textField(
|
|
50678
|
+
const sourceLocation = textField(field2(source, location));
|
|
50461
50679
|
if (type.value === "directory")
|
|
50462
50680
|
absolutePath2(sourceLocation);
|
|
50463
|
-
absolutePath2(textField(
|
|
50464
|
-
const updated = textField(
|
|
50465
|
-
|
|
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");
|
|
50466
50684
|
const millis = Date.parse(updated);
|
|
50467
|
-
|
|
50685
|
+
need7(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
|
|
50468
50686
|
row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
|
|
50469
50687
|
}
|
|
50470
50688
|
function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
50471
50689
|
const value = parse11(readRegistry2(path, budget2));
|
|
50472
50690
|
for (const [, row] of value.entries)
|
|
50473
50691
|
normalizeRow(row);
|
|
50474
|
-
const sha2562 =
|
|
50692
|
+
const sha2562 = createHash16("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
50475
50693
|
return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
|
|
50476
50694
|
}
|
|
50477
50695
|
function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
50478
50696
|
const value = parse11(readRegistry2(path, budget2));
|
|
50479
50697
|
for (const [, row] of value.entries)
|
|
50480
50698
|
normalizeRow(row, 2);
|
|
50481
|
-
const sha2562 =
|
|
50699
|
+
const sha2562 = createHash16("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
|
|
50482
50700
|
return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
|
|
50483
50701
|
}
|
|
50484
|
-
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];
|
|
50485
50703
|
var init_claude_marketplace_registry = __esm(() => {
|
|
50486
50704
|
CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
50487
50705
|
});
|
|
@@ -50500,10 +50718,10 @@ var init_codex_hook_additions_review = __esm(() => {
|
|
|
50500
50718
|
});
|
|
50501
50719
|
|
|
50502
50720
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
50503
|
-
import { createHash as
|
|
50721
|
+
import { createHash as createHash17 } from "crypto";
|
|
50504
50722
|
function assertCodexHookDiscoveryRecovery(binding, witness) {
|
|
50505
50723
|
const proof = proofs2.get(witness);
|
|
50506
|
-
|
|
50724
|
+
need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha3(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
50507
50725
|
unchanged2(proof.before);
|
|
50508
50726
|
unchanged2(proof.current);
|
|
50509
50727
|
proof.recheckAdditions();
|
|
@@ -50512,10 +50730,10 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
|
|
|
50512
50730
|
if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
|
|
50513
50731
|
return false;
|
|
50514
50732
|
assertCodexHookDiscoveryRecovery(binding, witness);
|
|
50515
|
-
|
|
50733
|
+
need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
50516
50734
|
return true;
|
|
50517
50735
|
}
|
|
50518
|
-
var sha3 = (text2) =>
|
|
50736
|
+
var sha3 = (text2) => createHash17("sha256").update(text2).digest("hex"), fields, proofs2;
|
|
50519
50737
|
var init_codex_hook_discovery_recovery = __esm(() => {
|
|
50520
50738
|
init_codex_hook_trust_files();
|
|
50521
50739
|
init_codex_hook_trust_layout();
|
|
@@ -50526,10 +50744,18 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
50526
50744
|
});
|
|
50527
50745
|
|
|
50528
50746
|
// src/lib/agent-discovery.ts
|
|
50529
|
-
import { createHash as
|
|
50747
|
+
import { createHash as createHash18 } from "crypto";
|
|
50530
50748
|
import { lstatSync as lstatSync18, readFileSync as readFileSync15, readdirSync as readdirSync7, realpathSync as realpathSync5 } from "fs";
|
|
50531
|
-
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";
|
|
50532
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
|
+
}
|
|
50533
50759
|
function parseConfig(text2, path, toml = false) {
|
|
50534
50760
|
try {
|
|
50535
50761
|
const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
|
|
@@ -50541,12 +50767,12 @@ function parseConfig(text2, path, toml = false) {
|
|
|
50541
50767
|
}
|
|
50542
50768
|
}
|
|
50543
50769
|
function safe4(path) {
|
|
50544
|
-
if (!
|
|
50770
|
+
if (!isAbsolute15(path) || path.includes("\x00"))
|
|
50545
50771
|
throw new Error("Expected an absolute native discovery path");
|
|
50546
|
-
for (let cursor = path;; cursor =
|
|
50772
|
+
for (let cursor = path;; cursor = dirname16(cursor)) {
|
|
50547
50773
|
if (lstatSync18(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
50548
50774
|
throw new Error(`Refusing symlink native discovery input: ${cursor}`);
|
|
50549
|
-
if (
|
|
50775
|
+
if (dirname16(cursor) === cursor)
|
|
50550
50776
|
break;
|
|
50551
50777
|
}
|
|
50552
50778
|
}
|
|
@@ -50565,7 +50791,7 @@ function projectNativeDiscoveryFields(text2, format, fields2, path) {
|
|
|
50565
50791
|
const object7 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
|
|
50566
50792
|
if (!object7 || typeof object7 !== "object" || Array.isArray(object7))
|
|
50567
50793
|
throw new Error("Expected native discovery configuration object");
|
|
50568
|
-
return digest(JSON.stringify(Object.fromEntries(fields2.map((
|
|
50794
|
+
return digest(JSON.stringify(Object.fromEntries(fields2.map((field3) => [field3, object7[field3] ?? null]))));
|
|
50569
50795
|
}
|
|
50570
50796
|
function isSupersededSettingsProjection(agent, configPath, source) {
|
|
50571
50797
|
if (agent === "sumi")
|
|
@@ -50610,6 +50836,14 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
|
|
|
50610
50836
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
50611
50837
|
return sha2562;
|
|
50612
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
|
+
}
|
|
50613
50847
|
if (source.hashMode === "claude-plugin-registry") {
|
|
50614
50848
|
if (source.format !== undefined || source.fields !== undefined || !source.managedPlugins || changes?.has(source.path))
|
|
50615
50849
|
throw new Error("Managed plugin registry witnesses require verified native registrations");
|
|
@@ -50647,7 +50881,7 @@ function absentCodexSkillRoots(binding) {
|
|
|
50647
50881
|
throw new Error("Invalid disabled Codex discovery proof");
|
|
50648
50882
|
if (binding.method !== "reviewed" || controls.every((control) => lstatSync18(control.pluginParent, { throwIfNoEntry: false })))
|
|
50649
50883
|
return [];
|
|
50650
|
-
const cache =
|
|
50884
|
+
const cache = dirname16(dirname16(controls[0].pluginParent)), config2 = join26(dirname16(dirname16(cache)), "config.toml");
|
|
50651
50885
|
const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
50652
50886
|
if (!source || projected(source) !== source.sha256)
|
|
50653
50887
|
throw new Error("Missing current disabled Codex configuration witness");
|
|
@@ -50655,7 +50889,7 @@ function absentCodexSkillRoots(binding) {
|
|
|
50655
50889
|
return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
|
|
50656
50890
|
}
|
|
50657
50891
|
function codexDirectHookSelects(cache, root) {
|
|
50658
|
-
const codex =
|
|
50892
|
+
const codex = dirname16(dirname16(cache)), config2 = Bun.TOML.parse(read(join26(codex, "config.toml")) ?? "");
|
|
50659
50893
|
const hooks = read(join26(codex, "hooks.json"));
|
|
50660
50894
|
if (hooks !== null)
|
|
50661
50895
|
hashNativeJsonControls(hooks);
|
|
@@ -50668,7 +50902,7 @@ function retiredCodexRoots(binding) {
|
|
|
50668
50902
|
const controls = binding.codexDisabledPluginSkills;
|
|
50669
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)
|
|
50670
50904
|
throw new Error("Invalid retired Codex materialization proof");
|
|
50671
|
-
const cache =
|
|
50905
|
+
const cache = dirname16(dirname16(controls[0].pluginParent)), config2 = join26(dirname16(dirname16(cache)), "config.toml");
|
|
50672
50906
|
const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
50673
50907
|
if (!source || projected(source) !== source.sha256)
|
|
50674
50908
|
throw new Error("Missing current retired Codex configuration witness");
|
|
@@ -50699,7 +50933,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
50699
50933
|
safe4(root);
|
|
50700
50934
|
if (lstatSync18(root, { throwIfNoEntry: false }))
|
|
50701
50935
|
continue;
|
|
50702
|
-
const claude =
|
|
50936
|
+
const claude = dirname16(dirname16(cache)), settings = join26(claude, "settings.json"), registry2 = join26(claude, "plugins/installed_plugins.json");
|
|
50703
50937
|
const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
|
|
50704
50938
|
const configSource = full(settings), registrySource = full(registry2);
|
|
50705
50939
|
if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
|
|
@@ -50716,7 +50950,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
50716
50950
|
if (!Array.isArray(rows) || rows.length !== 1 || rows[0]?.scope !== "user" || typeof rows[0]?.installPath !== "string")
|
|
50717
50951
|
continue;
|
|
50718
50952
|
const active = rows[0].installPath;
|
|
50719
|
-
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)
|
|
50720
50954
|
continue;
|
|
50721
50955
|
const activeManifest = full(join26(active, ".claude-plugin/plugin.json"));
|
|
50722
50956
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
@@ -50767,7 +51001,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
50767
51001
|
assertMarketplaceBinding(binding, source);
|
|
50768
51002
|
if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
|
|
50769
51003
|
throw new Error("Managed Claude registry witnesses cannot apply to another agent");
|
|
50770
|
-
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)))
|
|
50771
51005
|
throw new Error("Invalid native discovery projection");
|
|
50772
51006
|
if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
50773
51007
|
throw new Error("Invalid native discovery digest");
|
|
@@ -50795,15 +51029,15 @@ function codexInstallationRoots(binding) {
|
|
|
50795
51029
|
const proof = binding.codexInstallationInputs;
|
|
50796
51030
|
if (proof === undefined)
|
|
50797
51031
|
return [];
|
|
50798
|
-
if (binding.agent !== "codex" || binding.method !== "reviewed" || proof.version
|
|
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)
|
|
50799
51033
|
throw new Error("Invalid native installation input proof");
|
|
50800
|
-
const cache =
|
|
50801
|
-
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)));
|
|
50802
51036
|
const configSource = binding.sources.find((source) => source.path === config2 && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
|
|
50803
51037
|
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join26(home, path));
|
|
50804
|
-
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)))))
|
|
50805
51039
|
throw new Error("Native installation input overlaps configuration or loading roots");
|
|
50806
|
-
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)))
|
|
50807
51041
|
throw new Error("Missing native installation input source witness");
|
|
50808
51042
|
return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
|
|
50809
51043
|
const text2 = read(path);
|
|
@@ -50813,16 +51047,18 @@ function codexInstallationRoots(binding) {
|
|
|
50813
51047
|
});
|
|
50814
51048
|
}
|
|
50815
51049
|
function assertMarketplaceBinding(binding, source) {
|
|
50816
|
-
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"))))
|
|
50817
51051
|
throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
|
|
50818
|
-
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"))
|
|
50819
51053
|
throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
|
|
50820
|
-
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"))
|
|
50821
51055
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
50822
|
-
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"))
|
|
50823
51057
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
50824
51058
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
50825
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");
|
|
50826
51062
|
}
|
|
50827
51063
|
function agentDiscoveryConfigPath(home, agent) {
|
|
50828
51064
|
if (agent === "sumi")
|
|
@@ -50830,10 +51066,10 @@ function agentDiscoveryConfigPath(home, agent) {
|
|
|
50830
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"}`);
|
|
50831
51067
|
}
|
|
50832
51068
|
function resolveAgentDiscovery(options) {
|
|
50833
|
-
const
|
|
51069
|
+
const canonical8 = options.canonical ?? resolve17, home = resolve17(options.home), agent = options.agent;
|
|
50834
51070
|
const sources = [], roots = new Set, builtinNames = [];
|
|
50835
51071
|
const witness = (path, format, fields2, hashMode) => {
|
|
50836
|
-
const source = { path:
|
|
51072
|
+
const source = { path: canonical8(path), sha256: null, ...format ? { format, fields: fields2 } : {}, ...hashMode ? { hashMode } : {} };
|
|
50837
51073
|
source.sha256 = projected(source);
|
|
50838
51074
|
sources.push(source);
|
|
50839
51075
|
return read(source.path);
|
|
@@ -50855,13 +51091,13 @@ function resolveAgentDiscovery(options) {
|
|
|
50855
51091
|
unresolved("JSONC configuration requires a supported format adapter");
|
|
50856
51092
|
for (const root of [directory, join26(home, ".claude"), join26(home, ".agents")])
|
|
50857
51093
|
for (const name of ["skill", "skills"])
|
|
50858
|
-
roots.add(
|
|
51094
|
+
roots.add(canonical8(join26(root, name)));
|
|
50859
51095
|
if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
|
|
50860
51096
|
unresolved("skills must be a string array");
|
|
50861
51097
|
for (const value of config2.skills ?? []) {
|
|
50862
|
-
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(
|
|
51098
|
+
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute15(value) || value.startsWith("~/")))
|
|
50863
51099
|
unresolved("remote or relative skill sources need a dedicated discovery adapter");
|
|
50864
|
-
roots.add(
|
|
51100
|
+
roots.add(canonical8(value.startsWith("~/") ? join26(home, value.slice(2)) : value));
|
|
50865
51101
|
}
|
|
50866
51102
|
for (const key of ["plugin", "plugins"])
|
|
50867
51103
|
if (config2[key] !== undefined && !Array.isArray(config2[key]))
|
|
@@ -50900,23 +51136,23 @@ function resolveAgentDiscovery(options) {
|
|
|
50900
51136
|
continue;
|
|
50901
51137
|
if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
|
|
50902
51138
|
unresolved("user-specific tilde expansion requires a separate discovery adapter");
|
|
50903
|
-
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);
|
|
50904
51140
|
safe4(path);
|
|
50905
51141
|
roots.add(path);
|
|
50906
51142
|
}
|
|
50907
51143
|
}
|
|
50908
51144
|
if (agent === "gemini") {
|
|
50909
|
-
const executable =
|
|
51145
|
+
const executable = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
|
|
50910
51146
|
if (executable) {
|
|
50911
51147
|
let packageRoot;
|
|
50912
|
-
for (let directory =
|
|
51148
|
+
for (let directory = dirname16(executable.target), depth = 0;depth < 8; directory = dirname16(directory), depth++) {
|
|
50913
51149
|
const path = join26(directory, "package.json"), raw = read(path);
|
|
50914
51150
|
if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
|
|
50915
51151
|
packageRoot = directory;
|
|
50916
51152
|
witness(path);
|
|
50917
51153
|
break;
|
|
50918
51154
|
}
|
|
50919
|
-
if (
|
|
51155
|
+
if (dirname16(directory) === directory)
|
|
50920
51156
|
break;
|
|
50921
51157
|
}
|
|
50922
51158
|
if (!packageRoot)
|
|
@@ -50939,11 +51175,11 @@ function resolveAgentDiscovery(options) {
|
|
|
50939
51175
|
if (retained.agent !== agent || retained.method !== "reviewed")
|
|
50940
51176
|
unresolved("invalid retained review");
|
|
50941
51177
|
verifyAgentDiscovery(retained);
|
|
50942
|
-
if (!retained.sources.some((source) => source.path ===
|
|
51178
|
+
if (!retained.sources.some((source) => source.path === canonical8(configPath) && source.format === undefined && source.fields === undefined))
|
|
50943
51179
|
unresolved("retained review is missing the full agent configuration source");
|
|
50944
|
-
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)))
|
|
50945
51181
|
unresolved("retained settings witness names another configuration source");
|
|
50946
|
-
const covered = supersedesSettingsProjection(agent, retained.sources,
|
|
51182
|
+
const covered = supersedesSettingsProjection(agent, retained.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
|
|
50947
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))
|
|
50948
51184
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
50949
51185
|
return retained;
|
|
@@ -50955,15 +51191,15 @@ function resolveAgentDiscovery(options) {
|
|
|
50955
51191
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
50956
51192
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
50957
51193
|
verifyAgentDiscovery(supplied);
|
|
50958
|
-
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)))
|
|
50959
51195
|
throw new Error("Semantic settings witnesses must name the configured agent configuration source");
|
|
50960
|
-
if (!review.sources.some((source) => source.path ===
|
|
51196
|
+
if (!review.sources.some((source) => source.path === canonical8(configPath)))
|
|
50961
51197
|
throw new Error("Discovery review must include the agent configuration source");
|
|
50962
|
-
const reviewedSources = supersedesSettingsProjection(agent, review.sources,
|
|
51198
|
+
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical8(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical8(configPath), source)) : sources;
|
|
50963
51199
|
const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
|
|
50964
|
-
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")))
|
|
50965
51201
|
return source;
|
|
50966
|
-
const pluginRoot =
|
|
51202
|
+
const pluginRoot = dirname16(dirname16(source.path)), hooksPath = join26(pluginRoot, "hooks/hooks.json");
|
|
50967
51203
|
const hookStat = lstatSync18(hooksPath, { throwIfNoEntry: false });
|
|
50968
51204
|
const text2 = read(source.path);
|
|
50969
51205
|
if (text2 === null)
|
|
@@ -50978,13 +51214,13 @@ function resolveAgentDiscovery(options) {
|
|
|
50978
51214
|
if (manifest.hooks !== undefined) {
|
|
50979
51215
|
if (typeof manifest.hooks !== "string")
|
|
50980
51216
|
throw new Error("Reviewed Claude plugin manifest has an unsupported hooks target");
|
|
50981
|
-
const declaredHookPath =
|
|
51217
|
+
const declaredHookPath = resolve17(pluginRoot, manifest.hooks);
|
|
50982
51218
|
if (!declaredHookPath.startsWith(pluginRoot + sep6))
|
|
50983
51219
|
throw new Error("Reviewed Claude plugin hooks target escapes its root");
|
|
50984
51220
|
reviewedHookPaths.add(declaredHookPath);
|
|
50985
51221
|
}
|
|
50986
51222
|
for (const hooksFile of reviewedHookPaths)
|
|
50987
|
-
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")))
|
|
50988
51224
|
throw new Error("Reviewed Claude plugin manifest requires separately reviewed exact hook file sources");
|
|
50989
51225
|
return { path: source.path, sha256: manifestSha256, hashMode: "claude-plugin-manifest-v1" };
|
|
50990
51226
|
});
|
|
@@ -50993,7 +51229,7 @@ function resolveAgentDiscovery(options) {
|
|
|
50993
51229
|
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: unique, ...agent === "gemini" ? { builtinNames } : {} };
|
|
50994
51230
|
}
|
|
50995
51231
|
function plugin(root) {
|
|
50996
|
-
root =
|
|
51232
|
+
root = canonical8(root);
|
|
50997
51233
|
safe4(root);
|
|
50998
51234
|
const manifestPath = join26(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
50999
51235
|
const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
|
|
@@ -51016,16 +51252,16 @@ function resolveAgentDiscovery(options) {
|
|
|
51016
51252
|
if (agent === "claude")
|
|
51017
51253
|
roots.add(join26(root, "skills"));
|
|
51018
51254
|
for (const value of declared) {
|
|
51019
|
-
const path =
|
|
51255
|
+
const path = resolve17(root, value);
|
|
51020
51256
|
if (path !== root && !path.startsWith(root + sep6))
|
|
51021
51257
|
unresolved("plugin skill path escapes its root");
|
|
51022
|
-
roots.add(path.endsWith(`${sep6}SKILL.md`) ?
|
|
51258
|
+
roots.add(path.endsWith(`${sep6}SKILL.md`) ? dirname16(path) : path);
|
|
51023
51259
|
}
|
|
51024
51260
|
}
|
|
51025
51261
|
if (agent === "claude") {
|
|
51026
51262
|
const registrations = witness(join26(home, ".claude/plugins/installed_plugins.json"));
|
|
51027
51263
|
const installed = registrations === null ? {} : parseConfig(registrations, join26(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
51028
|
-
const commands =
|
|
51264
|
+
const commands = canonical8(join26(home, ".claude/commands"));
|
|
51029
51265
|
safe4(commands);
|
|
51030
51266
|
if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
51031
51267
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
@@ -51047,7 +51283,7 @@ function resolveAgentDiscovery(options) {
|
|
|
51047
51283
|
unresolved("unsupported plugin enablement");
|
|
51048
51284
|
const split = id.lastIndexOf("@"), name = id.slice(0, split), marketplace = id.slice(split + 1);
|
|
51049
51285
|
const market = config2.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
|
|
51050
|
-
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))
|
|
51051
51287
|
unresolved("enabled plugin marketplace is not an explicit local source");
|
|
51052
51288
|
const catalogText = witness(join26(market.source, ".agents/plugins/marketplace.json"));
|
|
51053
51289
|
if (catalogText === null)
|
|
@@ -51055,7 +51291,7 @@ function resolveAgentDiscovery(options) {
|
|
|
51055
51291
|
const catalog = parseConfig(catalogText, join26(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
51056
51292
|
if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
|
|
51057
51293
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
51058
|
-
plugin(
|
|
51294
|
+
plugin(resolve17(market.source, matches[0].source.path));
|
|
51059
51295
|
}
|
|
51060
51296
|
} else if (agent === "opencode") {
|
|
51061
51297
|
if (witness(join26(home, ".config/opencode/opencode.jsonc")) !== null || witness(join26(home, ".config/opencode/config.json")) !== null)
|
|
@@ -51063,7 +51299,7 @@ function resolveAgentDiscovery(options) {
|
|
|
51063
51299
|
if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
|
|
51064
51300
|
unresolved("external plugin or remote skill source");
|
|
51065
51301
|
for (const path of config2.skills?.paths ?? []) {
|
|
51066
|
-
if (typeof path !== "string" || !
|
|
51302
|
+
if (typeof path !== "string" || !isAbsolute15(path))
|
|
51067
51303
|
unresolved("relative or malformed added skill root");
|
|
51068
51304
|
roots.add(path);
|
|
51069
51305
|
}
|
|
@@ -51072,7 +51308,7 @@ function resolveAgentDiscovery(options) {
|
|
|
51072
51308
|
if (lstatSync18(localPlugins, { throwIfNoEntry: false }) && readdirSync7(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
51073
51309
|
unresolved("additional local plugin hooks require review");
|
|
51074
51310
|
} else if (agent === "sumi") {
|
|
51075
|
-
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))
|
|
51076
51312
|
unresolved("external or foreign local plugins require review");
|
|
51077
51313
|
} else if (agent === "hermes") {
|
|
51078
51314
|
for (const directory of [join26(home, ".hermes/plugins"), join26(home, ".hermes/hermes-agent")]) {
|
|
@@ -51102,9 +51338,15 @@ function resolveAgentDiscovery(options) {
|
|
|
51102
51338
|
roots.add(join26(root, "skills"));
|
|
51103
51339
|
}
|
|
51104
51340
|
}
|
|
51105
|
-
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))) } : {} };
|
|
51106
51342
|
}
|
|
51107
|
-
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");
|
|
51108
51350
|
var init_agent_discovery = __esm(() => {
|
|
51109
51351
|
init_sumi_settings_witness();
|
|
51110
51352
|
init_agent_policy_limits();
|
|
@@ -51116,21 +51358,24 @@ var init_agent_discovery = __esm(() => {
|
|
|
51116
51358
|
init_plugin_discovery();
|
|
51117
51359
|
init_plugin_admission();
|
|
51118
51360
|
init_claude_marketplace_registry();
|
|
51361
|
+
init_claude_marketplace_entry_witness();
|
|
51119
51362
|
init_claude_settings_witness();
|
|
51120
51363
|
init_codex_hook_discovery_recovery();
|
|
51121
51364
|
init_codex_settings_witness();
|
|
51122
51365
|
init_codex_plugin_skill_controls();
|
|
51123
51366
|
init_agent_sumi();
|
|
51124
51367
|
init_native_discovery_roots();
|
|
51368
|
+
init_codex_native_compatibility();
|
|
51125
51369
|
init_agent_discovery_directories();
|
|
51370
|
+
DISCOVERY_RUNTIME_COMMANDS = Object.freeze({ gemini: "gemini" });
|
|
51126
51371
|
});
|
|
51127
51372
|
|
|
51128
51373
|
// src/lib/authoring-path.ts
|
|
51129
51374
|
import { lstatSync as lstatSync19, realpathSync as realpathSync6 } from "fs";
|
|
51130
51375
|
import { homedir as homedir3 } from "os";
|
|
51131
|
-
import { basename as
|
|
51376
|
+
import { basename as basename10, dirname as dirname17, join as join27, resolve as resolve18, sep as sep7 } from "path";
|
|
51132
51377
|
function pathParts(path) {
|
|
51133
|
-
return
|
|
51378
|
+
return resolve18(path).split(sep7).filter(Boolean);
|
|
51134
51379
|
}
|
|
51135
51380
|
function nativeRootMatch(path) {
|
|
51136
51381
|
const parts = pathParts(path);
|
|
@@ -51144,16 +51389,16 @@ function nativeRootMatch(path) {
|
|
|
51144
51389
|
return;
|
|
51145
51390
|
}
|
|
51146
51391
|
function physicalPath(path) {
|
|
51147
|
-
let cursor =
|
|
51392
|
+
let cursor = resolve18(path);
|
|
51148
51393
|
const suffix = [];
|
|
51149
51394
|
while (!lstatSync19(cursor, { throwIfNoEntry: false })) {
|
|
51150
|
-
suffix.unshift(
|
|
51151
|
-
const parent =
|
|
51395
|
+
suffix.unshift(basename10(cursor));
|
|
51396
|
+
const parent = dirname17(cursor);
|
|
51152
51397
|
if (parent === cursor)
|
|
51153
|
-
return
|
|
51398
|
+
return resolve18(path);
|
|
51154
51399
|
cursor = parent;
|
|
51155
51400
|
}
|
|
51156
|
-
return
|
|
51401
|
+
return resolve18(realpathSync6(cursor), ...suffix);
|
|
51157
51402
|
}
|
|
51158
51403
|
function contains(root, path) {
|
|
51159
51404
|
return path === root || path.startsWith(root + sep7);
|
|
@@ -51161,7 +51406,7 @@ function contains(root, path) {
|
|
|
51161
51406
|
function configuredRoots(home, explicitHome) {
|
|
51162
51407
|
const homeData = join27(home, ".hasna", "skills");
|
|
51163
51408
|
const homePolicy = readManagedSkillPolicySnapshot(homeData);
|
|
51164
|
-
const configuredPolicy = !explicitHome &&
|
|
51409
|
+
const configuredPolicy = !explicitHome && resolve18(getDataDirReadOnly()) !== resolve18(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
|
|
51165
51410
|
const policy = homePolicy ?? configuredPolicy;
|
|
51166
51411
|
const bridge = policy?.value.bridge;
|
|
51167
51412
|
if (bridge && (typeof bridge.home !== "string" || physicalPath(bridge.home) !== physicalPath(home))) {
|
|
@@ -51200,22 +51445,22 @@ function configuredRoots(home, explicitHome) {
|
|
|
51200
51445
|
function assertPortableAuthoringPath(path, options = {}) {
|
|
51201
51446
|
if (typeof path !== "string" || !path || path.includes("\x00"))
|
|
51202
51447
|
throw new Error("Invalid portable authoring path");
|
|
51203
|
-
const lexical =
|
|
51448
|
+
const lexical = resolve18(path);
|
|
51204
51449
|
const physical = physicalPath(lexical);
|
|
51205
51450
|
const candidates = [lexical, physical];
|
|
51206
51451
|
let native = candidates.map(nativeRootMatch).find(Boolean);
|
|
51207
|
-
const home =
|
|
51452
|
+
const home = resolve18(options.homeDir ?? homedir3());
|
|
51208
51453
|
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join27(home, ...parts));
|
|
51209
51454
|
defaults.push(join27(home, ".codex/plugins/cache"), join27(home, ".claude/plugins/cache"), join27(home, ".claude/plugins/synced"), join27(home, ".gemini/extensions"));
|
|
51210
51455
|
for (const root of defaults) {
|
|
51211
|
-
if (candidates.some((candidate) => contains(
|
|
51456
|
+
if (candidates.some((candidate) => contains(resolve18(root), candidate) || contains(physicalPath(root), candidate)))
|
|
51212
51457
|
native ??= root;
|
|
51213
51458
|
}
|
|
51214
51459
|
if (native) {
|
|
51215
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.`);
|
|
51216
51461
|
}
|
|
51217
51462
|
for (const root of configuredRoots(home, options.homeDir !== undefined)) {
|
|
51218
|
-
if (candidates.some((candidate) => contains(
|
|
51463
|
+
if (candidates.some((candidate) => contains(resolve18(root), candidate) || contains(physicalPath(root), candidate))) {
|
|
51219
51464
|
throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
|
|
51220
51465
|
}
|
|
51221
51466
|
}
|
|
@@ -51242,7 +51487,7 @@ import {
|
|
|
51242
51487
|
statSync as statSync7,
|
|
51243
51488
|
writeFileSync as writeFileSync6
|
|
51244
51489
|
} from "fs";
|
|
51245
|
-
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";
|
|
51246
51491
|
function getPortableSkillsRoot(options = {}) {
|
|
51247
51492
|
return resolvePortableSkillsRoot(options, true);
|
|
51248
51493
|
}
|
|
@@ -51337,20 +51582,20 @@ function scaffoldPortableSkill(name, options = {}) {
|
|
|
51337
51582
|
return { name: skillName, path: skillPath, manifest, created: true };
|
|
51338
51583
|
}
|
|
51339
51584
|
function physicalImportPath(path) {
|
|
51340
|
-
let ancestor =
|
|
51585
|
+
let ancestor = resolve19(path);
|
|
51341
51586
|
const suffix = [];
|
|
51342
51587
|
while (!existsSync12(ancestor)) {
|
|
51343
|
-
suffix.unshift(
|
|
51344
|
-
ancestor =
|
|
51588
|
+
suffix.unshift(basename11(ancestor));
|
|
51589
|
+
ancestor = dirname18(ancestor);
|
|
51345
51590
|
}
|
|
51346
51591
|
return join28(realpathSync7(ancestor), ...suffix);
|
|
51347
51592
|
}
|
|
51348
51593
|
function assertDisjointImportPaths(source, destination) {
|
|
51349
51594
|
const sourcePath = realpathSync7(source);
|
|
51350
51595
|
const destinationPath = physicalImportPath(destination);
|
|
51351
|
-
const contains2 = (parent,
|
|
51352
|
-
const path = relative5(parent,
|
|
51353
|
-
return path === "" || !
|
|
51596
|
+
const contains2 = (parent, child2) => {
|
|
51597
|
+
const path = relative5(parent, child2);
|
|
51598
|
+
return path === "" || !isAbsolute16(path) && path !== ".." && !path.startsWith(`..${sep8}`);
|
|
51354
51599
|
};
|
|
51355
51600
|
if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
|
|
51356
51601
|
throw new Error("Source and destination skill directories must not overlap");
|
|
@@ -51365,8 +51610,8 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
51365
51610
|
const explicitName = options.name != null;
|
|
51366
51611
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
51367
51612
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
51368
|
-
const sourceSlug = safeNormalizeName(
|
|
51369
|
-
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.`;
|
|
51370
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.`);
|
|
51371
51616
|
}
|
|
51372
51617
|
const readOnlyDestination = join28(resolvePortableSkillsRoot(options, false), skillName);
|
|
@@ -51381,7 +51626,7 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
51381
51626
|
throw new Error(`Skill '${skillName}' already exists at ${destination}`);
|
|
51382
51627
|
rmSync3(destination, { recursive: true, force: true });
|
|
51383
51628
|
}
|
|
51384
|
-
mkdirSync7(
|
|
51629
|
+
mkdirSync7(dirname18(destination), { recursive: true });
|
|
51385
51630
|
copySkillDirectory(absoluteSource, destination);
|
|
51386
51631
|
const base = {
|
|
51387
51632
|
...inferred,
|
|
@@ -51515,7 +51760,7 @@ function safeIsDirectory(path) {
|
|
|
51515
51760
|
}
|
|
51516
51761
|
}
|
|
51517
51762
|
function isSafeRelativePath2(value) {
|
|
51518
|
-
if (!value.trim() ||
|
|
51763
|
+
if (!value.trim() || isAbsolute16(value))
|
|
51519
51764
|
return false;
|
|
51520
51765
|
const normalized = normalize3(value).replace(/\\/g, "/");
|
|
51521
51766
|
return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
|
|
@@ -52144,11 +52389,14 @@ var init_skill_context = __esm(() => {
|
|
|
52144
52389
|
});
|
|
52145
52390
|
|
|
52146
52391
|
// src/lib/session-reconciliation.ts
|
|
52147
|
-
var SESSION_RECONCILIATION_PLAN_TTL_MS;
|
|
52392
|
+
var SESSION_RECONCILIATION_PLAN_TTL_MS, SESSION_RENEWAL_REFUSAL_TTL_MS, SESSION_RENEWAL_REFUSAL_MAX_BYTES;
|
|
52148
52393
|
var init_session_reconciliation = __esm(() => {
|
|
52149
52394
|
init_profile_client();
|
|
52395
|
+
init_skill_bundle();
|
|
52150
52396
|
init_selection_cache();
|
|
52151
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;
|
|
52152
52400
|
});
|
|
52153
52401
|
|
|
52154
52402
|
// src/cli/commands/context.ts
|
|
@@ -52186,7 +52434,7 @@ var init_remote_customer_operations = __esm(() => {
|
|
|
52186
52434
|
});
|
|
52187
52435
|
|
|
52188
52436
|
// src/lib/canonical-json.ts
|
|
52189
|
-
import { createHash as
|
|
52437
|
+
import { createHash as createHash19 } from "crypto";
|
|
52190
52438
|
function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
|
|
52191
52439
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
52192
52440
|
}
|
|
@@ -52230,7 +52478,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
52230
52478
|
return visit3(value, 0);
|
|
52231
52479
|
}
|
|
52232
52480
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
52233
|
-
return
|
|
52481
|
+
return createHash19("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
|
|
52234
52482
|
}
|
|
52235
52483
|
var init_canonical_json = () => {};
|
|
52236
52484
|
|
|
@@ -52981,13 +53229,13 @@ var init_remote_workspace_leave = __esm(() => {
|
|
|
52981
53229
|
|
|
52982
53230
|
// src/lib/auth-store.ts
|
|
52983
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";
|
|
52984
|
-
import { basename as
|
|
53232
|
+
import { basename as basename12, dirname as dirname19, join as join30 } from "path";
|
|
52985
53233
|
function getAuthFilePath(env = process.env) {
|
|
52986
53234
|
return skillsCredentialFilePath(env);
|
|
52987
53235
|
}
|
|
52988
53236
|
function getIdentityFilePath(env = process.env) {
|
|
52989
53237
|
const file2 = skillsCredentialFilePath(env);
|
|
52990
|
-
return join30(
|
|
53238
|
+
return join30(dirname19(file2), basename12(file2).replace(/^credentials/, "identity") + ".json");
|
|
52991
53239
|
}
|
|
52992
53240
|
function getApiUrl(action, env = process.env, options = {}) {
|
|
52993
53241
|
return requireSkillsApiOrigin(action, env, options);
|
|
@@ -53069,17 +53317,17 @@ function runQuoteReceipt(value) {
|
|
|
53069
53317
|
return value;
|
|
53070
53318
|
}
|
|
53071
53319
|
function parseRemoteRunQuote(value) {
|
|
53072
|
-
const
|
|
53073
|
-
runQuoteReceipt(
|
|
53074
|
-
const pricing = object7(
|
|
53075
|
-
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))
|
|
53076
53324
|
throw new Error("Invalid quoted skill");
|
|
53077
53325
|
const costCents = creditCount(pricing.costCredits ?? pricing.costCents);
|
|
53078
53326
|
if (pricing.costCredits !== undefined && pricing.costCents !== undefined && pricing.costCents !== costCents)
|
|
53079
53327
|
throw new Error("Inconsistent quoted credit count");
|
|
53080
|
-
if (
|
|
53328
|
+
if (quote3.availability && object7(quote3.availability).status !== "available")
|
|
53081
53329
|
throw new Error("This skill is unavailable for remote execution");
|
|
53082
|
-
return { ...
|
|
53330
|
+
return { ...quote3, skill: quote3.skill, pricing: { ...pricing, costCredits: costCents, costCents, formattedCost: `${costCents} credits` } };
|
|
53083
53331
|
}
|
|
53084
53332
|
function parseRemoteCreditPacks(value) {
|
|
53085
53333
|
if (!Array.isArray(value))
|
|
@@ -53171,14 +53419,14 @@ var init_remote_credit_checkout = __esm(() => {
|
|
|
53171
53419
|
});
|
|
53172
53420
|
|
|
53173
53421
|
// src/lib/remote-profile.ts
|
|
53174
|
-
function customerNamePatch(input2,
|
|
53175
|
-
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))
|
|
53176
53424
|
throw new Error("Provide only the requested name field.");
|
|
53177
|
-
const value = input2[
|
|
53425
|
+
const value = input2[field3];
|
|
53178
53426
|
if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
|
|
53179
53427
|
throw new Error("Use a name of 1\u2013100 characters without control characters or newlines.");
|
|
53180
53428
|
}
|
|
53181
|
-
return { [
|
|
53429
|
+
return { [field3]: value.trim() };
|
|
53182
53430
|
}
|
|
53183
53431
|
function isRecord5(value) {
|
|
53184
53432
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -53215,10 +53463,10 @@ async function readQuoteUnavailableCode(response) {
|
|
|
53215
53463
|
let timer;
|
|
53216
53464
|
let deadlineExceeded = false;
|
|
53217
53465
|
const expired = Symbol("quote body deadline");
|
|
53218
|
-
const deadline = new Promise((
|
|
53466
|
+
const deadline = new Promise((resolve20) => {
|
|
53219
53467
|
timer = setTimeout(() => {
|
|
53220
53468
|
deadlineExceeded = true;
|
|
53221
|
-
|
|
53469
|
+
resolve20(expired);
|
|
53222
53470
|
reader.cancel().catch(() => {});
|
|
53223
53471
|
}, 1500);
|
|
53224
53472
|
});
|
|
@@ -53501,18 +53749,18 @@ class RemoteSkillsClient {
|
|
|
53501
53749
|
const maximum = creditCount(approval.maxCredits ?? approval.maxCostCents ?? 0);
|
|
53502
53750
|
if (approval.maxCostCents !== undefined && approval.maxCostCents !== maximum)
|
|
53503
53751
|
throw new Error("Credit approval fields disagree");
|
|
53504
|
-
const
|
|
53505
|
-
if (
|
|
53506
|
-
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);
|
|
53507
53755
|
const capabilities = await this.getCapabilities();
|
|
53508
53756
|
if (!capabilities.capabilities.includes("runs.submit") || capabilities.billing?.boundedRunApproval !== true || capabilities.billing.unit !== "credits") {
|
|
53509
53757
|
throw new Error("The configured server does not support bounded credit approval; refusing remote submission");
|
|
53510
53758
|
}
|
|
53511
|
-
return this.submitRun(
|
|
53759
|
+
return this.submitRun(quote3?.skill ?? slug2, input2, args, {
|
|
53512
53760
|
...approval,
|
|
53513
53761
|
maxCredits: maximum,
|
|
53514
53762
|
maxCostCents: maximum,
|
|
53515
|
-
...(
|
|
53763
|
+
...(quote3?.quoteReceipt ?? approval.quoteReceipt) === undefined ? {} : { quoteReceipt: quote3?.quoteReceipt ?? approval.quoteReceipt }
|
|
53516
53764
|
});
|
|
53517
53765
|
}
|
|
53518
53766
|
async getIdentity() {
|
|
@@ -54113,13 +54361,13 @@ class RemoteSkillsClient {
|
|
|
54113
54361
|
return normalizeUpdatedSincePage(await response.json());
|
|
54114
54362
|
}
|
|
54115
54363
|
}
|
|
54116
|
-
function requireOptionalString(record9,
|
|
54117
|
-
if (record9[
|
|
54364
|
+
function requireOptionalString(record9, field3) {
|
|
54365
|
+
if (record9[field3] === undefined)
|
|
54118
54366
|
return;
|
|
54119
|
-
if (typeof record9[
|
|
54120
|
-
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)`);
|
|
54121
54369
|
}
|
|
54122
|
-
return record9[
|
|
54370
|
+
return record9[field3];
|
|
54123
54371
|
}
|
|
54124
54372
|
function isVersionRecord(value) {
|
|
54125
54373
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -54456,7 +54704,7 @@ var init_remote_invitation_recovery = __esm(() => {
|
|
|
54456
54704
|
});
|
|
54457
54705
|
|
|
54458
54706
|
// src/lib/remote-private-publications.ts
|
|
54459
|
-
import { createHash as
|
|
54707
|
+
import { createHash as createHash20 } from "crypto";
|
|
54460
54708
|
function checkedPublicationDeclaration(value) {
|
|
54461
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)
|
|
54462
54710
|
return bad();
|
|
@@ -54701,12 +54949,12 @@ class RemotePrivatePublicationsClient {
|
|
|
54701
54949
|
previous = view;
|
|
54702
54950
|
if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
|
|
54703
54951
|
return view;
|
|
54704
|
-
await new Promise((
|
|
54952
|
+
await new Promise((resolve20) => {
|
|
54705
54953
|
const timer = setTimeout(done, Math.min(1000, until - Date.now()));
|
|
54706
54954
|
function done() {
|
|
54707
54955
|
clearTimeout(timer);
|
|
54708
54956
|
options.signal?.removeEventListener("abort", done);
|
|
54709
|
-
|
|
54957
|
+
resolve20();
|
|
54710
54958
|
}
|
|
54711
54959
|
options.signal?.addEventListener("abort", done, { once: true });
|
|
54712
54960
|
});
|
|
@@ -54717,7 +54965,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
|
|
|
54717
54965
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
54718
54966
|
}, invalid4 = () => {
|
|
54719
54967
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
54720
|
-
}, 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");
|
|
54721
54969
|
var init_remote_private_publications = __esm(() => {
|
|
54722
54970
|
init_fleet_credentials();
|
|
54723
54971
|
init_remote_workspace_selection();
|
|
@@ -55227,7 +55475,7 @@ var init_recurring_customer = __esm(() => {
|
|
|
55227
55475
|
|
|
55228
55476
|
// src/lib/recurring-recovery.ts
|
|
55229
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";
|
|
55230
|
-
import { dirname as
|
|
55478
|
+
import { dirname as dirname20, isAbsolute as isAbsolute17, join as join31, resolve as resolve20 } from "path";
|
|
55231
55479
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
55232
55480
|
|
|
55233
55481
|
class RecoveryOwner {
|
|
@@ -55235,14 +55483,14 @@ class RecoveryOwner {
|
|
|
55235
55483
|
parents = [];
|
|
55236
55484
|
constructor(directory) {
|
|
55237
55485
|
this.directory = directory;
|
|
55238
|
-
if (!
|
|
55486
|
+
if (!isAbsolute17(directory) || resolve20(directory) !== directory || realpathSync8(directory) !== directory)
|
|
55239
55487
|
invalid5();
|
|
55240
|
-
for (let path = directory;; path =
|
|
55488
|
+
for (let path = directory;; path = dirname20(path)) {
|
|
55241
55489
|
const stat3 = lstatSync21(path);
|
|
55242
55490
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
55243
55491
|
invalid5();
|
|
55244
55492
|
this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
|
|
55245
|
-
if (path ===
|
|
55493
|
+
if (path === dirname20(path))
|
|
55246
55494
|
break;
|
|
55247
55495
|
}
|
|
55248
55496
|
this.assert();
|
|
@@ -55370,7 +55618,7 @@ function base(customer, organizationId) {
|
|
|
55370
55618
|
};
|
|
55371
55619
|
}
|
|
55372
55620
|
function create(directory, intent) {
|
|
55373
|
-
if (!
|
|
55621
|
+
if (!isAbsolute17(directory) || resolve20(directory) !== directory || realpathSync8(dirname20(directory)) !== dirname20(directory))
|
|
55374
55622
|
invalid5();
|
|
55375
55623
|
mkdirSync10(directory, { mode: 448 });
|
|
55376
55624
|
const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
|
|
@@ -55533,7 +55781,7 @@ var init_recurring_recovery = __esm(() => {
|
|
|
55533
55781
|
});
|
|
55534
55782
|
|
|
55535
55783
|
// src/lib/recurring-surface.ts
|
|
55536
|
-
import { isAbsolute as
|
|
55784
|
+
import { isAbsolute as isAbsolute18 } from "path";
|
|
55537
55785
|
function recurringMcpSchema(action) {
|
|
55538
55786
|
return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
|
|
55539
55787
|
}
|
|
@@ -55638,7 +55886,7 @@ var init_recurring_surface = __esm(() => {
|
|
|
55638
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}$/);
|
|
55639
55887
|
context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
|
|
55640
55888
|
page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
|
|
55641
|
-
directory = exports_external.string().max(4096).refine(
|
|
55889
|
+
directory = exports_external.string().max(4096).refine(isAbsolute18, "Use an absolute recovery directory");
|
|
55642
55890
|
email4 = exports_external.string().trim().toLowerCase().email().max(254);
|
|
55643
55891
|
code = exports_external.string().regex(/^\d{6}$/);
|
|
55644
55892
|
recurringSurfaceSchemas = {
|
|
@@ -57467,7 +57715,7 @@ var init_credential_state = __esm(() => {
|
|
|
57467
57715
|
});
|
|
57468
57716
|
|
|
57469
57717
|
// src/lib/run-state.ts
|
|
57470
|
-
import { createHash as
|
|
57718
|
+
import { createHash as createHash21, randomBytes } from "crypto";
|
|
57471
57719
|
import { existsSync as existsSync15, mkdirSync as mkdirSync11, readFileSync as readFileSync19, readdirSync as readdirSync10, statSync as statSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
57472
57720
|
import { extname, join as join32, relative as relative6 } from "path";
|
|
57473
57721
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
@@ -57582,7 +57830,7 @@ function collectRunArtifacts(context2) {
|
|
|
57582
57830
|
artifacts.push({
|
|
57583
57831
|
path: toProjectRelative(context2.targetDir, path),
|
|
57584
57832
|
mime: mimeForPath(path),
|
|
57585
|
-
sha256:
|
|
57833
|
+
sha256: createHash21("sha256").update(bytes).digest("hex"),
|
|
57586
57834
|
sizeBytes: stat3.size
|
|
57587
57835
|
});
|
|
57588
57836
|
}
|
|
@@ -57828,12 +58076,12 @@ function parseExecution(value) {
|
|
|
57828
58076
|
].includes(v.status) || typeof v.skill !== "string" || typeof v.version !== "string" || !Array.isArray(v.artifacts))
|
|
57829
58077
|
throw Error("Unsupported cloud execution response");
|
|
57830
58078
|
runId(v.id);
|
|
57831
|
-
for (const
|
|
58079
|
+
for (const field3 of [
|
|
57832
58080
|
"bundleDigest",
|
|
57833
58081
|
"inputDigest",
|
|
57834
58082
|
"runtimeImageDigest"
|
|
57835
58083
|
])
|
|
57836
|
-
if (typeof v[
|
|
58084
|
+
if (typeof v[field3] !== "string" || !/^(sha256:)?[a-f0-9]{64}$/.test(v[field3]))
|
|
57837
58085
|
throw Error("Invalid cloud execution integrity receipt");
|
|
57838
58086
|
return v;
|
|
57839
58087
|
}
|
|
@@ -57858,7 +58106,7 @@ import { closeSync as closeSync16, fstatSync as fstatSync16, openSync as openSyn
|
|
|
57858
58106
|
import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
|
|
57859
58107
|
import { createRequire as createRequire2 } from "module";
|
|
57860
58108
|
import { hostname as osHostname2 } from "os";
|
|
57861
|
-
import { isAbsolute as
|
|
58109
|
+
import { isAbsolute as isAbsolute19, join as join33 } from "path";
|
|
57862
58110
|
import { createRequire as createRequire22 } from "module";
|
|
57863
58111
|
function envToken2(name) {
|
|
57864
58112
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -57882,7 +58130,7 @@ function homeDir2(env) {
|
|
|
57882
58130
|
}
|
|
57883
58131
|
function absoluteOverride2(env, key) {
|
|
57884
58132
|
const value = env[key]?.trim();
|
|
57885
|
-
return value &&
|
|
58133
|
+
return value && isAbsolute19(value) ? value : null;
|
|
57886
58134
|
}
|
|
57887
58135
|
function hasnaHomeDir2(env) {
|
|
57888
58136
|
const override = absoluteOverride2(env, HASNA_HOME_ENV_KEY2);
|
|
@@ -57928,9 +58176,9 @@ function parseEnvFile2(text3) {
|
|
|
57928
58176
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
|
|
57929
58177
|
continue;
|
|
57930
58178
|
let value = withoutExport.slice(equals + 1).trim();
|
|
57931
|
-
const
|
|
57932
|
-
if (
|
|
57933
|
-
if (value.length < 2 || !value.endsWith(
|
|
58179
|
+
const quote3 = value[0];
|
|
58180
|
+
if (quote3 === '"' || quote3 === "'") {
|
|
58181
|
+
if (value.length < 2 || !value.endsWith(quote3)) {
|
|
57934
58182
|
unusable.add(key);
|
|
57935
58183
|
continue;
|
|
57936
58184
|
}
|
|
@@ -57954,8 +58202,8 @@ function configFileReadsCoherent2(before, after) {
|
|
|
57954
58202
|
return before.dev === after.dev && before.ino === after.ino && before.size === after.size && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs;
|
|
57955
58203
|
}
|
|
57956
58204
|
function readAppConfigFile2(path) {
|
|
57957
|
-
const unsafe = (
|
|
57958
|
-
throw new CredentialFileUnsafeError2(path,
|
|
58205
|
+
const unsafe = (reason2) => {
|
|
58206
|
+
throw new CredentialFileUnsafeError2(path, reason2);
|
|
57959
58207
|
};
|
|
57960
58208
|
let fd = -1;
|
|
57961
58209
|
try {
|
|
@@ -58174,8 +58422,8 @@ function readKeychainItem2(name, env, kind, options) {
|
|
|
58174
58422
|
try {
|
|
58175
58423
|
result = run(["find-generic-password", "-a", account, "-s", service, "-w"]);
|
|
58176
58424
|
} catch (error61) {
|
|
58177
|
-
const
|
|
58178
|
-
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]);
|
|
58179
58427
|
}
|
|
58180
58428
|
if (result.status === KEYCHAIN_ITEM_NOT_FOUND_STATUS2)
|
|
58181
58429
|
return null;
|
|
@@ -59019,7 +59267,7 @@ function createSecretsClientFromEnv(env = process.env, overrides = {}) {
|
|
|
59019
59267
|
});
|
|
59020
59268
|
return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
|
|
59021
59269
|
}
|
|
59022
|
-
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;
|
|
59023
59271
|
var init_sdk = __esm(() => {
|
|
59024
59272
|
init_transport2 = __esm2(() => {
|
|
59025
59273
|
CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
|
|
@@ -59034,8 +59282,8 @@ var init_sdk = __esm(() => {
|
|
|
59034
59282
|
};
|
|
59035
59283
|
CredentialFileUnsafeError2 = class CredentialFileUnsafeError3 extends Error {
|
|
59036
59284
|
path;
|
|
59037
|
-
constructor(path,
|
|
59038
|
-
super(`Refusing unsafe credential/config file ${path}: ${
|
|
59285
|
+
constructor(path, reason2) {
|
|
59286
|
+
super(`Refusing unsafe credential/config file ${path}: ${reason2}.`);
|
|
59039
59287
|
this.name = "CredentialFileUnsafeError";
|
|
59040
59288
|
this.path = path;
|
|
59041
59289
|
}
|
|
@@ -59396,10 +59644,10 @@ __export(exports_selected_run, {
|
|
|
59396
59644
|
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
59397
59645
|
executeSelectedLocal: () => executeSelectedLocal
|
|
59398
59646
|
});
|
|
59399
|
-
import { createHash as
|
|
59647
|
+
import { createHash as createHash22 } from "crypto";
|
|
59400
59648
|
import { spawn } from "child_process";
|
|
59401
59649
|
import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync10 } from "fs";
|
|
59402
|
-
import { dirname as
|
|
59650
|
+
import { dirname as dirname21, join as join34, resolve as resolve21 } from "path";
|
|
59403
59651
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
59404
59652
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
59405
59653
|
const context2 = await resolveSelectionContext(profileId, options);
|
|
@@ -59488,11 +59736,11 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
59488
59736
|
throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
|
|
59489
59737
|
});
|
|
59490
59738
|
const destination = join34(runDirectory, entry.path);
|
|
59491
|
-
mkdirSync12(
|
|
59739
|
+
mkdirSync12(dirname21(destination), { recursive: true, mode: 448 });
|
|
59492
59740
|
writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
|
|
59493
59741
|
}
|
|
59494
59742
|
env.SKILLS_INPUT_JSON = input2;
|
|
59495
|
-
env.SKILLS_WORKSPACE_DIR =
|
|
59743
|
+
env.SKILLS_WORKSPACE_DIR = resolve21(options.cwd ?? process.cwd());
|
|
59496
59744
|
env.SKILLS_RUN_DIR = runDirectory;
|
|
59497
59745
|
if (runtime.version) {
|
|
59498
59746
|
const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
|
|
@@ -59522,7 +59770,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
59522
59770
|
selection: selection2,
|
|
59523
59771
|
target: "local",
|
|
59524
59772
|
runtime: runtimeName,
|
|
59525
|
-
inputDigest: `sha256:${
|
|
59773
|
+
inputDigest: `sha256:${createHash22("sha256").update(input2).digest("hex")}`,
|
|
59526
59774
|
runDirectory,
|
|
59527
59775
|
...executionGrant ? { executionGrant } : {},
|
|
59528
59776
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
@@ -59533,17 +59781,17 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
59533
59781
|
}
|
|
59534
59782
|
async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
59535
59783
|
return new Promise((resolveResult) => {
|
|
59536
|
-
const
|
|
59784
|
+
const child2 = spawn(command[0], command.slice(1), { cwd, env, shell: false, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
59537
59785
|
let outputBytes = 0, error61, ended = false;
|
|
59538
59786
|
const stdout = [], stderr = [];
|
|
59539
59787
|
const kill = () => {
|
|
59540
59788
|
try {
|
|
59541
|
-
if (process.platform !== "win32" &&
|
|
59542
|
-
process.kill(-
|
|
59789
|
+
if (process.platform !== "win32" && child2.pid)
|
|
59790
|
+
process.kill(-child2.pid, "SIGKILL");
|
|
59543
59791
|
else
|
|
59544
|
-
|
|
59792
|
+
child2.kill("SIGKILL");
|
|
59545
59793
|
} catch {
|
|
59546
|
-
|
|
59794
|
+
child2.kill("SIGKILL");
|
|
59547
59795
|
}
|
|
59548
59796
|
};
|
|
59549
59797
|
const timer = setTimeout(() => {
|
|
@@ -59559,8 +59807,8 @@ async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
|
59559
59807
|
}
|
|
59560
59808
|
target.push(chunk);
|
|
59561
59809
|
};
|
|
59562
|
-
|
|
59563
|
-
|
|
59810
|
+
child2.stdout.on("data", capture2(stdout));
|
|
59811
|
+
child2.stderr.on("data", capture2(stderr));
|
|
59564
59812
|
const finish = (code2) => {
|
|
59565
59813
|
if (ended)
|
|
59566
59814
|
return;
|
|
@@ -59568,13 +59816,13 @@ async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
|
59568
59816
|
clearTimeout(timer);
|
|
59569
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 } : {} });
|
|
59570
59818
|
};
|
|
59571
|
-
|
|
59819
|
+
child2.on("error", () => {
|
|
59572
59820
|
error61 = "LOCAL_RUNTIME_START_FAILED";
|
|
59573
59821
|
finish(127);
|
|
59574
59822
|
});
|
|
59575
|
-
|
|
59576
|
-
|
|
59577
|
-
|
|
59823
|
+
child2.on("close", (code2) => finish(code2 ?? 1));
|
|
59824
|
+
child2.stdin.on("error", () => {});
|
|
59825
|
+
child2.stdin.end(input2);
|
|
59578
59826
|
});
|
|
59579
59827
|
}
|
|
59580
59828
|
var init_selected_run = __esm(() => {
|
|
@@ -60091,9 +60339,9 @@ function registerOperationTools(server) {
|
|
|
60091
60339
|
}
|
|
60092
60340
|
}, async ({ run_id, detail }) => {
|
|
60093
60341
|
const { skillsCredentialOrReason: skillsCredentialOrReason2 } = await Promise.resolve().then(() => (init_fleet_credentials(), exports_fleet_credentials));
|
|
60094
|
-
const { apiKey, apiOrigin, reason } = await skillsCredentialOrReason2();
|
|
60342
|
+
const { apiKey, apiOrigin, reason: reason2 } = await skillsCredentialOrReason2();
|
|
60095
60343
|
if (!apiKey) {
|
|
60096
|
-
return mcpError("AUTH_REQUIRED",
|
|
60344
|
+
return mcpError("AUTH_REQUIRED", reason2 ?? "Remote run status requires API access. Run: skills auth login", ["skills auth login"]);
|
|
60097
60345
|
}
|
|
60098
60346
|
const localRun = findSkillRun(run_id);
|
|
60099
60347
|
const remoteRunId = localRun?.remoteRunId || run_id;
|
|
@@ -60263,14 +60511,14 @@ var init_operation_tools = __esm(() => {
|
|
|
60263
60511
|
|
|
60264
60512
|
// src/lib/feedback.ts
|
|
60265
60513
|
import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync13 } from "fs";
|
|
60266
|
-
import { dirname as
|
|
60514
|
+
import { dirname as dirname22, join as join36 } from "path";
|
|
60267
60515
|
import { Database } from "bun:sqlite";
|
|
60268
60516
|
function getFeedbackDbPath() {
|
|
60269
60517
|
return join36(getDataDir(), "skills.db");
|
|
60270
60518
|
}
|
|
60271
60519
|
function getFeedbackDb() {
|
|
60272
60520
|
const dbPath = getFeedbackDbPath();
|
|
60273
|
-
const dir =
|
|
60521
|
+
const dir = dirname22(dbPath);
|
|
60274
60522
|
if (!existsSync17(dir))
|
|
60275
60523
|
mkdirSync13(dir, { recursive: true });
|
|
60276
60524
|
const db = new Database(dbPath);
|
|
@@ -60299,7 +60547,7 @@ function saveFeedback(input2) {
|
|
|
60299
60547
|
const category = input2.category ?? "general";
|
|
60300
60548
|
if (isApiMode()) {
|
|
60301
60549
|
const path = join36(getDataDir(), "feedback.jsonl");
|
|
60302
|
-
const dir =
|
|
60550
|
+
const dir = dirname22(path);
|
|
60303
60551
|
if (!existsSync17(dir))
|
|
60304
60552
|
mkdirSync13(dir, { recursive: true });
|
|
60305
60553
|
appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
|
|
@@ -60750,7 +60998,7 @@ var init_schedule_tools = __esm(() => {
|
|
|
60750
60998
|
});
|
|
60751
60999
|
|
|
60752
61000
|
// src/lib/native-storage.ts
|
|
60753
|
-
import { createHash as
|
|
61001
|
+
import { createHash as createHash23, createHmac } from "crypto";
|
|
60754
61002
|
import {
|
|
60755
61003
|
existsSync as existsSync19,
|
|
60756
61004
|
mkdirSync as mkdirSync15,
|
|
@@ -60759,7 +61007,7 @@ import {
|
|
|
60759
61007
|
statSync as statSync11,
|
|
60760
61008
|
writeFileSync as writeFileSync13
|
|
60761
61009
|
} from "fs";
|
|
60762
|
-
import { dirname as
|
|
61010
|
+
import { dirname as dirname23, join as join38, normalize as normalize4, relative as relative7, sep as sep9 } from "path";
|
|
60763
61011
|
function resolveSkillsNativeStorageConfig(env = process.env) {
|
|
60764
61012
|
assertNoRetiredModeEnvVars(env, {
|
|
60765
61013
|
app: SKILLS_ENV_NAMESPACE,
|
|
@@ -60827,7 +61075,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
60827
61075
|
files.push({
|
|
60828
61076
|
path: relativePath,
|
|
60829
61077
|
sizeBytes: bytes.byteLength,
|
|
60830
|
-
sha256:
|
|
61078
|
+
sha256: createHash23("sha256").update(bytes).digest("hex"),
|
|
60831
61079
|
...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
|
|
60832
61080
|
});
|
|
60833
61081
|
}
|
|
@@ -61120,16 +61368,16 @@ var init_private_publication_customer = __esm(() => {
|
|
|
61120
61368
|
|
|
61121
61369
|
// src/lib/private-publication-recovery.ts
|
|
61122
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";
|
|
61123
|
-
import { dirname as
|
|
61371
|
+
import { dirname as dirname24, isAbsolute as isAbsolute20, join as join39, resolve as resolve22 } from "path";
|
|
61124
61372
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
61125
61373
|
function safeDirectory(directory2) {
|
|
61126
|
-
if (!
|
|
61374
|
+
if (!isAbsolute20(directory2) || directory2 !== resolve22(directory2) || realpathSync11(directory2) !== directory2)
|
|
61127
61375
|
return fail2();
|
|
61128
|
-
for (let path = directory2;; path =
|
|
61376
|
+
for (let path = directory2;; path = dirname24(path)) {
|
|
61129
61377
|
const stat3 = lstatSync22(path);
|
|
61130
61378
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
61131
61379
|
return fail2();
|
|
61132
|
-
if (path ===
|
|
61380
|
+
if (path === dirname24(path))
|
|
61133
61381
|
break;
|
|
61134
61382
|
}
|
|
61135
61383
|
const own2 = lstatSync22(directory2);
|
|
@@ -61261,11 +61509,11 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
|
|
|
61261
61509
|
phase: "prepared",
|
|
61262
61510
|
intent: null
|
|
61263
61511
|
};
|
|
61264
|
-
if (!
|
|
61512
|
+
if (!isAbsolute20(recoveryDirectory) || resolve22(recoveryDirectory) !== recoveryDirectory || realpathSync11(dirname24(recoveryDirectory)) !== dirname24(recoveryDirectory))
|
|
61265
61513
|
return fail2();
|
|
61266
61514
|
mkdirSync16(recoveryDirectory, { mode: 448 });
|
|
61267
61515
|
safeDirectory(recoveryDirectory);
|
|
61268
|
-
const parent = openSync18(
|
|
61516
|
+
const parent = openSync18(dirname24(recoveryDirectory), constants14.O_RDONLY | constants14.O_NOFOLLOW);
|
|
61269
61517
|
try {
|
|
61270
61518
|
fsyncSync5(parent);
|
|
61271
61519
|
} finally {
|
|
@@ -61362,10 +61610,10 @@ var init_private_publication_recovery = __esm(() => {
|
|
|
61362
61610
|
});
|
|
61363
61611
|
|
|
61364
61612
|
// src/mcp/private-publication-tools.ts
|
|
61365
|
-
import { isAbsolute as
|
|
61613
|
+
import { isAbsolute as isAbsolute21 } from "path";
|
|
61366
61614
|
function registerPrivatePublicationTools(server) {
|
|
61367
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}$/);
|
|
61368
|
-
const directory2 = exports_external.string().max(4096).refine(
|
|
61616
|
+
const directory2 = exports_external.string().max(4096).refine(isAbsolute21, "Use an absolute local directory");
|
|
61369
61617
|
const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
|
|
61370
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.";
|
|
61371
61619
|
const handler = (action) => async (value) => {
|
|
@@ -61777,8 +62025,8 @@ var WSContext = class {
|
|
|
61777
62025
|
}
|
|
61778
62026
|
url;
|
|
61779
62027
|
protocol;
|
|
61780
|
-
close(code2,
|
|
61781
|
-
this.#init.close(code2,
|
|
62028
|
+
close(code2, reason2) {
|
|
62029
|
+
this.#init.close(code2, reason2);
|
|
61782
62030
|
}
|
|
61783
62031
|
}, defineWebSocketHelper = (handler) => {
|
|
61784
62032
|
return (...args) => {
|
|
@@ -62058,9 +62306,9 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62058
62306
|
}, normalizeAbortError = (request2, incoming) => {
|
|
62059
62307
|
if (incoming.errored)
|
|
62060
62308
|
return incoming.errored;
|
|
62061
|
-
const
|
|
62062
|
-
if (
|
|
62063
|
-
return
|
|
62309
|
+
const reason2 = request2[abortReasonKey];
|
|
62310
|
+
if (reason2 !== undefined)
|
|
62311
|
+
return reason2 instanceof Error ? reason2 : new Error(String(reason2));
|
|
62064
62312
|
return /* @__PURE__ */ new Error("Client connection prematurely closed.");
|
|
62065
62313
|
}, readBodyDirect = (request2) => {
|
|
62066
62314
|
if (request2[bodyBufferKey])
|
|
@@ -62077,7 +62325,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62077
62325
|
request2[bodyBufferKey] = buffered;
|
|
62078
62326
|
return Promise.resolve(buffered);
|
|
62079
62327
|
}
|
|
62080
|
-
const promise3 = new Promise((
|
|
62328
|
+
const promise3 = new Promise((resolve23, reject) => {
|
|
62081
62329
|
const chunks = [];
|
|
62082
62330
|
let settled = false;
|
|
62083
62331
|
const finish = (callback) => {
|
|
@@ -62099,7 +62347,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62099
62347
|
reject(error61 ?? normalizeAbortError(request2, incoming));
|
|
62100
62348
|
else {
|
|
62101
62349
|
request2[bodyBufferKey] = recovered;
|
|
62102
|
-
|
|
62350
|
+
resolve23(recovered);
|
|
62103
62351
|
}
|
|
62104
62352
|
});
|
|
62105
62353
|
return true;
|
|
@@ -62111,7 +62359,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62111
62359
|
finish(() => {
|
|
62112
62360
|
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
|
|
62113
62361
|
request2[bodyBufferKey] = buffer;
|
|
62114
|
-
|
|
62362
|
+
resolve23(buffer);
|
|
62115
62363
|
});
|
|
62116
62364
|
};
|
|
62117
62365
|
const onError = (error61) => {
|
|
@@ -62385,7 +62633,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
62385
62633
|
});
|
|
62386
62634
|
if (!chunk) {
|
|
62387
62635
|
if (i === 1) {
|
|
62388
|
-
await new Promise((
|
|
62636
|
+
await new Promise((resolve23) => setTimeout(resolve23));
|
|
62389
62637
|
maxReadCount = 3;
|
|
62390
62638
|
continue;
|
|
62391
62639
|
}
|
|
@@ -62686,12 +62934,12 @@ var init_dist2 = __esm(() => {
|
|
|
62686
62934
|
get headers() {
|
|
62687
62935
|
return this[headersKey] ||= newHeadersFromIncoming(this[incomingKey]);
|
|
62688
62936
|
},
|
|
62689
|
-
[abortRequest](
|
|
62937
|
+
[abortRequest](reason2) {
|
|
62690
62938
|
if (this[abortReasonKey] === undefined)
|
|
62691
|
-
this[abortReasonKey] =
|
|
62939
|
+
this[abortReasonKey] = reason2;
|
|
62692
62940
|
const abortController = this[abortControllerKey];
|
|
62693
62941
|
if (abortController && !abortController.signal.aborted)
|
|
62694
|
-
abortController.abort(
|
|
62942
|
+
abortController.abort(reason2);
|
|
62695
62943
|
},
|
|
62696
62944
|
[getAbortController]() {
|
|
62697
62945
|
this[abortControllerKey] ||= new AbortController;
|
|
@@ -63015,8 +63263,8 @@ var init_dist2 = __esm(() => {
|
|
|
63015
63263
|
ws.on("message", bufferMessage);
|
|
63016
63264
|
const ctx = {
|
|
63017
63265
|
binaryType: "arraybuffer",
|
|
63018
|
-
close(code2,
|
|
63019
|
-
ws.close(code2,
|
|
63266
|
+
close(code2, reason2) {
|
|
63267
|
+
ws.close(code2, reason2);
|
|
63020
63268
|
},
|
|
63021
63269
|
protocol: ws.protocol,
|
|
63022
63270
|
raw: ws,
|
|
@@ -63048,11 +63296,11 @@ var init_dist2 = __esm(() => {
|
|
|
63048
63296
|
ws.on("message", (data, isBinary) => {
|
|
63049
63297
|
handleMessage(data, isBinary);
|
|
63050
63298
|
});
|
|
63051
|
-
ws.on("close", (code2,
|
|
63299
|
+
ws.on("close", (code2, reason2) => {
|
|
63052
63300
|
try {
|
|
63053
63301
|
events2?.onClose?.(new CloseEvent("close", {
|
|
63054
63302
|
code: code2,
|
|
63055
|
-
reason:
|
|
63303
|
+
reason: reason2.toString()
|
|
63056
63304
|
}), ctx);
|
|
63057
63305
|
} catch (e2) {
|
|
63058
63306
|
(options?.onError ?? console.error)(e2);
|
|
@@ -63615,9 +63863,9 @@ data:
|
|
|
63615
63863
|
const initRequest = messages.find((m) => isInitializeRequest(m));
|
|
63616
63864
|
const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
|
63617
63865
|
if (this._enableJsonResponse) {
|
|
63618
|
-
return new Promise((
|
|
63866
|
+
return new Promise((resolve23) => {
|
|
63619
63867
|
this._streamMapping.set(streamId, {
|
|
63620
|
-
resolveJson:
|
|
63868
|
+
resolveJson: resolve23,
|
|
63621
63869
|
cleanup: () => {
|
|
63622
63870
|
this._streamMapping.delete(streamId);
|
|
63623
63871
|
}
|
|
@@ -63986,19 +64234,19 @@ async function connectMcpForNode() {
|
|
|
63986
64234
|
return { server: server2, transport };
|
|
63987
64235
|
}
|
|
63988
64236
|
function readBody(req) {
|
|
63989
|
-
return new Promise((
|
|
64237
|
+
return new Promise((resolve23, reject) => {
|
|
63990
64238
|
const chunks = [];
|
|
63991
64239
|
req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
63992
64240
|
req.on("end", () => {
|
|
63993
64241
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
63994
64242
|
if (!raw.trim()) {
|
|
63995
|
-
|
|
64243
|
+
resolve23(undefined);
|
|
63996
64244
|
return;
|
|
63997
64245
|
}
|
|
63998
64246
|
try {
|
|
63999
|
-
|
|
64247
|
+
resolve23(JSON.parse(raw));
|
|
64000
64248
|
} catch {
|
|
64001
|
-
|
|
64249
|
+
resolve23(undefined);
|
|
64002
64250
|
}
|
|
64003
64251
|
});
|
|
64004
64252
|
req.on("error", reject);
|
|
@@ -64040,9 +64288,9 @@ async function startSkillsMcpHttpServer(options = {}) {
|
|
|
64040
64288
|
}
|
|
64041
64289
|
}
|
|
64042
64290
|
});
|
|
64043
|
-
await new Promise((
|
|
64291
|
+
await new Promise((resolve23, reject) => {
|
|
64044
64292
|
httpServer.once("error", reject);
|
|
64045
|
-
httpServer.listen(port, hostname4, () =>
|
|
64293
|
+
httpServer.listen(port, hostname4, () => resolve23());
|
|
64046
64294
|
});
|
|
64047
64295
|
const address = httpServer.address();
|
|
64048
64296
|
const listenPort = typeof address === "object" && address ? address.port : port;
|