@hasna/skills 0.10.80 → 0.10.82
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 +260 -0
- package/bin/index.js +3399 -1772
- package/bin/mcp.js +816 -493
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/cli/commands/metadata.d.ts +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2077 -918
- package/dist/lib/agent-discovery-directories.d.ts +2 -1
- package/dist/lib/agent-discovery.d.ts +11 -0
- package/dist/lib/agent-integration.d.ts +119 -1
- package/dist/lib/codex-native-skill-catalog.d.ts +38 -0
- package/dist/lib/codex-plugin-capability-paths.d.ts +8 -0
- package/dist/lib/codex-plugin-reconcile.d.ts +74 -0
- package/dist/lib/codex-plugin-skill-controls.d.ts +68 -1
- package/dist/lib/private-publication-customer.d.ts +4 -1
- package/dist/lib/remote-auth.d.ts +3 -1
- package/dist/lib/remote-client.d.ts +10 -0
- package/dist/lib/remote-private-publications.d.ts +35 -0
- package/dist/lib/skill-metadata-update.d.ts +46 -0
- package/dist/lib/skill-validation.d.ts +3 -1
- package/dist/runtime-prerequisites.js +2 -2
- package/dist/sdk/index.d.ts +2 -1
- package/dist/sdk/index.js +2261 -1101
- package/package.json +1 -1
package/bin/mcp.js
CHANGED
|
@@ -23,7 +23,7 @@ var package_default;
|
|
|
23
23
|
var init_package = __esm(() => {
|
|
24
24
|
package_default = {
|
|
25
25
|
name: "@hasna/skills",
|
|
26
|
-
version: "0.10.
|
|
26
|
+
version: "0.10.82",
|
|
27
27
|
description: "Skills library for AI coding agents",
|
|
28
28
|
type: "module",
|
|
29
29
|
bin: {
|
|
@@ -20974,13 +20974,13 @@ function parseSkillFrontmatter(content) {
|
|
|
20974
20974
|
}
|
|
20975
20975
|
return Object.keys(result).length > 0 ? result : null;
|
|
20976
20976
|
}
|
|
20977
|
-
function validateSkillDirectory(name, skillPath, registryMeta) {
|
|
20977
|
+
function validateSkillDirectory(name, skillPath, registryMeta, options = {}) {
|
|
20978
20978
|
const bareName = name;
|
|
20979
20979
|
const issues = [];
|
|
20980
20980
|
const warnings = [];
|
|
20981
20981
|
let packageDeclaresHosted = false;
|
|
20982
20982
|
let packageSkillSource;
|
|
20983
|
-
let resolvedKind = "executable";
|
|
20983
|
+
let resolvedKind = options.kind ?? "executable";
|
|
20984
20984
|
const metadata = {
|
|
20985
20985
|
binCommands: [],
|
|
20986
20986
|
docFiles: []
|
|
@@ -21042,7 +21042,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
|
|
|
21042
21042
|
}
|
|
21043
21043
|
if (frontmatter.kind !== undefined) {
|
|
21044
21044
|
if (VALID_SKILL_KINDS.includes(frontmatter.kind)) {
|
|
21045
|
-
|
|
21045
|
+
if (options.kind === undefined)
|
|
21046
|
+
resolvedKind = frontmatter.kind;
|
|
21046
21047
|
} else {
|
|
21047
21048
|
add(issues, "skill.kind_invalid", `SKILL.md kind '${frontmatter.kind}' is not one of: ${VALID_SKILL_KINDS.join(", ")}`);
|
|
21048
21049
|
}
|
|
@@ -23030,7 +23031,7 @@ function hashClaudePluginCacheOrphanMarker(path, budget2, changes) {
|
|
|
23030
23031
|
if (!before)
|
|
23031
23032
|
return null;
|
|
23032
23033
|
const uid = process.getuid?.();
|
|
23033
|
-
if (!before.isFile() || uid === undefined || before.uid !== uid || before.size > 32)
|
|
23034
|
+
if (!before.isFile() || uid === undefined || before.uid !== uid || before.size > 32 || (before.mode & 73) !== 0)
|
|
23034
23035
|
throw new Error("Invalid Claude orphan marker file or owner");
|
|
23035
23036
|
const fd = openSync7(path, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
|
|
23036
23037
|
try {
|
|
@@ -30443,7 +30444,7 @@ function safe2(path) {
|
|
|
30443
30444
|
function same2(before, after) {
|
|
30444
30445
|
return Boolean(after && after.isDirectory() && before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs);
|
|
30445
30446
|
}
|
|
30446
|
-
function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
|
|
30447
|
+
function capture(path, budget2, excludedRoots, omittedRoots = [], rows, claudeMarkers) {
|
|
30447
30448
|
safe2(path);
|
|
30448
30449
|
if (omittedRoots.some((root2) => path === root2 || path.startsWith(root2 + "/")))
|
|
30449
30450
|
return { path, sha256: null };
|
|
@@ -30471,6 +30472,11 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
|
|
|
30471
30472
|
need3(child2.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
|
|
30472
30473
|
const stat = lstatSync8(child2);
|
|
30473
30474
|
need3(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
|
|
30475
|
+
if (claudeMarkers && isClaudePluginCacheOrphanMarker(child2)) {
|
|
30476
|
+
need3(hashClaudePluginCacheOrphanMarker(child2) !== null, "Claude orphan marker changed while reading directory");
|
|
30477
|
+
if (claudeMarkers === "omit")
|
|
30478
|
+
continue;
|
|
30479
|
+
}
|
|
30474
30480
|
const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
|
|
30475
30481
|
`;
|
|
30476
30482
|
budget2.bytes += Buffer.byteLength(row);
|
|
@@ -30527,25 +30533,33 @@ function verifyDiscoveryDirectoryProjection(directories, omittedRoots, tolerance
|
|
|
30527
30533
|
witnessChanged(new NativeDiscoveryWitnessChange("membership", directories[i].path, "Native discovery directory membership changed outside retired Codex roots"), tolerance, tolerance?.acceptsMembership(directories[i].path) === true);
|
|
30528
30534
|
}
|
|
30529
30535
|
}
|
|
30530
|
-
function
|
|
30536
|
+
function captureOrdinaryDirectories(paths, excludedRoots, claudeMarkers) {
|
|
30531
30537
|
need3(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
|
|
30532
30538
|
const budget2 = { entries: 0, bytes: 0 };
|
|
30533
30539
|
for (const root of excludedRoots)
|
|
30534
30540
|
safe2(root);
|
|
30535
|
-
return paths.map((path) => capture(path, budget2, excludedRoots));
|
|
30541
|
+
return paths.map((path) => capture(path, budget2, excludedRoots, [], undefined, claudeMarkers));
|
|
30542
|
+
}
|
|
30543
|
+
function captureDiscoveryDirectories(paths, excludedRoots = []) {
|
|
30544
|
+
return captureOrdinaryDirectories(paths, excludedRoots, "omit");
|
|
30536
30545
|
}
|
|
30537
30546
|
function verifyDiscoveryDirectories(directories, excludedRoots = [], tolerance) {
|
|
30538
30547
|
need3(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
|
|
30539
30548
|
for (const directory of directories)
|
|
30540
30549
|
need3(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
|
|
30541
30550
|
const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
|
|
30551
|
+
let legacy;
|
|
30542
30552
|
for (let i = 0;i < directories.length; i++)
|
|
30543
30553
|
if (current[i].sha256 !== directories[i].sha256) {
|
|
30554
|
+
legacy ??= captureOrdinaryDirectories(directories.map((directory) => directory.path), excludedRoots, "retain");
|
|
30555
|
+
if (legacy[i].sha256 === directories[i].sha256)
|
|
30556
|
+
continue;
|
|
30544
30557
|
witnessChanged(new NativeDiscoveryWitnessChange("membership", directories[i].path, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`), tolerance, tolerance?.acceptsMembership(directories[i].path) === true);
|
|
30545
30558
|
}
|
|
30546
30559
|
}
|
|
30547
30560
|
var init_agent_discovery_directories = __esm(() => {
|
|
30548
30561
|
init_agent_policy_limits();
|
|
30562
|
+
init_claude_plugin_cache_marker();
|
|
30549
30563
|
init_native_discovery_witness_change();
|
|
30550
30564
|
});
|
|
30551
30565
|
|
|
@@ -32310,7 +32324,7 @@ function codexPluginRootCapabilityEntry(name) {
|
|
|
32310
32324
|
function isCodexSkillDocumentName(name) {
|
|
32311
32325
|
return foldCodexPluginEntryName(name) === "skill.md";
|
|
32312
32326
|
}
|
|
32313
|
-
var CODEX_PLUGIN_MANIFEST_LOCATIONS, CODEX_PLUGIN_MANIFEST_DIRECTORIES, CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES;
|
|
32327
|
+
var CODEX_PLUGIN_MANIFEST_LOCATIONS, CODEX_PLUGIN_MANIFEST_DIRECTORIES, CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES, CODEX_PLUGIN_MANIFEST_KNOWN_KEYS, CODEX_PLUGIN_DEFAULT_SKILLS_PATHS;
|
|
32314
32328
|
var init_codex_plugin_capability_paths = __esm(() => {
|
|
32315
32329
|
CODEX_PLUGIN_MANIFEST_LOCATIONS = Object.freeze([
|
|
32316
32330
|
"plugin.json",
|
|
@@ -32331,6 +32345,8 @@ var init_codex_plugin_capability_paths = __esm(() => {
|
|
|
32331
32345
|
"commands",
|
|
32332
32346
|
"agents"
|
|
32333
32347
|
]);
|
|
32348
|
+
CODEX_PLUGIN_MANIFEST_KNOWN_KEYS = Object.freeze(["name", "version", "description", "author", "homepage", "repository", "license", "keywords", "interface", "skills", "apps"]);
|
|
32349
|
+
CODEX_PLUGIN_DEFAULT_SKILLS_PATHS = Object.freeze(["./skills", "./skills/"]);
|
|
32334
32350
|
});
|
|
32335
32351
|
|
|
32336
32352
|
// src/lib/codex-hook-mcp-dependencies.ts
|
|
@@ -33665,11 +33681,14 @@ var init_codex_hook_rpc = __esm(() => {
|
|
|
33665
33681
|
});
|
|
33666
33682
|
|
|
33667
33683
|
// src/lib/codex-native-skill-catalog.ts
|
|
33668
|
-
import { realpathSync as realpathSync4 } from "fs";
|
|
33669
|
-
import { isAbsolute as isAbsolute14, normalize as normalize3 } from "path";
|
|
33684
|
+
import { lstatSync as lstatSync14, readdirSync as readdirSync5, readFileSync as readFileSync12, realpathSync as realpathSync4 } from "fs";
|
|
33685
|
+
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute14, join as join19, normalize as normalize3 } from "path";
|
|
33686
|
+
function codexPluginIsRemote(plugin) {
|
|
33687
|
+
return plugin !== undefined && (plugin.sourceType === "remote" || plugin.remotePluginId !== undefined);
|
|
33688
|
+
}
|
|
33670
33689
|
function codexPluginSourceIsConfigControlled(plugin) {
|
|
33671
33690
|
const remoteRealms = ["openai-curated-remote", "created-by-me-remote", "workspace-directory", "workspace-shared-with-me", "workspace-shared-with-me-private", "workspace-shared-with-me-unlisted"];
|
|
33672
|
-
return Boolean(plugin.sourceType && ["local", "git", "npm"].includes(plugin.sourceType) && plugin.sourceSha256 && /^[a-f0-9]{64}$/.test(plugin.sourceSha256) && !plugin
|
|
33691
|
+
return Boolean(plugin.sourceType && ["local", "git", "npm"].includes(plugin.sourceType) && plugin.sourceSha256 && /^[a-f0-9]{64}$/.test(plugin.sourceSha256) && !codexPluginIsRemote(plugin) && !remoteRealms.includes(plugin.id.slice(plugin.id.lastIndexOf("@") + 1)));
|
|
33673
33692
|
}
|
|
33674
33693
|
function refuse() {
|
|
33675
33694
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_INVALID");
|
|
@@ -33759,16 +33778,16 @@ var init_codex_native_skill_catalog = __esm(() => {
|
|
|
33759
33778
|
});
|
|
33760
33779
|
|
|
33761
33780
|
// src/lib/codex-plugin-skill-controls.ts
|
|
33762
|
-
import { basename as
|
|
33763
|
-
import { lstatSync as
|
|
33781
|
+
import { basename as basename9, dirname as dirname16, join as join20, relative as relative5, resolve as resolve14, sep as sep8 } from "path";
|
|
33782
|
+
import { lstatSync as lstatSync15, readdirSync as readdirSync6, readFileSync as readFileSync13, readlinkSync as readlinkSync3, realpathSync as realpathSync5 } from "fs";
|
|
33764
33783
|
function refuse2() {
|
|
33765
33784
|
throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
|
|
33766
33785
|
}
|
|
33767
33786
|
function codexRemoteInstallReceipt(parent, read) {
|
|
33768
33787
|
try {
|
|
33769
|
-
if (!
|
|
33788
|
+
if (!lstatSync15(parent).isDirectory() || realpathSync5(parent) !== parent)
|
|
33770
33789
|
return null;
|
|
33771
|
-
const path =
|
|
33790
|
+
const path = join20(parent, ".codex-remote-plugin-install.json"), stat2 = lstatSync15(path, { throwIfNoEntry: false });
|
|
33772
33791
|
if (!stat2?.isFile() || stat2.isSymbolicLink() || stat2.size > 16384)
|
|
33773
33792
|
return null;
|
|
33774
33793
|
const text2 = read(path);
|
|
@@ -33830,7 +33849,7 @@ function mcpControls(path, read) {
|
|
|
33830
33849
|
function isBundledCleanupHooks(root, namespace, value) {
|
|
33831
33850
|
const object5 = (v) => Boolean(v && typeof v === "object" && !Array.isArray(v));
|
|
33832
33851
|
const exactKeys = (v, keys) => Object.keys(v).length === keys.length && keys.every((key2) => Object.hasOwn(v, key2));
|
|
33833
|
-
if (
|
|
33852
|
+
if (basename9(dirname16(root)) !== namespace || basename9(dirname16(dirname16(root))) !== "openai-bundled")
|
|
33834
33853
|
return false;
|
|
33835
33854
|
const server = namespace === "unified-computer-use" ? "cua_repl" : ["browser", "chrome", "chrome-dev", "chrome-internal", "computer-use"].includes(namespace) ? "node_repl" : undefined;
|
|
33836
33855
|
if (!server || !object5(value) || !exactKeys(value, ["hooks"]) || !object5(value.hooks))
|
|
@@ -33854,8 +33873,8 @@ function readCodexPluginRootControls(root, read) {
|
|
|
33854
33873
|
return rootControls(root, read);
|
|
33855
33874
|
}
|
|
33856
33875
|
function rootControls(root, read) {
|
|
33857
|
-
const manifestPath =
|
|
33858
|
-
if (!
|
|
33876
|
+
const manifestPath = join20(root, ".codex-plugin/plugin.json"), manifestFile = lstatSync15(manifestPath, { throwIfNoEntry: false });
|
|
33877
|
+
if (!lstatSync15(join20(root, ".codex-plugin"), { throwIfNoEntry: false })?.isDirectory() || !manifestFile?.isFile() || manifestFile.size > 1024 * 1024)
|
|
33859
33878
|
refuse2();
|
|
33860
33879
|
let manifest, manifestSha256;
|
|
33861
33880
|
try {
|
|
@@ -33867,12 +33886,12 @@ function rootControls(root, read) {
|
|
|
33867
33886
|
}
|
|
33868
33887
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
|
|
33869
33888
|
refuse2();
|
|
33870
|
-
const cacheVersion =
|
|
33889
|
+
const cacheVersion = basename9(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
33871
33890
|
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
33872
33891
|
refuse2();
|
|
33873
|
-
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" ||
|
|
33892
|
+
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" || lstatSync15(join20(root, "hooks"), { throwIfNoEntry: false }))
|
|
33874
33893
|
refuse2();
|
|
33875
|
-
const mcp =
|
|
33894
|
+
const mcp = join20(root, ".mcp.json"), mcpPresent = lstatSync15(mcp, { throwIfNoEntry: false });
|
|
33876
33895
|
if (manifest.hooks !== undefined && (manifest.mcpServers !== undefined || mcpPresent))
|
|
33877
33896
|
refuse2();
|
|
33878
33897
|
if (mcpPresent && (!mcpPresent.isFile() || mcpPresent.isSymbolicLink() || mcpPresent.size > 1024 * 1024 || realpathSync5(mcp) !== mcp))
|
|
@@ -33880,7 +33899,7 @@ function rootControls(root, read) {
|
|
|
33880
33899
|
if (Boolean(mcpPresent) !== (manifest.mcpServers !== undefined))
|
|
33881
33900
|
refuse2();
|
|
33882
33901
|
const mcpSha256 = mcpPresent ? mcpControls(mcp, read) : undefined;
|
|
33883
|
-
const app =
|
|
33902
|
+
const app = join20(root, ".app.json"), present = lstatSync15(app, { throwIfNoEntry: false });
|
|
33884
33903
|
if (present && (!present.isFile() || present.isSymbolicLink() || present.size > 1024 * 1024))
|
|
33885
33904
|
refuse2();
|
|
33886
33905
|
if (manifest.apps !== undefined && !present)
|
|
@@ -33912,12 +33931,12 @@ function documentIdentity(document2, cache, read) {
|
|
|
33912
33931
|
}
|
|
33913
33932
|
if (!front || typeof front !== "object" || !identifier2(front.name) || typeof front.description !== "string" || !front.description.trim())
|
|
33914
33933
|
refuse2();
|
|
33915
|
-
for (let root =
|
|
33916
|
-
const path =
|
|
33917
|
-
if (!
|
|
33934
|
+
for (let root = dirname16(document2), depth = 0;root.startsWith(cache + sep8) && depth < 12; root = dirname16(root), depth++) {
|
|
33935
|
+
const path = join20(root, ".codex-plugin", "plugin.json");
|
|
33936
|
+
if (!lstatSync15(path, { throwIfNoEntry: false }))
|
|
33918
33937
|
continue;
|
|
33919
|
-
const manifestFile =
|
|
33920
|
-
if (!
|
|
33938
|
+
const manifestFile = lstatSync15(path);
|
|
33939
|
+
if (!lstatSync15(join20(root, ".codex-plugin")).isDirectory() || !manifestFile.isFile() || manifestFile.size > 1024 * 1024)
|
|
33921
33940
|
refuse2();
|
|
33922
33941
|
let manifest;
|
|
33923
33942
|
try {
|
|
@@ -33930,9 +33949,9 @@ function documentIdentity(document2, cache, read) {
|
|
|
33930
33949
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
|
|
33931
33950
|
refuse2();
|
|
33932
33951
|
const declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
33933
|
-
if (declaredVersion === null || (declaredVersion ? declaredVersion !==
|
|
33952
|
+
if (declaredVersion === null || (declaredVersion ? declaredVersion !== basename9(root) : basename9(root) !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
33934
33953
|
refuse2();
|
|
33935
|
-
return { name: `${manifest.name}:${front.name}`, namespace: manifest.name, pluginParent:
|
|
33954
|
+
return { name: `${manifest.name}:${front.name}`, namespace: manifest.name, pluginParent: dirname16(root), root };
|
|
33936
33955
|
}
|
|
33937
33956
|
refuse2();
|
|
33938
33957
|
}
|
|
@@ -33948,7 +33967,7 @@ function classifyCodexPluginCacheDocument(document2, cache, read) {
|
|
|
33948
33967
|
return null;
|
|
33949
33968
|
try {
|
|
33950
33969
|
const located = documentIdentity(document2, cache, read), parsed = identity3(document2, cache, read);
|
|
33951
|
-
if (!
|
|
33970
|
+
if (!lstatSync15(document2).isFile() || realpathSync5(document2) !== document2 || realpathSync5(located.root) !== located.root || realpathSync5(located.pluginParent) !== located.pluginParent || realpathSync5(join20(located.root, ".codex-plugin/plugin.json")) !== join20(located.root, ".codex-plugin/plugin.json"))
|
|
33952
33971
|
return null;
|
|
33953
33972
|
const parts = relative5(cache, parsed.pluginParent).split(sep8);
|
|
33954
33973
|
if (parts.length !== 2 || parts.some((part) => !identifier2(part)) || parts[1] !== parsed.namespace)
|
|
@@ -33963,11 +33982,11 @@ function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
|
33963
33982
|
const parts = relative5(cache, parent).split(sep8), enrolled = controls.filter((control) => control.pluginParent === parent);
|
|
33964
33983
|
if (resolve14(parent) !== parent || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !enrolled.length || !Array.isArray(rules))
|
|
33965
33984
|
return false;
|
|
33966
|
-
for (let cursor = parent;; cursor =
|
|
33967
|
-
const stat2 =
|
|
33985
|
+
for (let cursor = parent;; cursor = dirname16(cursor)) {
|
|
33986
|
+
const stat2 = lstatSync15(cursor, { throwIfNoEntry: false });
|
|
33968
33987
|
if (stat2 && (!stat2.isDirectory() || stat2.isSymbolicLink()))
|
|
33969
33988
|
return false;
|
|
33970
|
-
if (
|
|
33989
|
+
if (dirname16(cursor) === cursor)
|
|
33971
33990
|
break;
|
|
33972
33991
|
}
|
|
33973
33992
|
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 + sep8))) && rule.enabled !== false));
|
|
@@ -33976,36 +33995,36 @@ function reviewedDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
|
33976
33995
|
}
|
|
33977
33996
|
}
|
|
33978
33997
|
function absentDisabledCodexPluginParent(cache, parent, controls, rules) {
|
|
33979
|
-
return reviewedDisabledCodexPluginParent(cache, parent, controls, rules) && !
|
|
33998
|
+
return reviewedDisabledCodexPluginParent(cache, parent, controls, rules) && !lstatSync15(parent, { throwIfNoEntry: false });
|
|
33980
33999
|
}
|
|
33981
34000
|
function reviewedRetiredCodexRoot(cache, root, controls, rules, read, allowAbsent = false) {
|
|
33982
34001
|
try {
|
|
33983
|
-
const parent =
|
|
33984
|
-
if (resolve14(root) !== root || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !
|
|
34002
|
+
const parent = dirname16(root), parts = relative5(cache, parent).split(sep8), enrolled = controls.filter((control) => control.pluginParent === parent);
|
|
34003
|
+
if (resolve14(root) !== root || parts.length !== 2 || parts.some((part) => !identifier2(part)) || !basename9(root) || basename9(root) === "latest" || !enrolled.length || !Array.isArray(rules))
|
|
33985
34004
|
return false;
|
|
33986
|
-
for (let cursor = root;; cursor =
|
|
33987
|
-
const stat2 =
|
|
34005
|
+
for (let cursor = root;; cursor = dirname16(cursor)) {
|
|
34006
|
+
const stat2 = lstatSync15(cursor, { throwIfNoEntry: false });
|
|
33988
34007
|
if (stat2 && (!stat2.isDirectory() || stat2.isSymbolicLink()))
|
|
33989
34008
|
return false;
|
|
33990
|
-
if (
|
|
34009
|
+
if (dirname16(cursor) === cursor)
|
|
33991
34010
|
break;
|
|
33992
34011
|
}
|
|
33993
34012
|
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 + sep8))) && rule.enabled !== false)))
|
|
33994
34013
|
return false;
|
|
33995
|
-
if (!
|
|
33996
|
-
return allowAbsent && (
|
|
34014
|
+
if (!lstatSync15(root, { throwIfNoEntry: false }))
|
|
34015
|
+
return allowAbsent && (lstatSync15(parent, { throwIfNoEntry: false }) ? enrolled.every((control) => remoteInstallationMatches(parent, control.remotePluginId, read)) : absentDisabledCodexPluginParent(cache, parent, controls, rules));
|
|
33997
34016
|
if (!enrolled.every((control) => remoteInstallationMatches(parent, control.remotePluginId, read)))
|
|
33998
34017
|
return false;
|
|
33999
34018
|
const parsed = rootControls(root, read);
|
|
34000
|
-
if (JSON.parse(read(
|
|
34019
|
+
if (JSON.parse(read(join20(root, ".codex-plugin/plugin.json"))).hooks !== undefined)
|
|
34001
34020
|
return false;
|
|
34002
34021
|
if (!enrolled.some((control) => control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && !parsed.appSha256 && !parsed.mcpSha256))
|
|
34003
34022
|
return false;
|
|
34004
34023
|
let entries = 0;
|
|
34005
|
-
const emptySkills = (directory, depth) => depth <= 64 &&
|
|
34024
|
+
const emptySkills = (directory, depth) => depth <= 64 && readdirSync6(directory).every((name) => {
|
|
34006
34025
|
if (++entries > 4096 || name === "SKILL.md")
|
|
34007
34026
|
return false;
|
|
34008
|
-
const path =
|
|
34027
|
+
const path = join20(directory, name), stat2 = lstatSync15(path);
|
|
34009
34028
|
return !stat2.isSymbolicLink() && (stat2.isFile() || stat2.isDirectory() && emptySkills(path, depth + 1));
|
|
34010
34029
|
});
|
|
34011
34030
|
return emptySkills(root, 0);
|
|
@@ -34021,26 +34040,26 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
34021
34040
|
for (const parent of new Set(controls.map((control) => control.pluginParent))) {
|
|
34022
34041
|
if (absentDisabledCodexPluginParent(cache, parent, controls, rules))
|
|
34023
34042
|
continue;
|
|
34024
|
-
if (!parent.startsWith(cache + sep8) || !
|
|
34043
|
+
if (!parent.startsWith(cache + sep8) || !lstatSync15(parent, { throwIfNoEntry: false })?.isDirectory() || realpathSync5(parent) !== parent)
|
|
34025
34044
|
return false;
|
|
34026
34045
|
for (const control of controls.filter((control2) => control2.pluginParent === parent)) {
|
|
34027
34046
|
if (control.remotePluginId !== undefined && !remoteInstallationMatches(parent, control.remotePluginId, read))
|
|
34028
34047
|
return false;
|
|
34029
34048
|
}
|
|
34030
|
-
const names =
|
|
34049
|
+
const names = readdirSync6(parent);
|
|
34031
34050
|
entries += names.length;
|
|
34032
34051
|
if (entries > 4096)
|
|
34033
34052
|
return false;
|
|
34034
34053
|
for (const name of names) {
|
|
34035
|
-
let root =
|
|
34054
|
+
let root = join20(parent, name), stat2 = lstatSync15(root);
|
|
34036
34055
|
if (stat2.isSymbolicLink()) {
|
|
34037
34056
|
const target = resolve14(parent, readlinkSync3(root));
|
|
34038
|
-
if (name !== "latest" ||
|
|
34057
|
+
if (name !== "latest" || dirname16(target) !== parent || !lstatSync15(target).isDirectory() || realpathSync5(target) !== target)
|
|
34039
34058
|
return false;
|
|
34040
34059
|
root = target;
|
|
34041
|
-
stat2 =
|
|
34060
|
+
stat2 = lstatSync15(root);
|
|
34042
34061
|
}
|
|
34043
|
-
if (!stat2.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) =>
|
|
34062
|
+
if (!stat2.isDirectory() || ![".codex-plugin/plugin.json", ".app.json", "hooks", ".mcp.json"].some((path) => lstatSync15(join20(root, path), { throwIfNoEntry: false })))
|
|
34044
34063
|
continue;
|
|
34045
34064
|
const parsed = rootControls(root, read);
|
|
34046
34065
|
if (!controls.some((control) => control.pluginParent === parent && control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && control.appSha256 === parsed.appSha256 && control.mcpSha256 === parsed.mcpSha256))
|
|
@@ -34055,9 +34074,9 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read, rules)
|
|
|
34055
34074
|
function sourceInputUnchanged(input2, cache, read) {
|
|
34056
34075
|
try {
|
|
34057
34076
|
const parts = relative5(cache, input2.pluginParent).split(sep8);
|
|
34058
|
-
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 })) || resolve14(input2.sourceRoot) !== input2.sourceRoot || !
|
|
34077
|
+
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 })) || resolve14(input2.sourceRoot) !== input2.sourceRoot || !lstatSync15(input2.sourceRoot).isDirectory() || realpathSync5(input2.sourceRoot) !== input2.sourceRoot || input2.sourceRoot === cache || input2.sourceRoot.startsWith(cache + sep8) || cache.startsWith(input2.sourceRoot + sep8))
|
|
34059
34078
|
return false;
|
|
34060
|
-
const path =
|
|
34079
|
+
const path = join20(input2.sourceRoot, ".codex-plugin/plugin.json"), stat2 = lstatSync15(path);
|
|
34061
34080
|
if (!stat2.isFile() || stat2.size > 1024 * 1024 || realpathSync5(path) !== path)
|
|
34062
34081
|
return false;
|
|
34063
34082
|
const text2 = read(path);
|
|
@@ -34080,11 +34099,12 @@ var identifier2 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v
|
|
|
34080
34099
|
var init_codex_plugin_skill_controls = __esm(() => {
|
|
34081
34100
|
init_claude_settings_witness();
|
|
34082
34101
|
init_codex_native_compatibility();
|
|
34102
|
+
init_codex_plugin_capability_paths();
|
|
34083
34103
|
init_codex_native_skill_catalog();
|
|
34084
34104
|
});
|
|
34085
34105
|
|
|
34086
34106
|
// src/lib/codex-vendor-refresh.ts
|
|
34087
|
-
var CODEX_VENDOR_MARKETPLACES, CODEX_REMOTE_VENDOR_MARKETPLACES, OTHER_PLUGIN_CONTROLS
|
|
34107
|
+
var CODEX_VENDOR_MARKETPLACES, CODEX_REMOTE_VENDOR_MARKETPLACES, OTHER_PLUGIN_CONTROLS;
|
|
34088
34108
|
var init_codex_vendor_refresh = __esm(() => {
|
|
34089
34109
|
init_claude_settings_witness();
|
|
34090
34110
|
init_codex_plugin_skill_controls();
|
|
@@ -34092,8 +34112,6 @@ var init_codex_vendor_refresh = __esm(() => {
|
|
|
34092
34112
|
CODEX_VENDOR_MARKETPLACES = Object.freeze(["openai-bundled", "openai-curated", "openai-curated-remote"]);
|
|
34093
34113
|
CODEX_REMOTE_VENDOR_MARKETPLACES = Object.freeze(["openai-curated-remote"]);
|
|
34094
34114
|
OTHER_PLUGIN_CONTROLS = Object.freeze(CODEX_PLUGIN_ROOT_CAPABILITY_ENTRIES.filter((entry) => entry !== ".codex-plugin" && entry !== ".app.json"));
|
|
34095
|
-
VENDOR_MANIFEST_KEYS = Object.freeze(["name", "version", "description", "author", "homepage", "repository", "license", "keywords", "interface", "skills", "apps"]);
|
|
34096
|
-
DEFAULT_SKILLS_PATHS = Object.freeze(["./skills", "./skills/"]);
|
|
34097
34115
|
});
|
|
34098
34116
|
|
|
34099
34117
|
// src/lib/claude-plugin-manifest-witness.ts
|
|
@@ -34537,19 +34555,19 @@ function capturePreparationProcess(child2, platform = process.platform, signalGr
|
|
|
34537
34555
|
}
|
|
34538
34556
|
|
|
34539
34557
|
// src/lib/dependency-preparation.ts
|
|
34540
|
-
import { constants as constants9, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as
|
|
34541
|
-
import { join as
|
|
34558
|
+
import { constants as constants9, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as lstatSync16, mkdirSync as mkdirSync5, openSync as openSync12, readFileSync as readFileSync14, readdirSync as readdirSync7, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3, ftruncateSync, writeSync as writeSync2 } from "fs";
|
|
34559
|
+
import { join as join21 } from "path";
|
|
34542
34560
|
function hasDependencyPreparationMarker(skillPath) {
|
|
34543
34561
|
try {
|
|
34544
|
-
|
|
34562
|
+
lstatSync16(join21(skillPath, DEPENDENCY_PREPARATION_MARKER));
|
|
34545
34563
|
return true;
|
|
34546
34564
|
} catch (error61) {
|
|
34547
34565
|
return error61.code !== "ENOENT";
|
|
34548
34566
|
}
|
|
34549
34567
|
}
|
|
34550
34568
|
function claimPreparation(skillPath) {
|
|
34551
|
-
const marker =
|
|
34552
|
-
const state =
|
|
34569
|
+
const marker = join21(skillPath, DEPENDENCY_PREPARATION_MARKER);
|
|
34570
|
+
const state = join21(marker, "state.json"), active = join21(marker, "active");
|
|
34553
34571
|
let created = false;
|
|
34554
34572
|
try {
|
|
34555
34573
|
mkdirSync5(marker, { mode: 448 });
|
|
@@ -34560,14 +34578,14 @@ function claimPreparation(skillPath) {
|
|
|
34560
34578
|
}
|
|
34561
34579
|
let fd;
|
|
34562
34580
|
try {
|
|
34563
|
-
if (!
|
|
34581
|
+
if (!lstatSync16(marker).isDirectory() || lstatSync16(marker).isSymbolicLink())
|
|
34564
34582
|
return;
|
|
34565
34583
|
if (!created) {
|
|
34566
|
-
if (
|
|
34584
|
+
if (readdirSync7(marker).some((name) => name !== "state.json"))
|
|
34567
34585
|
return;
|
|
34568
|
-
if (!
|
|
34586
|
+
if (!lstatSync16(state).isFile() || lstatSync16(state).isSymbolicLink() || lstatSync16(state).size > 1024)
|
|
34569
34587
|
return;
|
|
34570
|
-
const previous = JSON.parse(
|
|
34588
|
+
const previous = JSON.parse(readFileSync14(state, "utf8"));
|
|
34571
34589
|
if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
|
|
34572
34590
|
return;
|
|
34573
34591
|
}
|
|
@@ -34700,6 +34718,9 @@ async function prepareSkillDependencies(skillPath, env, timeoutMs = DEFAULT_PREP
|
|
|
34700
34718
|
var DEPENDENCY_PREPARATION_MARKER = ".skills-dependency-preparation", RECOVERY = "Skill dependency preparation is incomplete. Confirm no installer is running, successfully run bun install --no-save in the skill directory, then remove only .skills-dependency-preparation. See docs/skill-standard.md#recovering-interrupted-dependency-preparation.", DEFAULT_PREPARATION_TIMEOUT_MS = 60000;
|
|
34701
34719
|
var init_dependency_preparation = () => {};
|
|
34702
34720
|
|
|
34721
|
+
// src/lib/codex-native-config.ts
|
|
34722
|
+
var init_codex_native_config = () => {};
|
|
34723
|
+
|
|
34703
34724
|
// src/lib/codex-native-skill-policy.ts
|
|
34704
34725
|
var MAX_EXECUTABLE_BYTES, MAX_BRIDGE_DOCUMENT_BYTES, CODEX_NATIVE_POLICY_HELPER_MAX_OUTPUT_BYTES, executableDigestMemory;
|
|
34705
34726
|
var init_codex_native_skill_policy = __esm(() => {
|
|
@@ -34711,8 +34732,8 @@ var init_codex_native_skill_policy = __esm(() => {
|
|
|
34711
34732
|
|
|
34712
34733
|
// src/lib/codex-semantic-cache-witness.ts
|
|
34713
34734
|
import { createHash as createHash18 } from "crypto";
|
|
34714
|
-
import { constants as constants10, closeSync as closeSync13, fstatSync as fstatSync13, lstatSync as
|
|
34715
|
-
import { basename as
|
|
34735
|
+
import { constants as constants10, closeSync as closeSync13, fstatSync as fstatSync13, lstatSync as lstatSync17, openSync as openSync13, readSync as readSync7, readdirSync as readdirSync8, realpathSync as realpathSync6 } from "fs";
|
|
34736
|
+
import { basename as basename10, dirname as dirname17, isAbsolute as isAbsolute15, join as join22, relative as relative6, resolve as resolve15, sep as sep9 } from "path";
|
|
34716
34737
|
function codexLocalMarketplaceMapsPlugin(text2, marketplace, plugin) {
|
|
34717
34738
|
try {
|
|
34718
34739
|
hashNativeJsonControls(text2);
|
|
@@ -34734,7 +34755,7 @@ function codexLocalMarketplaceMapsPlugin(text2, marketplace, plugin) {
|
|
|
34734
34755
|
}
|
|
34735
34756
|
}
|
|
34736
34757
|
function defaultRead(path) {
|
|
34737
|
-
const before =
|
|
34758
|
+
const before = lstatSync17(path, { throwIfNoEntry: false, bigint: true });
|
|
34738
34759
|
if (before === undefined)
|
|
34739
34760
|
return refuse3();
|
|
34740
34761
|
if (!before.isFile() || before.isSymbolicLink() || before.size > BigInt(MAX_DOCUMENT_BYTES))
|
|
@@ -34825,7 +34846,7 @@ function assertWitnessShape(value) {
|
|
|
34825
34846
|
const row = candidate;
|
|
34826
34847
|
const remote = row.installation === "remote-receipt";
|
|
34827
34848
|
const local = row.installation === "local-marketplace";
|
|
34828
|
-
if (!exactKeys(row, ["role", "pluginId", "namespace", "pluginParent", "installation", "manifestSha256", "hooksSha256"], remote ? ["remotePluginId", "receiptSha256"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || row.role !== "reviewed-hook" || !identifier4(row.namespace) || typeof row.pluginId !== "string" || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(row.pluginId) || typeof row.pluginParent !== "string" || !validPluginParent(String(witness.cacheRoot), row.pluginParent, row.namespace, row.pluginId) || remote && (typeof row.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(row.remotePluginId) || !digest(row.receiptSha256)) || local && (typeof row.marketplaceSourcePath !== "string" || !isAbsolute15(row.marketplaceSourcePath) || resolve15(row.marketplaceSourcePath) !== row.marketplaceSourcePath ||
|
|
34849
|
+
if (!exactKeys(row, ["role", "pluginId", "namespace", "pluginParent", "installation", "manifestSha256", "hooksSha256"], remote ? ["remotePluginId", "receiptSha256"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || row.role !== "reviewed-hook" || !identifier4(row.namespace) || typeof row.pluginId !== "string" || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(row.pluginId) || typeof row.pluginParent !== "string" || !validPluginParent(String(witness.cacheRoot), row.pluginParent, row.namespace, row.pluginId) || remote && (typeof row.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(row.remotePluginId) || !digest(row.receiptSha256)) || local && (typeof row.marketplaceSourcePath !== "string" || !isAbsolute15(row.marketplaceSourcePath) || resolve15(row.marketplaceSourcePath) !== row.marketplaceSourcePath || basename10(row.marketplaceSourcePath) !== "marketplace.json" || !digest(row.marketplaceSha256)) || !remote && !local || !digest(row.manifestSha256) || !digest(row.hooksSha256) || hookParentPaths.has(row.pluginParent) || controlParents.has(row.pluginParent) || appOnlyParentPaths.has(row.pluginParent))
|
|
34829
34850
|
refuse3();
|
|
34830
34851
|
hookParentPaths.add(row.pluginParent);
|
|
34831
34852
|
}
|
|
@@ -34857,23 +34878,23 @@ function assertWitnessShape(value) {
|
|
|
34857
34878
|
function assertCanonicalDirectory(path) {
|
|
34858
34879
|
if (resolve15(path) !== path || realpathSync6(path) !== path)
|
|
34859
34880
|
refuse3();
|
|
34860
|
-
for (let cursor = path;; cursor =
|
|
34861
|
-
const stat2 =
|
|
34881
|
+
for (let cursor = path;; cursor = dirname17(cursor)) {
|
|
34882
|
+
const stat2 = lstatSync17(cursor, { throwIfNoEntry: false });
|
|
34862
34883
|
if (stat2 && (!stat2.isDirectory() || stat2.isSymbolicLink()))
|
|
34863
34884
|
refuse3();
|
|
34864
|
-
if (
|
|
34885
|
+
if (dirname17(cursor) === cursor)
|
|
34865
34886
|
break;
|
|
34866
34887
|
}
|
|
34867
34888
|
}
|
|
34868
34889
|
function walkSafeTree(path, state, depth = 0, root = path) {
|
|
34869
34890
|
if (depth > 64 || ++state.entries > 16384)
|
|
34870
34891
|
refuse3();
|
|
34871
|
-
const names =
|
|
34892
|
+
const names = readdirSync8(path).sort();
|
|
34872
34893
|
const files = [];
|
|
34873
34894
|
for (const name of names) {
|
|
34874
34895
|
if (!name || name === "." || name === ".." || name.includes(sep9) || ++state.entries > 16384)
|
|
34875
34896
|
refuse3();
|
|
34876
|
-
const child2 =
|
|
34897
|
+
const child2 = join22(path, name), stat2 = lstatSync17(child2, { bigint: true });
|
|
34877
34898
|
state.members.push(child2);
|
|
34878
34899
|
state.signature.push(`${relative6(root, child2)}\x00${stat2.mode}\x00${stat2.dev}\x00${stat2.ino}\x00${stat2.isDirectory() ? 0 : stat2.size}`);
|
|
34879
34900
|
state.timestamps.set(child2, `${stat2.mtimeNs}\x00${stat2.ctimeNs}`);
|
|
@@ -34890,7 +34911,7 @@ function walkSafeTree(path, state, depth = 0, root = path) {
|
|
|
34890
34911
|
}
|
|
34891
34912
|
function treeSnapshot(cacheRoot) {
|
|
34892
34913
|
const state = { entries: 0, members: [], signature: [], timestamps: new Map };
|
|
34893
|
-
const rootStat =
|
|
34914
|
+
const rootStat = lstatSync17(cacheRoot, { throwIfNoEntry: false, bigint: true });
|
|
34894
34915
|
if (rootStat === undefined)
|
|
34895
34916
|
return refuse3();
|
|
34896
34917
|
if (!rootStat.isDirectory() || rootStat.isSymbolicLink() || realpathSync6(cacheRoot) !== cacheRoot)
|
|
@@ -34910,7 +34931,7 @@ function assertSameTree(before, after, semanticPaths) {
|
|
|
34910
34931
|
function trackedBoundedRead(read) {
|
|
34911
34932
|
const observed = new Map;
|
|
34912
34933
|
const stableStat = (path, max) => {
|
|
34913
|
-
const stat2 =
|
|
34934
|
+
const stat2 = lstatSync17(path, { throwIfNoEntry: false, bigint: true });
|
|
34914
34935
|
if (stat2 === undefined)
|
|
34915
34936
|
return refuse3();
|
|
34916
34937
|
if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > BigInt(max) || realpathSync6(path) !== path)
|
|
@@ -34966,7 +34987,7 @@ function controlProjection(controls, read) {
|
|
|
34966
34987
|
...control.mcpSha256 === undefined ? {} : { mcpSha256: control.mcpSha256 }
|
|
34967
34988
|
};
|
|
34968
34989
|
if (row.remotePluginId !== undefined) {
|
|
34969
|
-
const receipt =
|
|
34990
|
+
const receipt = join22(row.pluginParent, ".codex-remote-plugin-install.json"), stat2 = lstatSync17(receipt, { throwIfNoEntry: false });
|
|
34970
34991
|
if (!stat2?.isFile() || stat2.isSymbolicLink() || stat2.size > 16384)
|
|
34971
34992
|
refuse3();
|
|
34972
34993
|
try {
|
|
@@ -34998,10 +35019,10 @@ function appOnlyParentProjection(cacheRoot, parents2, read) {
|
|
|
34998
35019
|
if (resolve15(parent.pluginParent) !== parent.pluginParent || parts.length !== 2 || parts.some((part) => !identifier4(part)) || parent.pluginId !== `${parent.namespace}@${parts[0]}` || parts[1] !== parent.namespace || seen.has(parent.pluginParent))
|
|
34999
35020
|
refuse3();
|
|
35000
35021
|
seen.add(parent.pluginParent);
|
|
35001
|
-
const parentStat =
|
|
35022
|
+
const parentStat = lstatSync17(parent.pluginParent, { throwIfNoEntry: false });
|
|
35002
35023
|
if (!parentStat?.isDirectory() || parentStat.isSymbolicLink() || realpathSync6(parent.pluginParent) !== parent.pluginParent)
|
|
35003
35024
|
refuse3();
|
|
35004
|
-
const receipt =
|
|
35025
|
+
const receipt = join22(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync17(receipt, { throwIfNoEntry: false });
|
|
35005
35026
|
if (!receiptStat?.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > 16384)
|
|
35006
35027
|
refuse3();
|
|
35007
35028
|
let receiptText = "";
|
|
@@ -35014,13 +35035,13 @@ function appOnlyParentProjection(cacheRoot, parents2, read) {
|
|
|
35014
35035
|
} catch {
|
|
35015
35036
|
refuse3();
|
|
35016
35037
|
}
|
|
35017
|
-
const versions2 =
|
|
35038
|
+
const versions2 = readdirSync8(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json");
|
|
35018
35039
|
if (!versions2.length || versions2.length > 4096)
|
|
35019
35040
|
refuse3();
|
|
35020
35041
|
const materializations = versions2.map((version2) => {
|
|
35021
35042
|
if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
|
|
35022
35043
|
refuse3();
|
|
35023
|
-
const root =
|
|
35044
|
+
const root = join22(parent.pluginParent, version2), stat2 = lstatSync17(root, { throwIfNoEntry: false });
|
|
35024
35045
|
if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync6(root) !== root)
|
|
35025
35046
|
refuse3();
|
|
35026
35047
|
const rootControls2 = readCodexPluginRootControls(root, read);
|
|
@@ -35060,7 +35081,7 @@ function assertJsonValue(value, depth = 0, budget2 = { members: 0 }) {
|
|
|
35060
35081
|
}
|
|
35061
35082
|
}
|
|
35062
35083
|
function reviewedHookControls(root, read) {
|
|
35063
|
-
const manifestPath =
|
|
35084
|
+
const manifestPath = join22(root, ".codex-plugin/plugin.json"), hooksPath = join22(root, "hooks/hooks.json");
|
|
35064
35085
|
let manifest, manifestSha256, hooks, hooksSha256;
|
|
35065
35086
|
try {
|
|
35066
35087
|
const manifestText = read(manifestPath);
|
|
@@ -35073,7 +35094,7 @@ function reviewedHookControls(root, read) {
|
|
|
35073
35094
|
} catch {
|
|
35074
35095
|
return refuse3();
|
|
35075
35096
|
}
|
|
35076
|
-
if (!plainObject(manifest) || !exactKeys(manifest, ["name", "version", "hooks"], ["description"]) || !identifier4(manifest.name) || typeof manifest.version !== "string" || manifest.version !==
|
|
35097
|
+
if (!plainObject(manifest) || !exactKeys(manifest, ["name", "version", "hooks"], ["description"]) || !identifier4(manifest.name) || typeof manifest.version !== "string" || manifest.version !== basename10(root) || manifest.hooks !== "./hooks/hooks.json" || manifest.description !== undefined && (typeof manifest.description !== "string" || !manifest.description.trim() || manifest.description.length > 1024))
|
|
35077
35098
|
refuse3();
|
|
35078
35099
|
const manifestRecord = manifest;
|
|
35079
35100
|
if (!plainObject(hooks) || !exactKeys(hooks, ["hooks"], ["description"]) || !plainObject(hooks.hooks) || hooks.description !== undefined && typeof hooks.description !== "string")
|
|
@@ -35104,16 +35125,16 @@ function reviewedHookParentProjection(cacheRoot, parents2, read) {
|
|
|
35104
35125
|
const seen = new Set, rows = [];
|
|
35105
35126
|
for (const parent of parents2) {
|
|
35106
35127
|
const remote = parent?.installation === "remote-receipt", local = parent?.installation === "local-marketplace";
|
|
35107
|
-
if (!parent || !exactKeys(parent, ["installation", "namespace", "pluginId", "pluginParent", "role"], remote ? ["remotePluginId"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || parent.role !== "reviewed-hook" || !identifier4(parent.namespace) || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(parent.pluginId) || typeof parent.pluginParent !== "string" || remote && (typeof parent.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(parent.remotePluginId)) || local && (typeof parent.marketplaceSourcePath !== "string" || !isAbsolute15(parent.marketplaceSourcePath) || resolve15(parent.marketplaceSourcePath) !== parent.marketplaceSourcePath ||
|
|
35128
|
+
if (!parent || !exactKeys(parent, ["installation", "namespace", "pluginId", "pluginParent", "role"], remote ? ["remotePluginId"] : local ? ["marketplaceSourcePath", "marketplaceSha256"] : []) || parent.role !== "reviewed-hook" || !identifier4(parent.namespace) || !/^[A-Za-z0-9_-]{1,64}@[A-Za-z0-9_-]{1,64}$/.test(parent.pluginId) || typeof parent.pluginParent !== "string" || remote && (typeof parent.remotePluginId !== "string" || !/^[A-Za-z0-9_~-]{1,1024}$/.test(parent.remotePluginId)) || local && (typeof parent.marketplaceSourcePath !== "string" || !isAbsolute15(parent.marketplaceSourcePath) || resolve15(parent.marketplaceSourcePath) !== parent.marketplaceSourcePath || basename10(parent.marketplaceSourcePath) !== "marketplace.json" || !digest(parent.marketplaceSha256)) || !remote && !local)
|
|
35108
35129
|
refuse3();
|
|
35109
35130
|
const parts = relative6(cacheRoot, parent.pluginParent).split(sep9);
|
|
35110
35131
|
if (!isAbsolute15(parent.pluginParent) || resolve15(parent.pluginParent) !== parent.pluginParent || parts.length !== 2 || parts.some((part) => !identifier4(part)) || parts[1] !== parent.namespace || parent.pluginId !== `${parent.namespace}@${parts[0]}` || seen.has(parent.pluginParent))
|
|
35111
35132
|
refuse3();
|
|
35112
35133
|
seen.add(parent.pluginParent);
|
|
35113
|
-
const parentStat =
|
|
35134
|
+
const parentStat = lstatSync17(parent.pluginParent, { throwIfNoEntry: false });
|
|
35114
35135
|
if (!parentStat?.isDirectory() || parentStat.isSymbolicLink() || realpathSync6(parent.pluginParent) !== parent.pluginParent)
|
|
35115
35136
|
refuse3();
|
|
35116
|
-
const receiptPath =
|
|
35137
|
+
const receiptPath = join22(parent.pluginParent, ".codex-remote-plugin-install.json"), receiptStat = lstatSync17(receiptPath, { throwIfNoEntry: false });
|
|
35117
35138
|
let receiptText;
|
|
35118
35139
|
if (remote) {
|
|
35119
35140
|
if (!receiptStat?.isFile() || receiptStat.isSymbolicLink() || receiptStat.size > MAX_RECEIPT_BYTES)
|
|
@@ -35140,10 +35161,10 @@ function reviewedHookParentProjection(cacheRoot, parents2, read) {
|
|
|
35140
35161
|
if (createHash18("sha256").update(marketplaceText).digest("hex") !== parent.marketplaceSha256 || !codexLocalMarketplaceMapsPlugin(marketplaceText, parts[0], parent.namespace))
|
|
35141
35162
|
refuse3();
|
|
35142
35163
|
}
|
|
35143
|
-
const materializations =
|
|
35164
|
+
const materializations = readdirSync8(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json").map((version2) => {
|
|
35144
35165
|
if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
|
|
35145
35166
|
refuse3();
|
|
35146
|
-
const root =
|
|
35167
|
+
const root = join22(parent.pluginParent, version2), stat2 = lstatSync17(root, { throwIfNoEntry: false });
|
|
35147
35168
|
if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync6(root) !== root)
|
|
35148
35169
|
refuse3();
|
|
35149
35170
|
const controls = reviewedHookControls(root, read);
|
|
@@ -35172,17 +35193,17 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
|
|
|
35172
35193
|
const rel = relative6(cacheRoot, file2), parts = rel.split(sep9);
|
|
35173
35194
|
if (parts.length < 3 || !identifier4(parts[0]) || !identifier4(parts[1]))
|
|
35174
35195
|
refuse3();
|
|
35175
|
-
actual.add(
|
|
35196
|
+
actual.add(join22(cacheRoot, parts[0], parts[1]));
|
|
35176
35197
|
}
|
|
35177
|
-
const actualMarkets =
|
|
35198
|
+
const actualMarkets = readdirSync8(cacheRoot);
|
|
35178
35199
|
if (actualMarkets.length !== expectedMarkets.size || actualMarkets.some((market) => !expectedMarkets.has(market)))
|
|
35179
35200
|
refuse3();
|
|
35180
35201
|
for (const market of actualMarkets) {
|
|
35181
|
-
const marketPath =
|
|
35202
|
+
const marketPath = join22(cacheRoot, market), marketStat = lstatSync17(marketPath);
|
|
35182
35203
|
if (!identifier4(market) || !marketStat.isDirectory() || marketStat.isSymbolicLink())
|
|
35183
35204
|
refuse3();
|
|
35184
|
-
for (const plugin of
|
|
35185
|
-
const parent =
|
|
35205
|
+
for (const plugin of readdirSync8(marketPath)) {
|
|
35206
|
+
const parent = join22(marketPath, plugin), stat2 = lstatSync17(parent);
|
|
35186
35207
|
if (!identifier4(plugin) || !stat2.isDirectory() || stat2.isSymbolicLink())
|
|
35187
35208
|
refuse3();
|
|
35188
35209
|
actual.add(parent);
|
|
@@ -35194,8 +35215,8 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
|
|
|
35194
35215
|
const parts = relative6(cacheRoot, member).split(sep9);
|
|
35195
35216
|
if (parts.length < 3)
|
|
35196
35217
|
continue;
|
|
35197
|
-
const parent =
|
|
35198
|
-
const root =
|
|
35218
|
+
const parent = join22(cacheRoot, parts[0], parts[1]);
|
|
35219
|
+
const root = join22(parent, parts[2]);
|
|
35199
35220
|
const base = parts[parts.length - 1], folded = foldCodexPluginEntryName(base);
|
|
35200
35221
|
if (parts.length === 3 && (codexPluginRootCapabilityEntry(base) !== null || isCodexSkillDocumentName(base)))
|
|
35201
35222
|
refuse3();
|
|
@@ -35208,11 +35229,11 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
|
|
|
35208
35229
|
refuse3();
|
|
35209
35230
|
if (parts.some((part) => CODEX_PLUGIN_MANIFEST_DIRECTORIES.includes(foldCodexPluginEntryName(part))) && (parts.length < 4 || parts[3] !== ".codex-plugin" || (parts.length === 4 ? base !== ".codex-plugin" : parts.length !== 5 || base !== "plugin.json")))
|
|
35210
35231
|
refuse3();
|
|
35211
|
-
if ([".app.json", ".mcp.json"].includes(folded) && (parts.length !== 4 ||
|
|
35232
|
+
if ([".app.json", ".mcp.json"].includes(folded) && (parts.length !== 4 || dirname17(member) !== root))
|
|
35212
35233
|
refuse3();
|
|
35213
35234
|
if ([".app.json", ".mcp.json"].includes(folded) && hookParents.some((reviewed) => reviewed.pluginParent === parent))
|
|
35214
35235
|
refuse3();
|
|
35215
|
-
if ((rootEntry === "hooks" || folded === "hooks.json") && (![4, 5].includes(parts.length) || parts[3] !== "hooks" || (parts.length === 4 ? base !== "hooks" : base !== "hooks.json") || !hookParents.some((reviewed) => reviewed.pluginParent ===
|
|
35236
|
+
if ((rootEntry === "hooks" || folded === "hooks.json") && (![4, 5].includes(parts.length) || parts[3] !== "hooks" || (parts.length === 4 ? base !== "hooks" : base !== "hooks.json") || !hookParents.some((reviewed) => reviewed.pluginParent === join22(cacheRoot, parts[0], parts[1]))))
|
|
35216
35237
|
refuse3();
|
|
35217
35238
|
}
|
|
35218
35239
|
}
|
|
@@ -35242,14 +35263,14 @@ function assertSkillMaterializations(cacheRoot, controls, files, read) {
|
|
|
35242
35263
|
const expectedNames = new Set(rows.map((row) => row.name));
|
|
35243
35264
|
if (expectedNames.size !== rows.length)
|
|
35244
35265
|
refuse3();
|
|
35245
|
-
const entries =
|
|
35266
|
+
const entries = readdirSync8(parent);
|
|
35246
35267
|
let roots = 0;
|
|
35247
35268
|
for (const entry of entries) {
|
|
35248
35269
|
if (entry === ".codex-remote-plugin-install.json")
|
|
35249
35270
|
continue;
|
|
35250
35271
|
if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(entry))
|
|
35251
35272
|
refuse3();
|
|
35252
|
-
const root =
|
|
35273
|
+
const root = join22(parent, entry), stat2 = lstatSync17(root, { throwIfNoEntry: false });
|
|
35253
35274
|
if (!stat2?.isDirectory() || stat2.isSymbolicLink() || realpathSync6(root) !== root)
|
|
35254
35275
|
refuse3();
|
|
35255
35276
|
const actualControls = readCodexPluginRootControls(root, read);
|
|
@@ -35274,8 +35295,8 @@ function assertSkillMaterializations(cacheRoot, controls, files, read) {
|
|
|
35274
35295
|
const rel = relative6(cacheRoot, file2).split(sep9);
|
|
35275
35296
|
if (rel.length < 4)
|
|
35276
35297
|
refuse3();
|
|
35277
|
-
const parent =
|
|
35278
|
-
if (!byParent.has(parent) || !expectedByRoot.has(`${byParent.get(parent)[0].pluginId}\x00${
|
|
35298
|
+
const parent = join22(cacheRoot, rel[0], rel[1]);
|
|
35299
|
+
if (!byParent.has(parent) || !expectedByRoot.has(`${byParent.get(parent)[0].pluginId}\x00${join22(parent, rel[2])}`))
|
|
35279
35300
|
refuse3();
|
|
35280
35301
|
}
|
|
35281
35302
|
return expectedByRoot;
|
|
@@ -35336,11 +35357,11 @@ function captureCodexSemanticCacheWitness(options) {
|
|
|
35336
35357
|
const rootNames = new Map;
|
|
35337
35358
|
for (const document2 of docs) {
|
|
35338
35359
|
const rel = relative6(options.cacheRoot, document2).split(sep9);
|
|
35339
|
-
if (appOnlyParents.some((parent) => parent.pluginParent ===
|
|
35360
|
+
if (appOnlyParents.some((parent) => parent.pluginParent === join22(options.cacheRoot, rel[0], rel[1])))
|
|
35340
35361
|
refuse3();
|
|
35341
|
-
if (hookParents.some((parent) => parent.pluginParent ===
|
|
35362
|
+
if (hookParents.some((parent) => parent.pluginParent === join22(options.cacheRoot, rel[0], rel[1])))
|
|
35342
35363
|
refuse3();
|
|
35343
|
-
const documentStat =
|
|
35364
|
+
const documentStat = lstatSync17(document2, { throwIfNoEntry: false });
|
|
35344
35365
|
if (!documentStat?.isFile() || documentStat.isSymbolicLink() || documentStat.size > MAX_DOCUMENT_BYTES)
|
|
35345
35366
|
refuse3();
|
|
35346
35367
|
const identity4 = classifyCodexPluginCacheDocument(document2, options.cacheRoot, read);
|
|
@@ -35474,8 +35495,8 @@ var init_codex_node_modules = __esm(() => {
|
|
|
35474
35495
|
});
|
|
35475
35496
|
|
|
35476
35497
|
// src/lib/managed-policy.ts
|
|
35477
|
-
import { closeSync as closeSync14, constants as constants11, fstatSync as fstatSync14, lstatSync as
|
|
35478
|
-
import { join as
|
|
35498
|
+
import { closeSync as closeSync14, constants as constants11, fstatSync as fstatSync14, lstatSync as lstatSync18, openSync as openSync14, readSync as readSync8 } from "fs";
|
|
35499
|
+
import { join as join23 } from "path";
|
|
35479
35500
|
function refusal(reason2 = "is unreadable") {
|
|
35480
35501
|
return new SkillSelectionError("INVALID_AGENT_POLICY", `The Skills agent loading policy ${reason2}; refusing legacy fallback.`);
|
|
35481
35502
|
}
|
|
@@ -35500,10 +35521,10 @@ function parseManagedSkillPolicy(text2) {
|
|
|
35500
35521
|
return value;
|
|
35501
35522
|
}
|
|
35502
35523
|
function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
|
|
35503
|
-
const path =
|
|
35524
|
+
const path = join23(dataDir2, "agent-policy.json");
|
|
35504
35525
|
let descriptor, observed = false;
|
|
35505
35526
|
try {
|
|
35506
|
-
const stat2 =
|
|
35527
|
+
const stat2 = lstatSync18(path);
|
|
35507
35528
|
observed = true;
|
|
35508
35529
|
if (!stat2.isFile() || stat2.isSymbolicLink())
|
|
35509
35530
|
throw refusal();
|
|
@@ -35529,7 +35550,7 @@ function readManagedSkillPolicySnapshot(dataDir2 = getDataDirReadOnly()) {
|
|
|
35529
35550
|
return { text: text2, value: parseManagedSkillPolicy(text2) };
|
|
35530
35551
|
} catch (error61) {
|
|
35531
35552
|
if (error61.code === "ENOENT" && !observed) {
|
|
35532
|
-
if (
|
|
35553
|
+
if (lstatSync18(path, { throwIfNoEntry: false }) === undefined)
|
|
35533
35554
|
return null;
|
|
35534
35555
|
}
|
|
35535
35556
|
if (error61 instanceof SkillSelectionError)
|
|
@@ -35655,8 +35676,8 @@ var init_hook_diagnostics = __esm(() => {
|
|
|
35655
35676
|
|
|
35656
35677
|
// src/lib/agent-sumi.ts
|
|
35657
35678
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
35658
|
-
import { accessSync, constants as constants12, existsSync as existsSync8, lstatSync as
|
|
35659
|
-
import { delimiter, isAbsolute as isAbsolute16, join as
|
|
35679
|
+
import { accessSync, constants as constants12, existsSync as existsSync8, lstatSync as lstatSync19, realpathSync as realpathSync7, statSync as statSync8 } from "fs";
|
|
35680
|
+
import { delimiter, isAbsolute as isAbsolute16, join as join24, resolve as resolve16 } from "path";
|
|
35660
35681
|
function recordWithKeys(value, keys) {
|
|
35661
35682
|
return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys.length && keys.every((key2) => Object.hasOwn(value, key2));
|
|
35662
35683
|
}
|
|
@@ -35706,11 +35727,11 @@ function validPathPlan(value, home, cwd) {
|
|
|
35706
35727
|
const legacyConfigRoot = value.legacyRoots.config;
|
|
35707
35728
|
if (typeof configRoot !== "string" || legacyConfigRoot !== null && typeof legacyConfigRoot !== "string")
|
|
35708
35729
|
return false;
|
|
35709
|
-
if (value.configFiles.canonical !==
|
|
35730
|
+
if (value.configFiles.canonical !== join24(configRoot, "sumi.json") || value.skillRoots.canonical !== join24(configRoot, "skills"))
|
|
35710
35731
|
return false;
|
|
35711
35732
|
if (legacyConfigRoot === null)
|
|
35712
35733
|
return value.configFiles.legacy === null && value.skillRoots.legacy === null;
|
|
35713
|
-
return value.configFiles.legacy ===
|
|
35734
|
+
return value.configFiles.legacy === join24(legacyConfigRoot, "sumi.json") && value.skillRoots.legacy === join24(legacyConfigRoot, "skills");
|
|
35714
35735
|
}
|
|
35715
35736
|
function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
|
|
35716
35737
|
for (const key2 of ["SUMI_CONFIG", "SUMI_CONFIG_CONTENT"])
|
|
@@ -35761,7 +35782,7 @@ function selectedConfigDirectory(plan) {
|
|
|
35761
35782
|
const canonical9 = plan.roots.config, legacy = plan.legacyRoots.config;
|
|
35762
35783
|
if (legacy === null)
|
|
35763
35784
|
return existsSync8(canonical9) ? realpathSync7(canonical9) : canonical9;
|
|
35764
|
-
const canonicalStat =
|
|
35785
|
+
const canonicalStat = lstatSync19(canonical9, { throwIfNoEntry: false }), legacyStat = lstatSync19(legacy, { throwIfNoEntry: false });
|
|
35765
35786
|
if (canonicalStat && legacyStat && realpathSync7(canonical9) !== realpathSync7(legacy))
|
|
35766
35787
|
throw new Error("Sumi config roots conflict; complete native home adoption before Skills integration");
|
|
35767
35788
|
const selected = canonicalStat ? canonical9 : legacyStat ? legacy : canonical9;
|
|
@@ -35776,7 +35797,7 @@ function sumiConfigDirectory(home, env = process.env, cwd = process.cwd()) {
|
|
|
35776
35797
|
return selectedConfigDirectory(sumiPathPlan(home, cwd, env));
|
|
35777
35798
|
}
|
|
35778
35799
|
function sumiConfigPath(home, cwd = process.cwd(), env = process.env) {
|
|
35779
|
-
return
|
|
35800
|
+
return join24(sumiConfigDirectory(home, env, cwd), "sumi.json");
|
|
35780
35801
|
}
|
|
35781
35802
|
var SUMI_PATH_SELECTORS, SUMI_PATH_KEYS, SUMI_PATH_OUTPUT_LIMIT, SumiPathResolverError;
|
|
35782
35803
|
var init_agent_sumi = __esm(() => {
|
|
@@ -35795,9 +35816,9 @@ var init_agent_sumi = __esm(() => {
|
|
|
35795
35816
|
});
|
|
35796
35817
|
|
|
35797
35818
|
// src/lib/codex-hook-trust-files.ts
|
|
35798
|
-
import { closeSync as closeSync15, constants as constants13, fstatSync as fstatSync15, fsyncSync as fsyncSync3, lstatSync as
|
|
35819
|
+
import { closeSync as closeSync15, constants as constants13, fstatSync as fstatSync15, fsyncSync as fsyncSync3, lstatSync as lstatSync20, openSync as openSync15, readlinkSync as readlinkSync4, readSync as readSync9, writeFileSync as writeFileSync4 } from "fs";
|
|
35799
35820
|
import { createHash as createHash20 } from "crypto";
|
|
35800
|
-
import { dirname as
|
|
35821
|
+
import { dirname as dirname18, isAbsolute as isAbsolute17, resolve as resolve17 } from "path";
|
|
35801
35822
|
function need8(value, code) {
|
|
35802
35823
|
if (!value)
|
|
35803
35824
|
throw new Error(`CODEX_HOOK_TRUST_${code}`);
|
|
@@ -35806,18 +35827,18 @@ function trustedAncestorOwner(uid2) {
|
|
|
35806
35827
|
return BigInt(uid2) === 0n || BigInt(uid2) === BigInt(process.getuid());
|
|
35807
35828
|
}
|
|
35808
35829
|
function safeParents(file2) {
|
|
35809
|
-
for (let p =
|
|
35810
|
-
const s =
|
|
35830
|
+
for (let p = dirname18(file2);; p = dirname18(p)) {
|
|
35831
|
+
const s = lstatSync20(p);
|
|
35811
35832
|
need8(s.isDirectory() && !s.isSymbolicLink() && trustedAncestorOwner(s.uid), "UNSAFE_PARENT");
|
|
35812
35833
|
need8((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
|
|
35813
|
-
if (
|
|
35834
|
+
if (dirname18(p) === p)
|
|
35814
35835
|
break;
|
|
35815
35836
|
}
|
|
35816
35837
|
}
|
|
35817
35838
|
function snapshot(file2, privateFile = false, options = {}) {
|
|
35818
35839
|
const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
|
|
35819
35840
|
safeParents(file2);
|
|
35820
|
-
const initial =
|
|
35841
|
+
const initial = lstatSync20(file2, { bigint: true });
|
|
35821
35842
|
need8(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");
|
|
35822
35843
|
need8(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
|
|
35823
35844
|
const fd = openSync15(file2, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
|
|
@@ -35832,7 +35853,7 @@ function snapshot(file2, privateFile = false, options = {}) {
|
|
|
35832
35853
|
break;
|
|
35833
35854
|
length += n2;
|
|
35834
35855
|
}
|
|
35835
|
-
need8(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before,
|
|
35856
|
+
need8(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before, lstatSync20(file2, { bigint: true })), "INPUT_CHANGED");
|
|
35836
35857
|
const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
35837
35858
|
return { file: file2, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash20("sha256").update(content).digest("hex") };
|
|
35838
35859
|
} finally {
|
|
@@ -35899,25 +35920,25 @@ var init_runtime_launcher = __esm(() => {
|
|
|
35899
35920
|
|
|
35900
35921
|
// src/lib/retained-review-artifacts.ts
|
|
35901
35922
|
import { createHash as createHash21 } from "crypto";
|
|
35902
|
-
import { constants as constants14, closeSync as closeSync16, fstatSync as fstatSync16, fsyncSync as fsyncSync4, lstatSync as
|
|
35903
|
-
import { dirname as
|
|
35923
|
+
import { constants as constants14, closeSync as closeSync16, fstatSync as fstatSync16, fsyncSync as fsyncSync4, lstatSync as lstatSync21, mkdirSync as mkdirSync6, openSync as openSync16, readSync as readSync10, writeSync as writeSync3 } from "fs";
|
|
35924
|
+
import { dirname as dirname19, isAbsolute as isAbsolute18, join as join25, resolve as resolve18, sep as sep10 } from "path";
|
|
35904
35925
|
function keys(value, names) {
|
|
35905
35926
|
return Boolean(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === names.length && names.every((name) => Object.hasOwn(value, name)));
|
|
35906
35927
|
}
|
|
35907
35928
|
function safe4(path) {
|
|
35908
35929
|
need9(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute18(path) && resolve18(path) === path && !/[\x00-\x1f\x7f]/.test(path));
|
|
35909
|
-
for (let cursor = path;; cursor =
|
|
35910
|
-
const stat2 =
|
|
35930
|
+
for (let cursor = path;; cursor = dirname19(cursor)) {
|
|
35931
|
+
const stat2 = lstatSync21(cursor, { throwIfNoEntry: false });
|
|
35911
35932
|
need9(!stat2?.isSymbolicLink());
|
|
35912
35933
|
if (cursor !== path && stat2)
|
|
35913
35934
|
need9(stat2.isDirectory());
|
|
35914
|
-
if (
|
|
35935
|
+
if (dirname19(cursor) === cursor)
|
|
35915
35936
|
break;
|
|
35916
35937
|
}
|
|
35917
35938
|
}
|
|
35918
35939
|
function readExact(path) {
|
|
35919
35940
|
safe4(path);
|
|
35920
|
-
const before =
|
|
35941
|
+
const before = lstatSync21(path, { throwIfNoEntry: false });
|
|
35921
35942
|
need9(before?.isFile() && before.nlink === 1 && before.size <= AGENT_POLICY_LIMITS.discoveryRawSourceBytes && (before.mode & 63) === 0 && (process.getuid === undefined || before.uid === process.getuid()));
|
|
35922
35943
|
const fd = openSync16(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
|
|
35923
35944
|
try {
|
|
@@ -35931,7 +35952,7 @@ function readExact(path) {
|
|
|
35931
35952
|
offset += count;
|
|
35932
35953
|
}
|
|
35933
35954
|
need9(readSync10(fd, Buffer.alloc(1), 0, 1, null) === 0);
|
|
35934
|
-
const after = fstatSync16(fd), current =
|
|
35955
|
+
const after = fstatSync16(fd), current = lstatSync21(path, { throwIfNoEntry: false });
|
|
35935
35956
|
safe4(path);
|
|
35936
35957
|
need9(current && opened.dev === current.dev && opened.ino === current.ino && opened.mode === current.mode && opened.uid === current.uid && opened.size === current.size && opened.mtimeMs === current.mtimeMs && opened.ctimeMs === current.ctimeMs && current.nlink === 1 && opened.mode === after.mode && opened.uid === after.uid && after.nlink === 1 && opened.size === after.size && opened.mtimeMs === after.mtimeMs && opened.ctimeMs === after.ctimeMs);
|
|
35937
35958
|
const text2 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
@@ -35948,20 +35969,20 @@ function catalogDigest(text2) {
|
|
|
35948
35969
|
} catch {
|
|
35949
35970
|
return refuse4();
|
|
35950
35971
|
}
|
|
35951
|
-
need9(catalog && typeof catalog === "object" && !Array.isArray(catalog) && Object.keys(catalog).every((key2) => ["version", "cwd", "skills", "plugins"].includes(key2)) && typeof catalog.version === "string" && supportsCodexNativeCapability(catalog.version, "installed-plugin-review"));
|
|
35972
|
+
need9(catalog && typeof catalog === "object" && !Array.isArray(catalog) && Object.keys(catalog).every((key2) => ["version", "cwd", "skills", "plugins", "remoteReceipts"].includes(key2)) && typeof catalog.version === "string" && supportsCodexNativeCapability(catalog.version, "installed-plugin-review"));
|
|
35952
35973
|
const skills = projectCodexNativeSkillCatalog({ data: [{ cwd: catalog.cwd, errors: [], skills: catalog.skills }] }, catalog.cwd);
|
|
35953
35974
|
const plugins = catalog.plugins === undefined ? undefined : projectCodexInstalledPluginEntries(catalog.plugins);
|
|
35954
35975
|
return sha3(JSON.stringify({ version: catalog.version, cwd: catalog.cwd, skills, ...plugins === undefined ? {} : { plugins } }));
|
|
35955
35976
|
}
|
|
35956
35977
|
function retainedArtifactPath(metadata) {
|
|
35957
|
-
return
|
|
35978
|
+
return join25(metadata.storeRoot, "agent-discovery", "artifacts", metadata.sha256, "catalog.json");
|
|
35958
35979
|
}
|
|
35959
35980
|
function validRetainedArtifact(value) {
|
|
35960
35981
|
return keys(value, ["version", "kind", "storeRoot", "originalPath", "sha256", "catalogSha256"]) && value.version === 1 && value.kind === "codex-native-catalog" && hex3(value.sha256) && hex3(value.catalogSha256) && [value.storeRoot, value.originalPath].every((path) => typeof path === "string" && isAbsolute18(path) && resolve18(path) === path && path.length <= AGENT_POLICY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(path));
|
|
35961
35982
|
}
|
|
35962
35983
|
function privateStore(storeRoot) {
|
|
35963
35984
|
safe4(storeRoot);
|
|
35964
|
-
const stat2 =
|
|
35985
|
+
const stat2 = lstatSync21(storeRoot, { throwIfNoEntry: false });
|
|
35965
35986
|
need9(!stat2 || stat2.isDirectory() && (stat2.mode & 18) === 0 && (process.getuid === undefined || stat2.uid === process.getuid()));
|
|
35966
35987
|
}
|
|
35967
35988
|
function verifyRetainedReviewArtifact(source, storeRoot) {
|
|
@@ -35970,8 +35991,8 @@ function verifyRetainedReviewArtifact(source, storeRoot) {
|
|
|
35970
35991
|
privateStore(artifact.storeRoot);
|
|
35971
35992
|
const text2 = readExact(source.path);
|
|
35972
35993
|
need9(sha3(text2) === artifact.sha256 && catalogDigest(text2) === artifact.catalogSha256);
|
|
35973
|
-
for (let parent =
|
|
35974
|
-
const stat2 =
|
|
35994
|
+
for (let parent = dirname19(source.path);parent !== artifact.storeRoot; parent = dirname19(parent)) {
|
|
35995
|
+
const stat2 = lstatSync21(parent);
|
|
35975
35996
|
need9(stat2.isDirectory() && (stat2.mode & 63) === 0 && (process.getuid === undefined || stat2.uid === process.getuid()));
|
|
35976
35997
|
}
|
|
35977
35998
|
}
|
|
@@ -35991,6 +36012,8 @@ var init_retained_review_artifacts = __esm(() => {
|
|
|
35991
36012
|
var init_agent_integration = __esm(() => {
|
|
35992
36013
|
init_sumi_settings_witness();
|
|
35993
36014
|
init_codex_corpus_write();
|
|
36015
|
+
init_codex_hook_rpc();
|
|
36016
|
+
init_codex_native_config();
|
|
35994
36017
|
init_codex_plugin_skill_controls();
|
|
35995
36018
|
init_codex_native_skill_policy();
|
|
35996
36019
|
init_codex_native_skill_catalog();
|
|
@@ -36050,20 +36073,20 @@ var init_skill_aliases = __esm(() => {
|
|
|
36050
36073
|
});
|
|
36051
36074
|
|
|
36052
36075
|
// src/lib/project-state.ts
|
|
36053
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as
|
|
36054
|
-
import { join as
|
|
36076
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync15, writeFileSync as writeFileSync5 } from "fs";
|
|
36077
|
+
import { join as join26 } from "path";
|
|
36055
36078
|
function getProjectStateDir(targetDir = process.cwd()) {
|
|
36056
|
-
return
|
|
36079
|
+
return join26(targetDir, SKILLS_PROJECT_DIR);
|
|
36057
36080
|
}
|
|
36058
36081
|
function getProjectConfigPath(targetDir = process.cwd()) {
|
|
36059
|
-
return
|
|
36082
|
+
return join26(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
|
|
36060
36083
|
}
|
|
36061
36084
|
function loadProjectConfig(targetDir = process.cwd()) {
|
|
36062
36085
|
const path = getProjectConfigPath(targetDir);
|
|
36063
36086
|
if (!existsSync9(path))
|
|
36064
36087
|
return null;
|
|
36065
36088
|
try {
|
|
36066
|
-
return normalizeProjectConfig(JSON.parse(
|
|
36089
|
+
return normalizeProjectConfig(JSON.parse(readFileSync15(path, "utf-8")));
|
|
36067
36090
|
} catch {
|
|
36068
36091
|
return null;
|
|
36069
36092
|
}
|
|
@@ -36171,8 +36194,8 @@ var init_project_state = __esm(() => {
|
|
|
36171
36194
|
});
|
|
36172
36195
|
|
|
36173
36196
|
// src/lib/installer.ts
|
|
36174
|
-
import { existsSync as existsSync10, readFileSync as
|
|
36175
|
-
import { join as
|
|
36197
|
+
import { existsSync as existsSync10, readFileSync as readFileSync16, rmSync as rmSync2 } from "fs";
|
|
36198
|
+
import { join as join27 } from "path";
|
|
36176
36199
|
import { homedir as homedir2 } from "os";
|
|
36177
36200
|
function getSkillPath(name) {
|
|
36178
36201
|
const skillName = normalizeSkillName(getCanonicalSkillName(name));
|
|
@@ -36182,7 +36205,7 @@ function getSkillPath(name) {
|
|
|
36182
36205
|
const extensionPath = findExtensionSkillPath(skillName);
|
|
36183
36206
|
if (extensionPath)
|
|
36184
36207
|
return extensionPath;
|
|
36185
|
-
return
|
|
36208
|
+
return join27(getPortableSkillsRoot(), skillName);
|
|
36186
36209
|
}
|
|
36187
36210
|
function getCanonicalSkillName(name) {
|
|
36188
36211
|
return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
|
|
@@ -36236,11 +36259,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
|
|
|
36236
36259
|
const base = projectDir || process.cwd();
|
|
36237
36260
|
switch (agent) {
|
|
36238
36261
|
case "pi":
|
|
36239
|
-
return scope === "project" ?
|
|
36262
|
+
return scope === "project" ? join27(base, ".pi", "skills") : join27(homedir2(), ".pi", "agent", "skills");
|
|
36240
36263
|
case "opencode":
|
|
36241
|
-
return scope === "project" ?
|
|
36264
|
+
return scope === "project" ? join27(base, ".opencode", "skills") : join27(homedir2(), ".config", "opencode", "skills");
|
|
36242
36265
|
default:
|
|
36243
|
-
return scope === "project" ?
|
|
36266
|
+
return scope === "project" ? join27(base, `.${agent}`, "skills") : join27(homedir2(), `.${agent}`, "skills");
|
|
36244
36267
|
}
|
|
36245
36268
|
}
|
|
36246
36269
|
function warnMissingDependencies(name, targetDir) {
|
|
@@ -36255,11 +36278,11 @@ function warnMissingDependencies(name, targetDir) {
|
|
|
36255
36278
|
}
|
|
36256
36279
|
}
|
|
36257
36280
|
function readBundledSkillVersion(name) {
|
|
36258
|
-
const pkgPath =
|
|
36281
|
+
const pkgPath = join27(getSkillPath(name), "package.json");
|
|
36259
36282
|
if (!existsSync10(pkgPath))
|
|
36260
36283
|
return "unknown";
|
|
36261
36284
|
try {
|
|
36262
|
-
const pkg = JSON.parse(
|
|
36285
|
+
const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
|
|
36263
36286
|
return pkg.version || "unknown";
|
|
36264
36287
|
} catch {
|
|
36265
36288
|
return "unknown";
|
|
@@ -36324,16 +36347,16 @@ var init_skill_doc_file = __esm(() => {
|
|
|
36324
36347
|
});
|
|
36325
36348
|
|
|
36326
36349
|
// src/lib/skillinfo.ts
|
|
36327
|
-
import { existsSync as existsSync11, readFileSync as
|
|
36328
|
-
import { join as
|
|
36350
|
+
import { existsSync as existsSync11, readFileSync as readFileSync17 } from "fs";
|
|
36351
|
+
import { join as join28 } from "path";
|
|
36329
36352
|
function isInstructionSkillDir(skillPath, meta3) {
|
|
36330
36353
|
if (meta3?.kind === "instruction")
|
|
36331
36354
|
return true;
|
|
36332
|
-
const skillMdPath =
|
|
36355
|
+
const skillMdPath = join28(skillPath, "SKILL.md");
|
|
36333
36356
|
if (!existsSync11(skillMdPath))
|
|
36334
36357
|
return false;
|
|
36335
36358
|
try {
|
|
36336
|
-
return parseSkillFrontmatter(
|
|
36359
|
+
return parseSkillFrontmatter(readFileSync17(skillMdPath, "utf-8"))?.kind === "instruction";
|
|
36337
36360
|
} catch {
|
|
36338
36361
|
return false;
|
|
36339
36362
|
}
|
|
@@ -36343,9 +36366,9 @@ function getSkillDocs(name) {
|
|
|
36343
36366
|
if (!existsSync11(skillPath))
|
|
36344
36367
|
return null;
|
|
36345
36368
|
return {
|
|
36346
|
-
skillMd: readIfExists(
|
|
36347
|
-
readme: readIfExists(
|
|
36348
|
-
claudeMd: readIfExists(
|
|
36369
|
+
skillMd: readIfExists(join28(skillPath, "SKILL.md")),
|
|
36370
|
+
readme: readIfExists(join28(skillPath, "README.md")),
|
|
36371
|
+
claudeMd: readIfExists(join28(skillPath, "CLAUDE.md"))
|
|
36349
36372
|
};
|
|
36350
36373
|
}
|
|
36351
36374
|
function getSkillBestDoc(name, file2) {
|
|
@@ -36361,14 +36384,14 @@ function getSkillRequirements(name) {
|
|
|
36361
36384
|
return null;
|
|
36362
36385
|
const texts = [];
|
|
36363
36386
|
for (const file2 of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
|
|
36364
|
-
const content = readIfExists(
|
|
36387
|
+
const content = readIfExists(join28(skillPath, file2));
|
|
36365
36388
|
if (content)
|
|
36366
36389
|
texts.push(content);
|
|
36367
36390
|
}
|
|
36368
36391
|
const meta3 = getSkill(name);
|
|
36369
36392
|
let dependencies = {};
|
|
36370
36393
|
try {
|
|
36371
|
-
dependencies = JSON.parse(
|
|
36394
|
+
dependencies = JSON.parse(readFileSync17(join28(skillPath, "package.json"), "utf8")).dependencies || {};
|
|
36372
36395
|
} catch {}
|
|
36373
36396
|
return getSkillRequirementsFromContent(name, texts, dependencies, meta3);
|
|
36374
36397
|
}
|
|
@@ -36430,13 +36453,13 @@ async function runSkill(name, args, options = {}) {
|
|
|
36430
36453
|
error: `Skill '${name}' is an instruction skill (kind: instruction) and is not runnable. Instruction skills are consumed by coding agents via SKILL.md, not executed with 'skills run'.`
|
|
36431
36454
|
};
|
|
36432
36455
|
}
|
|
36433
|
-
const pkgPath =
|
|
36456
|
+
const pkgPath = join28(skillPath, "package.json");
|
|
36434
36457
|
if (!existsSync11(pkgPath)) {
|
|
36435
36458
|
return { exitCode: 1, error: `No package.json in skill '${name}'` };
|
|
36436
36459
|
}
|
|
36437
36460
|
let entryPoint2;
|
|
36438
36461
|
try {
|
|
36439
|
-
const pkg = JSON.parse(
|
|
36462
|
+
const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
|
|
36440
36463
|
if (pkg.bin) {
|
|
36441
36464
|
const binValues = Object.values(pkg.bin);
|
|
36442
36465
|
entryPoint2 = binValues[0];
|
|
@@ -36450,12 +36473,12 @@ async function runSkill(name, args, options = {}) {
|
|
|
36450
36473
|
} catch {
|
|
36451
36474
|
return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
|
|
36452
36475
|
}
|
|
36453
|
-
const entryPath =
|
|
36476
|
+
const entryPath = join28(skillPath, entryPoint2);
|
|
36454
36477
|
if (!existsSync11(entryPath)) {
|
|
36455
36478
|
return { exitCode: 1, error: `Entry point '${entryPoint2}' not found in skill '${name}'` };
|
|
36456
36479
|
}
|
|
36457
36480
|
const env = { ...process.env, ...options.env };
|
|
36458
|
-
if (!existsSync11(
|
|
36481
|
+
if (!existsSync11(join28(skillPath, "node_modules")) || hasDependencyPreparationMarker(skillPath)) {
|
|
36459
36482
|
const failure = await prepareSkillDependencies(skillPath, env, options.preparationTimeoutMs);
|
|
36460
36483
|
if (failure)
|
|
36461
36484
|
return failure;
|
|
@@ -36481,7 +36504,7 @@ async function runSkill(name, args, options = {}) {
|
|
|
36481
36504
|
function detectProjectSkills(cwd = process.cwd()) {
|
|
36482
36505
|
let pkg;
|
|
36483
36506
|
try {
|
|
36484
|
-
pkg = JSON.parse(
|
|
36507
|
+
pkg = JSON.parse(readFileSync17(join28(cwd, "package.json"), "utf8"));
|
|
36485
36508
|
} catch {
|
|
36486
36509
|
return { detected: [], recommended: [] };
|
|
36487
36510
|
}
|
|
@@ -36518,7 +36541,7 @@ function extractEnvVars(text2) {
|
|
|
36518
36541
|
function readIfExists(path) {
|
|
36519
36542
|
try {
|
|
36520
36543
|
if (existsSync11(path)) {
|
|
36521
|
-
return
|
|
36544
|
+
return readFileSync17(path, "utf-8");
|
|
36522
36545
|
}
|
|
36523
36546
|
} catch {}
|
|
36524
36547
|
return null;
|
|
@@ -36846,7 +36869,7 @@ var init_selected_manifest = __esm(() => {
|
|
|
36846
36869
|
});
|
|
36847
36870
|
|
|
36848
36871
|
// src/lib/plugin-admission.ts
|
|
36849
|
-
import { isAbsolute as isAbsolute19, join as
|
|
36872
|
+
import { isAbsolute as isAbsolute19, join as join29, resolve as resolve19 } from "path";
|
|
36850
36873
|
function validatePluginTarget(value) {
|
|
36851
36874
|
pluginKeys(value, ["schemaVersion", "pluginId", "registrations", "native", "resolver"]);
|
|
36852
36875
|
pluginNeed(value.schemaVersion === 1, "Invalid plugin admission target");
|
|
@@ -37007,12 +37030,12 @@ function pluginResolverCommand(binding) {
|
|
|
37007
37030
|
}
|
|
37008
37031
|
function pluginBindingPath(storeRoot, id) {
|
|
37009
37032
|
pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
|
|
37010
|
-
return
|
|
37033
|
+
return join29(storeRoot, "bindings", `${id}.json`);
|
|
37011
37034
|
}
|
|
37012
37035
|
function pluginReceiptPath(storeRoot, id, digest2) {
|
|
37013
37036
|
pluginNeed(/^[a-f0-9]{64}$/.test(id), "Invalid plugin binding identifier");
|
|
37014
37037
|
pluginDigest(digest2);
|
|
37015
|
-
return
|
|
37038
|
+
return join29(storeRoot, "receipts", id, `${digest2.slice(7)}.json`);
|
|
37016
37039
|
}
|
|
37017
37040
|
function readPluginBinding(storeRoot, id) {
|
|
37018
37041
|
const value = readPluginJson(pluginBindingPath(storeRoot, id));
|
|
@@ -37032,7 +37055,7 @@ function readPluginAdmissionReceipt(storeRoot, id, digest2) {
|
|
|
37032
37055
|
pluginNeed(receipt.plan.bindingId === id && receipt.plan.planDigest === digest2, "Plugin receipt identity differs from its filename");
|
|
37033
37056
|
const binding = readPluginBinding(storeRoot, id);
|
|
37034
37057
|
pluginNeed(canonicalJson(binding) === canonicalJson(receipt.plan.binding) && receipt.plan.sourceCommand === pluginResolverCommand(binding), "Plugin receipt binding changed");
|
|
37035
|
-
pluginNeed(receipt.materializedPath ===
|
|
37058
|
+
pluginNeed(receipt.materializedPath === join29(storeRoot, "objects", id, digest2.slice(7)), "Plugin receipt points outside its immutable materialization");
|
|
37036
37059
|
pluginText(receipt.admittedAt, 64);
|
|
37037
37060
|
pluginNeed(Number.isFinite(Date.parse(receipt.admittedAt)), "Invalid plugin admission time");
|
|
37038
37061
|
return receipt;
|
|
@@ -37049,8 +37072,8 @@ var init_plugin_admission = __esm(() => {
|
|
|
37049
37072
|
});
|
|
37050
37073
|
|
|
37051
37074
|
// src/lib/plugin-discovery.ts
|
|
37052
|
-
import { closeSync as closeSync17, constants as constants15, fstatSync as fstatSync17, lstatSync as
|
|
37053
|
-
import { basename as
|
|
37075
|
+
import { closeSync as closeSync17, constants as constants15, fstatSync as fstatSync17, lstatSync as lstatSync22, openSync as openSync17, opendirSync as opendirSync3, readSync as readSync11 } from "fs";
|
|
37076
|
+
import { basename as basename11, dirname as dirname20, isAbsolute as isAbsolute20, join as join30, resolve as resolve20 } from "path";
|
|
37054
37077
|
function validateManagedPluginWitnesses(value) {
|
|
37055
37078
|
pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
|
|
37056
37079
|
const seen = new Set;
|
|
@@ -37065,15 +37088,15 @@ function validateManagedPluginWitnesses(value) {
|
|
|
37065
37088
|
function safe5(path) {
|
|
37066
37089
|
pluginText(path);
|
|
37067
37090
|
pluginNeed(isAbsolute20(path) && resolve20(path) === path, "Invalid plugin registry path");
|
|
37068
|
-
for (let at = path;; at =
|
|
37069
|
-
pluginNeed(!
|
|
37070
|
-
if (at ===
|
|
37091
|
+
for (let at = path;; at = dirname20(at)) {
|
|
37092
|
+
pluginNeed(!lstatSync22(at, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
|
|
37093
|
+
if (at === dirname20(at))
|
|
37071
37094
|
break;
|
|
37072
37095
|
}
|
|
37073
37096
|
}
|
|
37074
37097
|
function readRegistry(path) {
|
|
37075
37098
|
safe5(path);
|
|
37076
|
-
const initial =
|
|
37099
|
+
const initial = lstatSync22(path);
|
|
37077
37100
|
pluginNeed(initial.isFile() && initial.size <= 1024 * 1024, "Plugin registry is not a bounded regular file");
|
|
37078
37101
|
const fd = openSync17(path, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
|
|
37079
37102
|
try {
|
|
@@ -37087,7 +37110,7 @@ function readRegistry(path) {
|
|
|
37087
37110
|
break;
|
|
37088
37111
|
length += count;
|
|
37089
37112
|
}
|
|
37090
|
-
const after = fstatSync17(fd), current =
|
|
37113
|
+
const after = fstatSync17(fd), current = lstatSync22(path);
|
|
37091
37114
|
safe5(path);
|
|
37092
37115
|
pluginNeed(length <= 1024 * 1024 && length === opened.size && after.size === opened.size && after.mtimeMs === opened.mtimeMs && after.ctimeMs === opened.ctimeMs && current.dev === opened.dev && current.ino === opened.ino && current.mtimeMs === opened.mtimeMs && current.ctimeMs === opened.ctimeMs, "Plugin registry changed during read");
|
|
37093
37116
|
let value;
|
|
@@ -37117,7 +37140,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
37117
37140
|
seen.add(target.pluginId);
|
|
37118
37141
|
const rows = plugins[target.pluginId];
|
|
37119
37142
|
pluginNeed(Array.isArray(rows) && rows.length === target.registrations.length, "Managed plugin registration membership changed");
|
|
37120
|
-
const [name, market] = target.pluginId.split("@"), cacheRoot =
|
|
37143
|
+
const [name, market] = target.pluginId.split("@"), cacheRoot = join30(dirname20(path), "cache", market, name);
|
|
37121
37144
|
const scopes = new Set, approvals = new Map, currentFiles = new Map;
|
|
37122
37145
|
plugins[target.pluginId] = rows.map((row) => {
|
|
37123
37146
|
pluginNeed(pluginObject(row), "Invalid managed plugin registration");
|
|
@@ -37130,10 +37153,10 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
37130
37153
|
pluginText(row.sourceProducerPath);
|
|
37131
37154
|
pluginText(row.lastUpdated, 64);
|
|
37132
37155
|
pluginNeed(Number.isFinite(Date.parse(row.lastUpdated)), "Invalid managed plugin update timestamp");
|
|
37133
|
-
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath ===
|
|
37156
|
+
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join30(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
37134
37157
|
const approval = (producer) => {
|
|
37135
37158
|
pluginText(producer);
|
|
37136
|
-
const digest2 = `sha256:${
|
|
37159
|
+
const digest2 = `sha256:${basename11(producer)}`;
|
|
37137
37160
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
|
|
37138
37161
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
37139
37162
|
if (!verified.has(producer)) {
|
|
@@ -37160,7 +37183,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
37160
37183
|
return Object.fromEntries(Object.entries(row).filter(([key2]) => !["version", "installPath", "sourceProducerPath", "previousProducerPaths", "lastUpdated"].includes(key2)));
|
|
37161
37184
|
});
|
|
37162
37185
|
safe5(cacheRoot);
|
|
37163
|
-
const before =
|
|
37186
|
+
const before = lstatSync22(cacheRoot);
|
|
37164
37187
|
pluginNeed(before.isDirectory(), "Invalid managed plugin cache root");
|
|
37165
37188
|
const directory = opendirSync3(cacheRoot), names = [];
|
|
37166
37189
|
try {
|
|
@@ -37173,17 +37196,17 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
37173
37196
|
directory.closeSync();
|
|
37174
37197
|
}
|
|
37175
37198
|
for (const version2 of names.sort()) {
|
|
37176
|
-
const files = pluginFileWitnesses(snapshotPluginTree(
|
|
37199
|
+
const files = pluginFileWitnesses(snapshotPluginTree(join30(cacheRoot, version2), { nativeRuntime: `claude-${target.native.version}` }));
|
|
37177
37200
|
verifiedBytes += files.reduce((total, file2) => total + file2.size, 0);
|
|
37178
37201
|
pluginNeed(verifiedBytes <= 256 * 1024 * 1024, "Managed plugin verification exceeds its aggregate byte budget");
|
|
37179
37202
|
const serialized = JSON.stringify(files);
|
|
37180
|
-
const expected = currentFiles.get(
|
|
37203
|
+
const expected = currentFiles.get(join30(cacheRoot, version2));
|
|
37181
37204
|
pluginNeed(expected === undefined || serialized === expected, "Current native cache differs from its exact registered producer receipt");
|
|
37182
37205
|
pluginNeed([...approvals.values()].some((receipt) => nativeVersionMatches(version2, receipt) && JSON.stringify(receipt.plan.files) === serialized), "A retained native plugin cache version differs from every approved projection");
|
|
37183
37206
|
}
|
|
37184
37207
|
for (const row of rows)
|
|
37185
37208
|
pluginNeed(names.includes(row.version), "Managed native plugin installation is missing");
|
|
37186
|
-
const after =
|
|
37209
|
+
const after = lstatSync22(cacheRoot);
|
|
37187
37210
|
safe5(cacheRoot);
|
|
37188
37211
|
pluginNeed(before.dev === after.dev && before.ino === after.ino && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs, "Managed cache version membership changed during verification");
|
|
37189
37212
|
}
|
|
@@ -37198,8 +37221,8 @@ var init_plugin_discovery = __esm(() => {
|
|
|
37198
37221
|
|
|
37199
37222
|
// src/lib/claude-marketplace-registry.ts
|
|
37200
37223
|
import { createHash as createHash22 } from "crypto";
|
|
37201
|
-
import { closeSync as closeSync18, constants as constants16, fstatSync as fstatSync18, lstatSync as
|
|
37202
|
-
import { basename as
|
|
37224
|
+
import { closeSync as closeSync18, constants as constants16, fstatSync as fstatSync18, lstatSync as lstatSync23, openSync as openSync18, readSync as readSync12 } from "fs";
|
|
37225
|
+
import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute21, resolve as resolve21 } from "path";
|
|
37203
37226
|
function need10(value, reason2) {
|
|
37204
37227
|
if (!value)
|
|
37205
37228
|
throw new Error(`Claude marketplace registry ${reason2}`);
|
|
@@ -37209,19 +37232,19 @@ function absolutePath4(value) {
|
|
|
37209
37232
|
}
|
|
37210
37233
|
function parents2(path) {
|
|
37211
37234
|
const result = [];
|
|
37212
|
-
for (let at =
|
|
37213
|
-
const stat2 =
|
|
37235
|
+
for (let at = dirname21(path);; at = dirname21(at)) {
|
|
37236
|
+
const stat2 = lstatSync23(at, { bigint: true });
|
|
37214
37237
|
need10(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
37215
37238
|
result.push([at, stat2]);
|
|
37216
|
-
if (at ===
|
|
37239
|
+
if (at === dirname21(at))
|
|
37217
37240
|
return result;
|
|
37218
37241
|
}
|
|
37219
37242
|
}
|
|
37220
37243
|
function readRegistry2(path, budget2) {
|
|
37221
37244
|
absolutePath4(path);
|
|
37222
|
-
need10(
|
|
37245
|
+
need10(basename12(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
37223
37246
|
need10(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
|
|
37224
|
-
const ancestors2 = parents2(path), initial =
|
|
37247
|
+
const ancestors2 = parents2(path), initial = lstatSync23(path, { bigint: true });
|
|
37225
37248
|
need10(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
37226
37249
|
need10(initial.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
|
|
37227
37250
|
const fd = openSync18(path, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
|
|
@@ -37236,10 +37259,10 @@ function readRegistry2(path, budget2) {
|
|
|
37236
37259
|
break;
|
|
37237
37260
|
length += count;
|
|
37238
37261
|
}
|
|
37239
|
-
const after = fstatSync18(fd, { bigint: true }), current =
|
|
37262
|
+
const after = fstatSync18(fd, { bigint: true }), current = lstatSync23(path, { bigint: true });
|
|
37240
37263
|
need10(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
|
|
37241
37264
|
for (const [ancestor, before] of ancestors2) {
|
|
37242
|
-
const now =
|
|
37265
|
+
const now = lstatSync23(ancestor, { bigint: true });
|
|
37243
37266
|
need10(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
37244
37267
|
}
|
|
37245
37268
|
budget2.remaining -= length;
|
|
@@ -37426,8 +37449,8 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
37426
37449
|
|
|
37427
37450
|
// src/lib/agent-discovery.ts
|
|
37428
37451
|
import { createHash as createHash24 } from "crypto";
|
|
37429
|
-
import { lstatSync as
|
|
37430
|
-
import { basename as
|
|
37452
|
+
import { lstatSync as lstatSync24, readFileSync as readFileSync18, readdirSync as readdirSync9, realpathSync as realpathSync8 } from "fs";
|
|
37453
|
+
import { basename as basename13, dirname as dirname22, isAbsolute as isAbsolute22, join as join31, relative as relative7, resolve as resolve22, sep as sep11 } from "path";
|
|
37431
37454
|
import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
|
|
37432
37455
|
function discoveryExecutable(agent) {
|
|
37433
37456
|
const command = DISCOVERY_RUNTIME_COMMANDS[agent];
|
|
@@ -37450,10 +37473,10 @@ function parseConfig(text2, path, toml = false) {
|
|
|
37450
37473
|
function safe6(path) {
|
|
37451
37474
|
if (!isAbsolute22(path) || path.includes("\x00"))
|
|
37452
37475
|
throw new Error("Expected an absolute native discovery path");
|
|
37453
|
-
for (let cursor = path;; cursor =
|
|
37454
|
-
if (
|
|
37476
|
+
for (let cursor = path;; cursor = dirname22(cursor)) {
|
|
37477
|
+
if (lstatSync24(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
37455
37478
|
throw new Error(`Refusing symlink native discovery input: ${cursor}`);
|
|
37456
|
-
if (
|
|
37479
|
+
if (dirname22(cursor) === cursor)
|
|
37457
37480
|
break;
|
|
37458
37481
|
}
|
|
37459
37482
|
}
|
|
@@ -37461,19 +37484,19 @@ function read(path, changes) {
|
|
|
37461
37484
|
safe6(path);
|
|
37462
37485
|
if (changes?.has(path))
|
|
37463
37486
|
return changes.get(path);
|
|
37464
|
-
const stat2 =
|
|
37487
|
+
const stat2 = lstatSync24(path, { throwIfNoEntry: false });
|
|
37465
37488
|
if (!stat2)
|
|
37466
37489
|
return null;
|
|
37467
37490
|
if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
|
|
37468
37491
|
throw new Error(`Unsupported or oversized native discovery input: ${path}`);
|
|
37469
|
-
return
|
|
37492
|
+
return readFileSync18(path, "utf8");
|
|
37470
37493
|
}
|
|
37471
37494
|
function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
|
|
37472
37495
|
const enabledIds = Object.entries(config2.enabledPlugins ?? {}).filter(([, enabled]) => enabled === true).map(([id]) => id);
|
|
37473
37496
|
if (enabledIds.length === 0)
|
|
37474
37497
|
return;
|
|
37475
|
-
const registryPath = canonical9(
|
|
37476
|
-
const cacheAliasRoot =
|
|
37498
|
+
const registryPath = canonical9(join31(home, ".claude/plugins/installed_plugins.json"));
|
|
37499
|
+
const cacheAliasRoot = join31(home, ".claude/plugins/cache");
|
|
37477
37500
|
const cacheRoot = canonical9(cacheAliasRoot);
|
|
37478
37501
|
const registryText = read(registryPath);
|
|
37479
37502
|
if (registryText === null)
|
|
@@ -37494,7 +37517,7 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
|
|
|
37494
37517
|
throw new Error("Reviewed Claude enabled plugin registration requires an object with an installPath string");
|
|
37495
37518
|
}
|
|
37496
37519
|
if ([cacheAliasRoot, cacheRoot].some((root) => row.installPath === root || row.installPath.startsWith(root + sep11))) {
|
|
37497
|
-
if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" ||
|
|
37520
|
+
if (!cachePath(row.installPath) || row.installPath.length > AGENT_POLICY_LIMITS.pathCharacters || row.version !== undefined && (typeof row.version !== "string" || basename13(row.installPath) !== row.version)) {
|
|
37498
37521
|
throw new Error("Reviewed Claude discovery has a malformed active cache registration");
|
|
37499
37522
|
}
|
|
37500
37523
|
if (row.scope === "user" && (row.projectPath === undefined || row.projectPath === null)) {} else if (row.scope === "project" && typeof row.projectPath === "string" && isAbsolute22(row.projectPath) && resolve22(row.projectPath) === row.projectPath && row.projectPath.length <= AGENT_POLICY_LIMITS.pathCharacters) {} else
|
|
@@ -37515,11 +37538,11 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
|
|
|
37515
37538
|
};
|
|
37516
37539
|
for (const root of activeRoots) {
|
|
37517
37540
|
safe6(root);
|
|
37518
|
-
const rootStat =
|
|
37541
|
+
const rootStat = lstatSync24(root, { throwIfNoEntry: false });
|
|
37519
37542
|
if (!rootStat?.isDirectory() || realpathSync8(root) !== root)
|
|
37520
37543
|
throw new Error("Reviewed Claude active cache plugin root is missing or unsafe");
|
|
37521
|
-
const manifestPath =
|
|
37522
|
-
const manifestStat =
|
|
37544
|
+
const manifestPath = join31(root, ".claude-plugin/plugin.json");
|
|
37545
|
+
const manifestStat = lstatSync24(manifestPath, { throwIfNoEntry: false });
|
|
37523
37546
|
let manifest;
|
|
37524
37547
|
if (manifestStat) {
|
|
37525
37548
|
if (!manifestStat.isFile())
|
|
@@ -37534,8 +37557,8 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
|
|
|
37534
37557
|
} else if (!review.sources.some((source) => source.path === manifestPath && source.hashMode === "path-bytes" && source.sha256 !== null && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined)) {
|
|
37535
37558
|
throw new Error("Reviewed Claude active cache plugin manifest absence requires a path-bytes witness");
|
|
37536
37559
|
}
|
|
37537
|
-
const roots = new Set([
|
|
37538
|
-
if (
|
|
37560
|
+
const roots = new Set([join31(root, "skills")]);
|
|
37561
|
+
if (lstatSync24(join31(root, "SKILL.md"), { throwIfNoEntry: false })?.isFile())
|
|
37539
37562
|
roots.add(root);
|
|
37540
37563
|
const declared = manifest?.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
|
|
37541
37564
|
if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
|
|
@@ -37544,13 +37567,13 @@ function assertReviewedClaudeCacheClosures(home, config2, review, canonical9) {
|
|
|
37544
37567
|
const path = resolve22(root, value);
|
|
37545
37568
|
if (path !== root && !path.startsWith(root + sep11))
|
|
37546
37569
|
throw new Error("Reviewed Claude active cache plugin skill path escapes its root");
|
|
37547
|
-
roots.add(path.endsWith(`${sep11}SKILL.md`) ?
|
|
37570
|
+
roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname22(path) : path);
|
|
37548
37571
|
}
|
|
37549
37572
|
for (const skillRoot of roots)
|
|
37550
37573
|
if (!review.roots.includes(skillRoot))
|
|
37551
37574
|
throw new Error("Reviewed Claude active cache plugin skill root is not covered");
|
|
37552
|
-
const hooksPath =
|
|
37553
|
-
const hooksStat =
|
|
37575
|
+
const hooksPath = join31(root, "hooks/hooks.json");
|
|
37576
|
+
const hooksStat = lstatSync24(hooksPath, { throwIfNoEntry: false });
|
|
37554
37577
|
if (hooksStat) {
|
|
37555
37578
|
if (!hooksStat.isFile())
|
|
37556
37579
|
throw new Error("Reviewed Claude plugin hook manifest is unsupported");
|
|
@@ -37688,18 +37711,18 @@ function absentCodexSkillRoots(binding, tolerance) {
|
|
|
37688
37711
|
return [];
|
|
37689
37712
|
if (binding.agent !== "codex" || !Array.isArray(controls) || controls.length > 4096)
|
|
37690
37713
|
throw new Error("Invalid disabled Codex discovery proof");
|
|
37691
|
-
if (binding.method !== "reviewed" || controls.every((control) =>
|
|
37714
|
+
if (binding.method !== "reviewed" || controls.every((control) => lstatSync24(control.pluginParent, { throwIfNoEntry: false })))
|
|
37692
37715
|
return [];
|
|
37693
|
-
const cache =
|
|
37716
|
+
const cache = dirname22(dirname22(controls[0].pluginParent)), config2 = join31(dirname22(dirname22(cache)), "config.toml");
|
|
37694
37717
|
const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
37695
37718
|
if (!source || !codexConfigWitnessCurrent(source, tolerance))
|
|
37696
37719
|
throw new Error("Missing current disabled Codex configuration witness");
|
|
37697
37720
|
const rules = Bun.TOML.parse(read(config2)).skills?.config ?? [];
|
|
37698
37721
|
return [...new Set(controls.map((control) => control.pluginParent))].filter((parent) => !codexDirectHookSelects(cache, parent) && absentDisabledCodexPluginParent(cache, parent, controls, rules));
|
|
37699
37722
|
}
|
|
37700
|
-
function codexDirectHookSelects(cache, root, configPath =
|
|
37701
|
-
const codex =
|
|
37702
|
-
const hooks = read(
|
|
37723
|
+
function codexDirectHookSelects(cache, root, configPath = join31(dirname22(dirname22(cache)), "config.toml")) {
|
|
37724
|
+
const codex = dirname22(configPath), config2 = Bun.TOML.parse(read(configPath) ?? "");
|
|
37725
|
+
const hooks = read(join31(codex, "hooks.json"));
|
|
37703
37726
|
if (hooks !== null)
|
|
37704
37727
|
hashNativeJsonControls(hooks);
|
|
37705
37728
|
return JSON.stringify(config2.hooks ?? {}).includes(root) || hooks !== null && JSON.stringify(JSON.parse(hooks)).includes(root);
|
|
@@ -37711,7 +37734,7 @@ function retiredCodexRoots(binding, tolerance) {
|
|
|
37711
37734
|
const controls = binding.codexDisabledPluginSkills;
|
|
37712
37735
|
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)
|
|
37713
37736
|
throw new Error("Invalid retired Codex materialization proof");
|
|
37714
|
-
const cache =
|
|
37737
|
+
const cache = dirname22(dirname22(controls[0].pluginParent)), config2 = join31(dirname22(dirname22(cache)), "config.toml");
|
|
37715
37738
|
const source = binding.sources.find((source2) => source2.path === config2 && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
37716
37739
|
if (!source || !codexConfigWitnessCurrent(source, tolerance))
|
|
37717
37740
|
throw new Error("Missing current retired Codex configuration witness");
|
|
@@ -37719,7 +37742,7 @@ function retiredCodexRoots(binding, tolerance) {
|
|
|
37719
37742
|
if ((proof.parents ?? []).some((parent) => codexDirectHookSelects(cache, parent) || !reviewedDisabledCodexPluginParent(cache, parent, controls, rules)) || !reviewedCodexPluginCapabilitiesUnchanged(cache, controls, (path) => read(path), rules))
|
|
37720
37743
|
throw new Error("Retired Codex parent capabilities changed");
|
|
37721
37744
|
for (const root of proof.roots) {
|
|
37722
|
-
const manifest = binding.sources.find((source2) => source2.path ===
|
|
37745
|
+
const manifest = binding.sources.find((source2) => source2.path === join31(root, ".codex-plugin/plugin.json") && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined && [undefined, "bytes"].includes(source2.hashMode));
|
|
37723
37746
|
if (!manifest || codexDirectHookSelects(cache, root) || !reviewedRetiredCodexRoot(cache, root, controls, rules, (path) => read(path), true))
|
|
37724
37747
|
throw new Error("Retired Codex materialization changed");
|
|
37725
37748
|
}
|
|
@@ -37730,7 +37753,7 @@ function retainableAbsentWitness(source) {
|
|
|
37730
37753
|
return null;
|
|
37731
37754
|
if ([undefined, "bytes"].includes(source.hashMode))
|
|
37732
37755
|
return "bytes";
|
|
37733
|
-
if (source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(
|
|
37756
|
+
if (source.hashMode === "claude-plugin-manifest-v1" && source.sha256 !== null && source.path.endsWith(join31(sep11, ".claude-plugin", "plugin.json")))
|
|
37734
37757
|
return "claude-plugin-manifest-v1";
|
|
37735
37758
|
if (source.hashMode === CLAUDE_ORPHAN_MARKER_MODE && source.sha256 !== null && isClaudePluginCacheOrphanMarker(source.path))
|
|
37736
37759
|
return CLAUDE_ORPHAN_MARKER_MODE;
|
|
@@ -37755,11 +37778,11 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
37755
37778
|
const cache = source.path.slice(0, at + marker.length - 1), parts = source.path.slice(at + marker.length).split(sep11);
|
|
37756
37779
|
if (parts.length < 4 || parts.slice(0, 3).some((part) => !part || part === "." || part === ".."))
|
|
37757
37780
|
continue;
|
|
37758
|
-
const root =
|
|
37781
|
+
const root = join31(cache, ...parts.slice(0, 3));
|
|
37759
37782
|
safe6(root);
|
|
37760
|
-
if (
|
|
37783
|
+
if (lstatSync24(root, { throwIfNoEntry: false }))
|
|
37761
37784
|
continue;
|
|
37762
|
-
const claude =
|
|
37785
|
+
const claude = dirname22(dirname22(cache)), settings = join31(claude, "settings.json"), registry2 = join31(claude, "plugins/installed_plugins.json");
|
|
37763
37786
|
const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
|
|
37764
37787
|
const configSource = full(settings), registrySource = full(registry2);
|
|
37765
37788
|
if (!configSource || !registrySource || projected(configSource) !== configSource.sha256 || projected(registrySource) !== registrySource.sha256)
|
|
@@ -37802,9 +37825,9 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
37802
37825
|
if (!targetValid || !targetScopes.has("user\x00"))
|
|
37803
37826
|
continue;
|
|
37804
37827
|
const active = rows[0]?.installPath;
|
|
37805
|
-
if (typeof active !== "string" || rows[0]?.version !==
|
|
37828
|
+
if (typeof active !== "string" || rows[0]?.version !== basename13(active) || dirname22(active) !== dirname22(root) || active === root || !lstatSync24(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync8(active) !== active)
|
|
37806
37829
|
continue;
|
|
37807
|
-
const activeManifest = full(
|
|
37830
|
+
const activeManifest = full(join31(active, ".claude-plugin/plugin.json"));
|
|
37808
37831
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
37809
37832
|
continue;
|
|
37810
37833
|
result.add(root);
|
|
@@ -37815,10 +37838,10 @@ function codexSemanticCacheSourceRole(source, cacheRoot, parents3, hookParents =
|
|
|
37815
37838
|
if (!isAbsolute22(source.path) || resolve22(source.path) !== source.path || /[\x00-\x1f\x7f]/.test(source.path) || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.reviewArtifact !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes")
|
|
37816
37839
|
return false;
|
|
37817
37840
|
const parts = relative7(cacheRoot, source.path).split(sep11);
|
|
37818
|
-
if (parts.length < 3 || !parents3.includes(
|
|
37841
|
+
if (parts.length < 3 || !parents3.includes(join31(cacheRoot, parts[0], parts[1])))
|
|
37819
37842
|
return false;
|
|
37820
37843
|
const tail = parts.slice(3).join("/");
|
|
37821
|
-
const parent =
|
|
37844
|
+
const parent = join31(cacheRoot, parts[0], parts[1]);
|
|
37822
37845
|
return parts.length === 5 && tail === ".codex-plugin/plugin.json" && source.sha256 !== null || parts.length === 4 && [".app.json", ".mcp.json"].includes(tail) && source.sha256 !== null || parts.length === 5 && tail === "hooks/hooks.json" && hookParents.includes(parent) && source.sha256 !== null || source.sha256 === null && (parts.length === 4 && tail === "SKILL.md" || parts.length === 5 && tail === "hooks/hooks.json");
|
|
37823
37846
|
}
|
|
37824
37847
|
function codexSemanticCacheDirectoryRole(path, cacheRoot) {
|
|
@@ -37827,9 +37850,9 @@ function codexSemanticCacheDirectoryRole(path, cacheRoot) {
|
|
|
37827
37850
|
function assertCodexSemanticCacheHookSafety(cacheRoot, parents3, configPath, hookRootAlias = null) {
|
|
37828
37851
|
const selectionRoots = [cacheRoot, ...parents3];
|
|
37829
37852
|
if (hookRootAlias !== null) {
|
|
37830
|
-
if (!hookRootAlias || Object.keys(hookRootAlias).length !== 2 || [hookRootAlias.alias, hookRootAlias.target].some((path) => typeof path !== "string" || !isAbsolute22(path) || resolve22(path) !== path || /[\x00-\x1f\x7f]/.test(path)) || hookRootAlias.target !==
|
|
37853
|
+
if (!hookRootAlias || Object.keys(hookRootAlias).length !== 2 || [hookRootAlias.alias, hookRootAlias.target].some((path) => typeof path !== "string" || !isAbsolute22(path) || resolve22(path) !== path || /[\x00-\x1f\x7f]/.test(path)) || hookRootAlias.target !== dirname22(configPath) || cacheRoot !== join31(hookRootAlias.target, "plugins/cache") || !lstatSync24(hookRootAlias.alias, { throwIfNoEntry: false })?.isSymbolicLink() || realpathSync8(hookRootAlias.alias) !== hookRootAlias.target || realpathSync8(hookRootAlias.target) !== hookRootAlias.target)
|
|
37831
37854
|
throw new Error("Reviewed semantic cache hook alias changed");
|
|
37832
|
-
selectionRoots.push(...selectionRoots.map((root) =>
|
|
37855
|
+
selectionRoots.push(...selectionRoots.map((root) => join31(hookRootAlias.alias, relative7(hookRootAlias.target, root))));
|
|
37833
37856
|
}
|
|
37834
37857
|
selectionRoots.push("plugins/cache");
|
|
37835
37858
|
if (selectionRoots.some((parent) => codexDirectHookSelects(cacheRoot, parent, configPath)))
|
|
@@ -37849,7 +37872,7 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
|
|
|
37849
37872
|
if (binding.agent !== "codex" || binding.method !== "reviewed" || !controls?.length || proof.schema !== "hasna.codex-semantic-cache-discovery.v1" || !/^[a-f0-9]{64}$/.test(proof.previousPolicySha256) || !Array.isArray(proof.appOnlyParents) || !Array.isArray(proof.supersededSources) || !Array.isArray(proof.supersededDirectories))
|
|
37850
37873
|
throw new Error("Invalid Codex semantic cache discovery proof");
|
|
37851
37874
|
const cacheRoot = proof.witness.cacheRoot;
|
|
37852
|
-
if (controls.some((control) =>
|
|
37875
|
+
if (controls.some((control) => dirname22(dirname22(control.pluginParent)) !== cacheRoot))
|
|
37853
37876
|
throw new Error("Codex semantic cache names another enrolled cache");
|
|
37854
37877
|
const reviewedHookParents = proof.reviewedHookParents ?? [];
|
|
37855
37878
|
if (!Array.isArray(reviewedHookParents) || reviewedHookParents.length > 4096 || reviewedHookParents.some((parent) => !parent || !(parent.installation === "remote-receipt" && Object.keys(parent).sort().join(",") === "installation,namespace,pluginId,pluginParent,remotePluginId,role" && typeof parent.remotePluginId === "string" || parent.installation === "local-marketplace" && Object.keys(parent).sort().join(",") === "installation,marketplaceSha256,marketplaceSourcePath,namespace,pluginId,pluginParent,role" && typeof parent.marketplaceSourcePath === "string" && /^[a-f0-9]{64}$/.test(parent.marketplaceSha256 ?? "")) || parent.role !== "reviewed-hook" || typeof parent.pluginId !== "string" || typeof parent.namespace !== "string" || typeof parent.pluginParent !== "string") || new Set(reviewedHookParents.map((parent) => parent.pluginParent)).size !== reviewedHookParents.length || !isDeepStrictEqual5((proof.witness.hookParents ?? []).map(({ manifestSha256: _manifest, hooksSha256: _hooks, receiptSha256: _receipt, ...parent }) => parent), reviewedHookParents)) {
|
|
@@ -37865,7 +37888,7 @@ function verifyCodexSemanticCacheDiscovery(binding, reviewedRootAliases) {
|
|
|
37865
37888
|
if (!directories.length || !isDeepStrictEqual5(sources, proof.supersededSources) || !isDeepStrictEqual5(directories, proof.supersededDirectories))
|
|
37866
37889
|
throw new Error("Codex semantic cache provenance changed");
|
|
37867
37890
|
const configPath = proof.configPath;
|
|
37868
|
-
if (!isAbsolute22(configPath) || resolve22(configPath) !== configPath ||
|
|
37891
|
+
if (!isAbsolute22(configPath) || resolve22(configPath) !== configPath || basename13(configPath) !== "config.toml" || /[\x00-\x1f\x7f]/.test(configPath))
|
|
37869
37892
|
throw new Error("Invalid semantic cache configuration source");
|
|
37870
37893
|
const configSource = binding.sources.find((source) => source.path === configPath && source.sha256 !== null && source.format === undefined && source.fields === undefined);
|
|
37871
37894
|
if (!configSource || projected(configSource) !== configSource.sha256)
|
|
@@ -37898,7 +37921,7 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
|
|
|
37898
37921
|
const projection = binding.codexRetiredMaterializations.directories.filter((directory) => !semanticDirectory(directory.path));
|
|
37899
37922
|
if (projection.length !== ordinary.length || projection.some((item, index) => item.path !== ordinary[index]?.path))
|
|
37900
37923
|
throw new Error("Missing retired Codex directory projection");
|
|
37901
|
-
const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !
|
|
37924
|
+
const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync24(parent, { throwIfNoEntry: false }))];
|
|
37902
37925
|
if (projection.every((item) => Array.isArray(item.entries)))
|
|
37903
37926
|
verifyDiscoveryDirectoryProjection(projection, omitted, witnessTolerance);
|
|
37904
37927
|
else {
|
|
@@ -37915,7 +37938,7 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
|
|
|
37915
37938
|
verifyDiscoveryDirectories(ordinary, [], witnessTolerance);
|
|
37916
37939
|
verifyDiscoveryDirectories(projected2, installationRoots, witnessTolerance);
|
|
37917
37940
|
}
|
|
37918
|
-
const absentRoots = [...absentCodexSkillRoots(binding, witnessTolerance), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !
|
|
37941
|
+
const absentRoots = [...absentCodexSkillRoots(binding, witnessTolerance), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root) => !lstatSync24(root, { throwIfNoEntry: false }))];
|
|
37919
37942
|
const budget2 = discoveryByteBudget();
|
|
37920
37943
|
for (const source of binding.sources) {
|
|
37921
37944
|
assertMarketplaceBinding(binding, source);
|
|
@@ -37953,12 +37976,12 @@ function verifyAgentDiscovery(binding, codexRecovery, reviewedRootAliases, witne
|
|
|
37953
37976
|
safe6(root);
|
|
37954
37977
|
for (const root of absentRoots) {
|
|
37955
37978
|
safe6(root);
|
|
37956
|
-
if (
|
|
37979
|
+
if (lstatSync24(root, { throwIfNoEntry: false }))
|
|
37957
37980
|
throw new Error("Retired native materialization changed during discovery verification");
|
|
37958
37981
|
}
|
|
37959
37982
|
}
|
|
37960
37983
|
function claudeControlSource(source) {
|
|
37961
|
-
return CLAUDE_CONTROL_WITNESS_MODES.has(source.hashMode ?? "") || CLAUDE_CONTROL_FILES.has(
|
|
37984
|
+
return CLAUDE_CONTROL_WITNESS_MODES.has(source.hashMode ?? "") || CLAUDE_CONTROL_FILES.has(basename13(source.path)) && !source.path.includes(`${sep11}.claude${sep11}plugins${sep11}cache${sep11}`);
|
|
37962
37985
|
}
|
|
37963
37986
|
function retainedAbsentClaudeRoot(absentRoots, source) {
|
|
37964
37987
|
return claudeControlSource(source) ? undefined : retainedAbsentRoot(absentRoots, source);
|
|
@@ -37969,13 +37992,13 @@ function codexInstallationRoots(binding) {
|
|
|
37969
37992
|
return [];
|
|
37970
37993
|
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)
|
|
37971
37994
|
throw new Error("Invalid native installation input proof");
|
|
37972
|
-
const cache =
|
|
37973
|
-
const config2 =
|
|
37995
|
+
const cache = dirname22(dirname22(proof.plugins[0].pluginParent));
|
|
37996
|
+
const config2 = join31(dirname22(dirname22(cache)), "config.toml"), home = dirname22(dirname22(dirname22(cache)));
|
|
37974
37997
|
const configSource = binding.sources.find((source) => source.path === config2 && source.sha256 !== null && (!source.format || source.format === "toml" && source.fields?.includes("plugins")));
|
|
37975
|
-
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) =>
|
|
37976
|
-
if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep11) || input2.sourceRoot.startsWith(root + sep11)) || binding.sources.some((source) =>
|
|
37998
|
+
const nativeRoots = NATIVE_SKILL_ROOTS.filter(([agent]) => agent === "codex").map(([, path]) => join31(home, path));
|
|
37999
|
+
if (!configSource || proof.plugins.some((input2) => nativeRoots.some((root) => root === input2.sourceRoot || root.startsWith(input2.sourceRoot + sep11) || input2.sourceRoot.startsWith(root + sep11)) || binding.sources.some((source) => basename13(source.path) === "config.toml" && (source.path === input2.sourceRoot || source.path.startsWith(input2.sourceRoot + sep11)))))
|
|
37977
38000
|
throw new Error("Native installation input overlaps configuration or loading roots");
|
|
37978
|
-
if (proof.plugins.some((input2) =>
|
|
38001
|
+
if (proof.plugins.some((input2) => dirname22(dirname22(input2.pluginParent)) !== cache || !binding.sources.some((source) => source.path === join31(input2.sourceRoot, ".codex-plugin/plugin.json") && source.sha256 !== null && source.format === undefined && source.fields === undefined)))
|
|
37979
38002
|
throw new Error("Missing native installation input source witness");
|
|
37980
38003
|
return reviewedCodexPluginSourceRoots(cache, proof.plugins, (path) => {
|
|
37981
38004
|
const text2 = read(path);
|
|
@@ -37991,13 +38014,13 @@ function assertMarketplaceBinding(binding, source) {
|
|
|
37991
38014
|
throw new Error("Provider executable witnesses require explicit reviewed Codex V6");
|
|
37992
38015
|
if (source.hashMode === "codex-settings-v6" && (new Set(binding.sources.map((row) => row.path)).size !== binding.sources.length || !Array.isArray(source.hookSources) || source.hookSources.some((hook) => !binding.sources.some((row) => row.path === hook.path && row.sha256 === hook.sha256 && [undefined, "bytes"].includes(row.hashMode) && row.format === undefined && row.fields === undefined))))
|
|
37993
38016
|
throw new Error("Missing independently reviewed Codex hook source population");
|
|
37994
|
-
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" ||
|
|
38017
|
+
if (source.hashMode === "claude-plugin-manifest-v1" && (binding.agent !== "claude" || basename13(source.path) !== "plugin.json" || !source.path.endsWith(join31(sep11, ".claude-plugin", "plugin.json"))))
|
|
37995
38018
|
throw new Error("Claude plugin manifest witnesses require Claude plugin discovery");
|
|
37996
|
-
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" ||
|
|
38019
|
+
if (source.hashMode === "sumi-settings-v1" && (binding.agent !== "sumi" || binding.method !== "reviewed" || basename13(source.path) !== "sumi.json"))
|
|
37997
38020
|
throw new Error("Sumi settings witnesses require explicit reviewed Sumi configuration");
|
|
37998
|
-
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5" || source.hashMode === "codex-settings-v6")) && (binding.agent !== "codex" || binding.method !== "reviewed" ||
|
|
38021
|
+
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2" || (source.hashMode === "codex-settings-v3" || source.hashMode === "codex-settings-v4" || source.hashMode === "codex-settings-v5" || source.hashMode === "codex-settings-v6")) && (binding.agent !== "codex" || binding.method !== "reviewed" || basename13(source.path) !== "config.toml"))
|
|
37999
38022
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
38000
|
-
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" ||
|
|
38023
|
+
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" || basename13(source.path) !== "settings.json"))
|
|
38001
38024
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
38002
38025
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
38003
38026
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
@@ -38005,11 +38028,11 @@ function assertMarketplaceBinding(binding, source) {
|
|
|
38005
38028
|
throw new Error("Claude marketplace entry witnesses require explicit reviewed Claude discovery of one named entry");
|
|
38006
38029
|
}
|
|
38007
38030
|
function hashReviewedExecutable(path, budget2) {
|
|
38008
|
-
const before =
|
|
38031
|
+
const before = lstatSync24(path, { bigint: true });
|
|
38009
38032
|
if (before.size < 0n || before.size > BigInt(budget2.remaining))
|
|
38010
38033
|
throw new Error("Discovery aggregate executable byte limit exceeded");
|
|
38011
38034
|
const digest3 = pluginExecutableDigest(path).slice(7);
|
|
38012
|
-
const after =
|
|
38035
|
+
const after = lstatSync24(path, { bigint: true });
|
|
38013
38036
|
for (const key2 of ["dev", "ino", "size", "mode", "uid", "gid", "nlink", "mtimeNs", "ctimeNs"]) {
|
|
38014
38037
|
if (before[key2] !== after[key2])
|
|
38015
38038
|
throw new Error("Discovery executable changed during budgeted capture");
|
|
@@ -38020,7 +38043,7 @@ function hashReviewedExecutable(path, budget2) {
|
|
|
38020
38043
|
function agentDiscoveryConfigPath(home, agent) {
|
|
38021
38044
|
if (agent === "sumi")
|
|
38022
38045
|
return sumiConfigPath(home);
|
|
38023
|
-
return
|
|
38046
|
+
return join31(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
|
|
38024
38047
|
}
|
|
38025
38048
|
function resolveAgentDiscovery(options) {
|
|
38026
38049
|
const canonical9 = options.canonical ?? resolve22, home = resolve22(options.home), agent = options.agent;
|
|
@@ -38044,42 +38067,42 @@ function resolveAgentDiscovery(options) {
|
|
|
38044
38067
|
const review = options.reviewed?.agents.find((item) => item.agent === agent);
|
|
38045
38068
|
if (agent === "sumi") {
|
|
38046
38069
|
const directory = sumiConfigDirectory(home);
|
|
38047
|
-
if (witness(
|
|
38070
|
+
if (witness(join31(directory, "sumi.jsonc")) !== null)
|
|
38048
38071
|
unresolved("JSONC configuration requires a supported format adapter");
|
|
38049
|
-
for (const root of [directory,
|
|
38072
|
+
for (const root of [directory, join31(home, ".claude"), join31(home, ".agents")])
|
|
38050
38073
|
for (const name of ["skill", "skills"])
|
|
38051
|
-
roots.add(canonical9(
|
|
38074
|
+
roots.add(canonical9(join31(root, name)));
|
|
38052
38075
|
if (config2.skills !== undefined && (!Array.isArray(config2.skills) || config2.skills.some((path) => typeof path !== "string")))
|
|
38053
38076
|
unresolved("skills must be a string array");
|
|
38054
38077
|
for (const value of config2.skills ?? []) {
|
|
38055
38078
|
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute22(value) || value.startsWith("~/")))
|
|
38056
38079
|
unresolved("remote or relative skill sources need a dedicated discovery adapter");
|
|
38057
|
-
roots.add(canonical9(value.startsWith("~/") ?
|
|
38080
|
+
roots.add(canonical9(value.startsWith("~/") ? join31(home, value.slice(2)) : value));
|
|
38058
38081
|
}
|
|
38059
38082
|
for (const key2 of ["plugin", "plugins"])
|
|
38060
38083
|
if (config2[key2] !== undefined && !Array.isArray(config2[key2]))
|
|
38061
38084
|
unresolved(`${key2} must be an array`);
|
|
38062
|
-
const plugins = [
|
|
38085
|
+
const plugins = [join31(directory, "plugin"), join31(directory, "plugins")];
|
|
38063
38086
|
for (const path of plugins) {
|
|
38064
38087
|
safe6(path);
|
|
38065
|
-
if (
|
|
38066
|
-
for (const name of
|
|
38088
|
+
if (lstatSync24(path, { throwIfNoEntry: false })?.isDirectory())
|
|
38089
|
+
for (const name of readdirSync9(path).sort()) {
|
|
38067
38090
|
if (name === "skills-cli.js" && path === plugins[1])
|
|
38068
38091
|
continue;
|
|
38069
|
-
const target =
|
|
38070
|
-
if (!
|
|
38092
|
+
const target = join31(path, name);
|
|
38093
|
+
if (!lstatSync24(target).isFile())
|
|
38071
38094
|
unresolved("local plugin packages need a dedicated discovery adapter");
|
|
38072
38095
|
witness(target);
|
|
38073
38096
|
}
|
|
38074
38097
|
}
|
|
38075
38098
|
for (const root of roots) {
|
|
38076
38099
|
safe6(root);
|
|
38077
|
-
if (
|
|
38100
|
+
if (lstatSync24(root, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(root).some((name) => name.endsWith(".md")))
|
|
38078
38101
|
unresolved("flat markdown skills require a dedicated native migration adapter");
|
|
38079
38102
|
}
|
|
38080
38103
|
}
|
|
38081
38104
|
if (agent === "hermes") {
|
|
38082
|
-
const profile = witness(
|
|
38105
|
+
const profile = witness(join31(home, ".hermes/active_profile"));
|
|
38083
38106
|
if (profile?.trim() && profile.trim() !== "default")
|
|
38084
38107
|
unresolved("a non-default profile is active");
|
|
38085
38108
|
const declared = config2.skills?.external_dirs ?? [], paths = typeof declared === "string" ? [declared] : declared;
|
|
@@ -38093,7 +38116,7 @@ function resolveAgentDiscovery(options) {
|
|
|
38093
38116
|
continue;
|
|
38094
38117
|
if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
|
|
38095
38118
|
unresolved("user-specific tilde expansion requires a separate discovery adapter");
|
|
38096
|
-
const path = normalized === "~" ? home : normalized.startsWith("~/") ?
|
|
38119
|
+
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join31(home, normalized.slice(2)) : resolve22(home, ".hermes", normalized);
|
|
38097
38120
|
safe6(path);
|
|
38098
38121
|
roots.add(path);
|
|
38099
38122
|
}
|
|
@@ -38102,24 +38125,24 @@ function resolveAgentDiscovery(options) {
|
|
|
38102
38125
|
const executable = options.executable === undefined ? discoveryExecutable(agent) : options.executable;
|
|
38103
38126
|
if (executable) {
|
|
38104
38127
|
let packageRoot;
|
|
38105
|
-
for (let directory =
|
|
38106
|
-
const path =
|
|
38128
|
+
for (let directory = dirname22(executable.target), depth = 0;depth < 8; directory = dirname22(directory), depth++) {
|
|
38129
|
+
const path = join31(directory, "package.json"), raw = read(path);
|
|
38107
38130
|
if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
|
|
38108
38131
|
packageRoot = directory;
|
|
38109
38132
|
witness(path);
|
|
38110
38133
|
break;
|
|
38111
38134
|
}
|
|
38112
|
-
if (
|
|
38135
|
+
if (dirname22(directory) === directory)
|
|
38113
38136
|
break;
|
|
38114
38137
|
}
|
|
38115
38138
|
if (!packageRoot)
|
|
38116
38139
|
unresolved("installed Gemini package layout is not recognized");
|
|
38117
|
-
const builtinRoot =
|
|
38140
|
+
const builtinRoot = join31(packageRoot, "bundle/builtin");
|
|
38118
38141
|
safe6(builtinRoot);
|
|
38119
|
-
if (!
|
|
38142
|
+
if (!lstatSync24(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
|
|
38120
38143
|
unresolved("installed Gemini builtin root is missing");
|
|
38121
|
-
for (const name of
|
|
38122
|
-
const text2 = witness(
|
|
38144
|
+
for (const name of readdirSync9(builtinRoot).sort()) {
|
|
38145
|
+
const text2 = witness(join31(builtinRoot, name, "SKILL.md"));
|
|
38123
38146
|
const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
|
|
38124
38147
|
if (!match?.[1] || builtinNames.includes(match[1]))
|
|
38125
38148
|
unresolved("installed Gemini builtin name is missing or ambiguous");
|
|
@@ -38165,10 +38188,10 @@ function resolveAgentDiscovery(options) {
|
|
|
38165
38188
|
if (agent === "claude" && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && source.reviewArtifact === undefined && [undefined, "bytes", "path-bytes"].includes(source.hashMode) && isClaudePluginCacheOrphanMarker(source.path)) {
|
|
38166
38189
|
return { path: source.path, hashMode: CLAUDE_ORPHAN_MARKER_MODE, sha256: hashClaudePluginCacheOrphanMarker(source.path) };
|
|
38167
38190
|
}
|
|
38168
|
-
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" ||
|
|
38191
|
+
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename13(source.path) !== "plugin.json" || !source.path.endsWith(join31(sep11, ".claude-plugin", "plugin.json")))
|
|
38169
38192
|
return source;
|
|
38170
|
-
const pluginRoot =
|
|
38171
|
-
const hookStat =
|
|
38193
|
+
const pluginRoot = dirname22(dirname22(source.path)), hooksPath = join31(pluginRoot, "hooks/hooks.json");
|
|
38194
|
+
const hookStat = lstatSync24(hooksPath, { throwIfNoEntry: false });
|
|
38172
38195
|
const text2 = read(source.path);
|
|
38173
38196
|
if (text2 === null)
|
|
38174
38197
|
throw new Error("Reviewed Claude plugin manifest is missing");
|
|
@@ -38196,7 +38219,7 @@ function resolveAgentDiscovery(options) {
|
|
|
38196
38219
|
assertReviewedClaudeCacheClosures(home, config2, review, canonical9);
|
|
38197
38220
|
for (const root of absentRoots) {
|
|
38198
38221
|
safe6(root);
|
|
38199
|
-
if (
|
|
38222
|
+
if (lstatSync24(root, { throwIfNoEntry: false }))
|
|
38200
38223
|
throw new Error("Retired native materialization changed during discovery review");
|
|
38201
38224
|
}
|
|
38202
38225
|
const combined = [...reviewedSources, ...reviewedSourcesWithManifestProjection];
|
|
@@ -38206,39 +38229,39 @@ function resolveAgentDiscovery(options) {
|
|
|
38206
38229
|
function plugin(root) {
|
|
38207
38230
|
root = canonical9(root);
|
|
38208
38231
|
safe6(root);
|
|
38209
|
-
const manifestPath =
|
|
38232
|
+
const manifestPath = join31(root, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
38210
38233
|
const raw = witness(manifestPath, undefined, undefined, agent === "claude" ? "claude-plugin-manifest-v1" : undefined);
|
|
38211
38234
|
if (raw === null)
|
|
38212
38235
|
unresolved("plugin manifest missing");
|
|
38213
38236
|
const manifest = parseConfig(raw, manifestPath);
|
|
38214
|
-
const hooks = witness(
|
|
38237
|
+
const hooks = witness(join31(root, "hooks/hooks.json"));
|
|
38215
38238
|
if (manifest.hooks !== undefined || hooks !== null)
|
|
38216
38239
|
unresolved("plugin hooks require a separate no-skill-injection review");
|
|
38217
|
-
const commands =
|
|
38240
|
+
const commands = join31(root, "commands");
|
|
38218
38241
|
safe6(commands);
|
|
38219
|
-
if (agent === "claude" && (manifest.commands !== undefined ||
|
|
38242
|
+
if (agent === "claude" && (manifest.commands !== undefined || lstatSync24(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
|
|
38220
38243
|
unresolved("legacy command discovery requires retirement or a dedicated format adapter");
|
|
38221
|
-
const rootSkill = witness(
|
|
38244
|
+
const rootSkill = witness(join31(root, "SKILL.md"));
|
|
38222
38245
|
if (rootSkill !== null)
|
|
38223
38246
|
roots.add(root);
|
|
38224
38247
|
const declared = manifest.skills === undefined ? ["./skills"] : typeof manifest.skills === "string" ? [manifest.skills] : manifest.skills;
|
|
38225
38248
|
if (!Array.isArray(declared) || declared.some((path) => typeof path !== "string"))
|
|
38226
38249
|
unresolved("unsupported plugin skill paths");
|
|
38227
38250
|
if (agent === "claude")
|
|
38228
|
-
roots.add(
|
|
38251
|
+
roots.add(join31(root, "skills"));
|
|
38229
38252
|
for (const value of declared) {
|
|
38230
38253
|
const path = resolve22(root, value);
|
|
38231
38254
|
if (path !== root && !path.startsWith(root + sep11))
|
|
38232
38255
|
unresolved("plugin skill path escapes its root");
|
|
38233
|
-
roots.add(path.endsWith(`${sep11}SKILL.md`) ?
|
|
38256
|
+
roots.add(path.endsWith(`${sep11}SKILL.md`) ? dirname22(path) : path);
|
|
38234
38257
|
}
|
|
38235
38258
|
}
|
|
38236
38259
|
if (agent === "claude") {
|
|
38237
|
-
const registrations = witness(
|
|
38238
|
-
const installed = registrations === null ? {} : parseConfig(registrations,
|
|
38239
|
-
const commands = canonical9(
|
|
38260
|
+
const registrations = witness(join31(home, ".claude/plugins/installed_plugins.json"));
|
|
38261
|
+
const installed = registrations === null ? {} : parseConfig(registrations, join31(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
38262
|
+
const commands = canonical9(join31(home, ".claude/commands"));
|
|
38240
38263
|
safe6(commands);
|
|
38241
|
-
if (
|
|
38264
|
+
if (lstatSync24(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
|
|
38242
38265
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
38243
38266
|
for (const [id, enabled] of Object.entries(config2.enabledPlugins ?? {})) {
|
|
38244
38267
|
if (enabled === false)
|
|
@@ -38260,16 +38283,16 @@ function resolveAgentDiscovery(options) {
|
|
|
38260
38283
|
const market = config2.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
|
|
38261
38284
|
if (split < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute22(market.source))
|
|
38262
38285
|
unresolved("enabled plugin marketplace is not an explicit local source");
|
|
38263
|
-
const catalogText = witness(
|
|
38286
|
+
const catalogText = witness(join31(market.source, ".agents/plugins/marketplace.json"));
|
|
38264
38287
|
if (catalogText === null)
|
|
38265
38288
|
unresolved("marketplace catalog missing");
|
|
38266
|
-
const catalog = parseConfig(catalogText,
|
|
38289
|
+
const catalog = parseConfig(catalogText, join31(market.source, ".agents/plugins/marketplace.json")), matches = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
38267
38290
|
if (matches.length !== 1 || matches[0]?.source?.source !== "local" || typeof matches[0]?.source?.path !== "string")
|
|
38268
38291
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
38269
38292
|
plugin(resolve22(market.source, matches[0].source.path));
|
|
38270
38293
|
}
|
|
38271
38294
|
} else if (agent === "opencode") {
|
|
38272
|
-
if (witness(
|
|
38295
|
+
if (witness(join31(home, ".config/opencode/opencode.jsonc")) !== null || witness(join31(home, ".config/opencode/config.json")) !== null)
|
|
38273
38296
|
unresolved("additional config layers require review");
|
|
38274
38297
|
if ((config2.plugin?.length ?? 0) > 0 || config2.skills?.urls?.length)
|
|
38275
38298
|
unresolved("external plugin or remote skill source");
|
|
@@ -38278,17 +38301,17 @@ function resolveAgentDiscovery(options) {
|
|
|
38278
38301
|
unresolved("relative or malformed added skill root");
|
|
38279
38302
|
roots.add(path);
|
|
38280
38303
|
}
|
|
38281
|
-
const localPlugins =
|
|
38304
|
+
const localPlugins = join31(home, ".config/opencode/plugins");
|
|
38282
38305
|
safe6(localPlugins);
|
|
38283
|
-
if (
|
|
38306
|
+
if (lstatSync24(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
38284
38307
|
unresolved("additional local plugin hooks require review");
|
|
38285
38308
|
} else if (agent === "sumi") {
|
|
38286
|
-
if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical9(configPath) && source.path !== canonical9(
|
|
38309
|
+
if ((config2.plugin?.length ?? 0) > 0 || (config2.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical9(configPath) && source.path !== canonical9(join31(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
|
|
38287
38310
|
unresolved("external or foreign local plugins require review");
|
|
38288
38311
|
} else if (agent === "hermes") {
|
|
38289
|
-
for (const directory of [
|
|
38312
|
+
for (const directory of [join31(home, ".hermes/plugins"), join31(home, ".hermes/hermes-agent")]) {
|
|
38290
38313
|
safe6(directory);
|
|
38291
|
-
if (
|
|
38314
|
+
if (lstatSync24(directory, { throwIfNoEntry: false }))
|
|
38292
38315
|
unresolved("installed runtime/plugin discovery requires reviewed source bindings");
|
|
38293
38316
|
}
|
|
38294
38317
|
if (Bun.which("hermes") || Object.keys(config2.plugins ?? {}).length)
|
|
@@ -38296,24 +38319,24 @@ function resolveAgentDiscovery(options) {
|
|
|
38296
38319
|
} else if (agent === "gemini") {
|
|
38297
38320
|
if (Object.keys(config2.extensions ?? {}).length || config2.skills?.paths?.length)
|
|
38298
38321
|
unresolved("custom extension or skill paths");
|
|
38299
|
-
const directory =
|
|
38322
|
+
const directory = join31(home, ".gemini/extensions");
|
|
38300
38323
|
safe6(directory);
|
|
38301
|
-
if (
|
|
38302
|
-
for (const name of
|
|
38303
|
-
const root =
|
|
38324
|
+
if (lstatSync24(directory, { throwIfNoEntry: false }))
|
|
38325
|
+
for (const name of readdirSync9(directory)) {
|
|
38326
|
+
const root = join31(directory, name);
|
|
38304
38327
|
safe6(root);
|
|
38305
|
-
if (!
|
|
38328
|
+
if (!lstatSync24(root)?.isDirectory())
|
|
38306
38329
|
continue;
|
|
38307
|
-
const raw = witness(
|
|
38330
|
+
const raw = witness(join31(root, "gemini-extension.json"));
|
|
38308
38331
|
if (raw === null)
|
|
38309
38332
|
unresolved("extension registration missing");
|
|
38310
|
-
const manifest = parseConfig(raw,
|
|
38311
|
-
if (manifest.hooks !== undefined || witness(
|
|
38333
|
+
const manifest = parseConfig(raw, join31(root, "gemini-extension.json"));
|
|
38334
|
+
if (manifest.hooks !== undefined || witness(join31(root, "hooks/hooks.json")) !== null || witness(join31(root, ".gemini-extension-install.json")) !== null)
|
|
38312
38335
|
unresolved("extension hooks or linked registration require review");
|
|
38313
|
-
roots.add(
|
|
38336
|
+
roots.add(join31(root, "skills"));
|
|
38314
38337
|
}
|
|
38315
38338
|
}
|
|
38316
|
-
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([
|
|
38339
|
+
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join31(home, ".hermes/plugins"), join31(home, ".hermes/hermes-agent")].map((path) => canonical9(path))) } : {} };
|
|
38317
38340
|
}
|
|
38318
38341
|
var DISCOVERY_RUNTIME_COMMANDS, realpathOrNull = (path) => {
|
|
38319
38342
|
try {
|
|
@@ -38358,9 +38381,9 @@ var init_agent_discovery = __esm(() => {
|
|
|
38358
38381
|
});
|
|
38359
38382
|
|
|
38360
38383
|
// src/lib/authoring-path.ts
|
|
38361
|
-
import { lstatSync as
|
|
38384
|
+
import { lstatSync as lstatSync25, realpathSync as realpathSync9 } from "fs";
|
|
38362
38385
|
import { homedir as homedir3 } from "os";
|
|
38363
|
-
import { basename as
|
|
38386
|
+
import { basename as basename14, dirname as dirname23, join as join32, resolve as resolve23, sep as sep12 } from "path";
|
|
38364
38387
|
function pathParts(path) {
|
|
38365
38388
|
return resolve23(path).split(sep12).filter(Boolean);
|
|
38366
38389
|
}
|
|
@@ -38378,9 +38401,9 @@ function nativeRootMatch(path) {
|
|
|
38378
38401
|
function physicalPath(path) {
|
|
38379
38402
|
let cursor = resolve23(path);
|
|
38380
38403
|
const suffix = [];
|
|
38381
|
-
while (!
|
|
38382
|
-
suffix.unshift(
|
|
38383
|
-
const parent =
|
|
38404
|
+
while (!lstatSync25(cursor, { throwIfNoEntry: false })) {
|
|
38405
|
+
suffix.unshift(basename14(cursor));
|
|
38406
|
+
const parent = dirname23(cursor);
|
|
38384
38407
|
if (parent === cursor)
|
|
38385
38408
|
return resolve23(path);
|
|
38386
38409
|
cursor = parent;
|
|
@@ -38391,7 +38414,7 @@ function contains(root, path) {
|
|
|
38391
38414
|
return path === root || path.startsWith(root + sep12);
|
|
38392
38415
|
}
|
|
38393
38416
|
function configuredRoots(home, explicitHome) {
|
|
38394
|
-
const homeData =
|
|
38417
|
+
const homeData = join32(home, ".hasna", "skills");
|
|
38395
38418
|
const homePolicy = readManagedSkillPolicySnapshot(homeData);
|
|
38396
38419
|
const configuredPolicy = !explicitHome && resolve23(getDataDirReadOnly()) !== resolve23(homeData) ? readManagedSkillPolicySnapshot(getDataDirReadOnly()) : null;
|
|
38397
38420
|
const policy = homePolicy ?? configuredPolicy;
|
|
@@ -38422,8 +38445,8 @@ function configuredRoots(home, explicitHome) {
|
|
|
38422
38445
|
admitBinding(binding);
|
|
38423
38446
|
continue;
|
|
38424
38447
|
}
|
|
38425
|
-
const nativeHome =
|
|
38426
|
-
if (!
|
|
38448
|
+
const nativeHome = join32(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
|
|
38449
|
+
if (!lstatSync25(nativeHome, { throwIfNoEntry: false }))
|
|
38427
38450
|
continue;
|
|
38428
38451
|
roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
|
|
38429
38452
|
}
|
|
@@ -38437,8 +38460,8 @@ function assertPortableAuthoringPath(path, options = {}) {
|
|
|
38437
38460
|
const candidates = [lexical, physical];
|
|
38438
38461
|
let native = candidates.map(nativeRootMatch).find(Boolean);
|
|
38439
38462
|
const home = resolve23(options.homeDir ?? homedir3());
|
|
38440
|
-
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) =>
|
|
38441
|
-
defaults.push(
|
|
38463
|
+
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join32(home, ...parts));
|
|
38464
|
+
defaults.push(join32(home, ".codex/plugins/cache"), join32(home, ".claude/plugins/cache"), join32(home, ".claude/plugins/synced"), join32(home, ".gemini/extensions"));
|
|
38442
38465
|
for (const root of defaults) {
|
|
38443
38466
|
if (candidates.some((candidate) => contains(resolve23(root), candidate) || contains(physicalPath(root), candidate)))
|
|
38444
38467
|
native ??= root;
|
|
@@ -38467,29 +38490,29 @@ import {
|
|
|
38467
38490
|
existsSync as existsSync12,
|
|
38468
38491
|
mkdirSync as mkdirSync8,
|
|
38469
38492
|
mkdtempSync,
|
|
38470
|
-
readdirSync as
|
|
38493
|
+
readdirSync as readdirSync10,
|
|
38471
38494
|
realpathSync as realpathSync10,
|
|
38472
38495
|
renameSync as renameSync3,
|
|
38473
38496
|
rmSync as rmSync3,
|
|
38474
38497
|
statSync as statSync9,
|
|
38475
38498
|
writeFileSync as writeFileSync6
|
|
38476
38499
|
} from "fs";
|
|
38477
|
-
import { basename as
|
|
38500
|
+
import { basename as basename15, dirname as dirname24, isAbsolute as isAbsolute23, join as join33, normalize as normalize4, relative as relative8, resolve as resolve24, sep as sep13 } from "path";
|
|
38478
38501
|
function getPortableSkillsRoot(options = {}) {
|
|
38479
38502
|
return resolvePortableSkillsRoot(options, true);
|
|
38480
38503
|
}
|
|
38481
38504
|
function resolvePortableSkillsRoot(options, migrate) {
|
|
38482
38505
|
if (options.rootDir)
|
|
38483
38506
|
return options.rootDir;
|
|
38484
|
-
const appDir = options.homeDir ?
|
|
38485
|
-
const cache =
|
|
38507
|
+
const appDir = options.homeDir ? join33(options.homeDir, ".hasna", "skills") : migrate ? getDataDir() : getDataDirReadOnly();
|
|
38508
|
+
const cache = join33(appDir, SKILLS_CACHE_DIRNAME);
|
|
38486
38509
|
if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
|
|
38487
38510
|
return cache;
|
|
38488
|
-
const installed =
|
|
38511
|
+
const installed = join33(appDir, INSTALLED_SKILLS_DIRNAME);
|
|
38489
38512
|
return installed;
|
|
38490
38513
|
}
|
|
38491
38514
|
function getPortableSkillPath(name, options = {}) {
|
|
38492
|
-
return
|
|
38515
|
+
return join33(getPortableSkillsRoot(options), normalizePortableSkillName(name));
|
|
38493
38516
|
}
|
|
38494
38517
|
function findPortableSkill(name, options = {}) {
|
|
38495
38518
|
let normalized;
|
|
@@ -38512,10 +38535,10 @@ function listPortableSkills(options = {}) {
|
|
|
38512
38535
|
if (!safeIsDirectory(root))
|
|
38513
38536
|
return [];
|
|
38514
38537
|
const skills = [];
|
|
38515
|
-
for (const entry of
|
|
38538
|
+
for (const entry of readdirSync10(root).sort()) {
|
|
38516
38539
|
if (entry.startsWith("."))
|
|
38517
38540
|
continue;
|
|
38518
|
-
const path =
|
|
38541
|
+
const path = join33(root, entry);
|
|
38519
38542
|
if (!safeIsDirectory(path))
|
|
38520
38543
|
continue;
|
|
38521
38544
|
try {
|
|
@@ -38548,9 +38571,9 @@ function isOfficialSkillName(name) {
|
|
|
38548
38571
|
function scaffoldPortableSkill(name, options = {}) {
|
|
38549
38572
|
const skillName = normalizeNewPortableSkillName(name);
|
|
38550
38573
|
const readOnlyRoot = resolvePortableSkillsRoot(options, false);
|
|
38551
|
-
assertPortableAuthoringPath(
|
|
38574
|
+
assertPortableAuthoringPath(join33(readOnlyRoot, skillName), options);
|
|
38552
38575
|
const root = getPortableSkillsRoot(options);
|
|
38553
|
-
const skillPath =
|
|
38576
|
+
const skillPath = join33(root, skillName);
|
|
38554
38577
|
assertPortableAuthoringPath(skillPath, options);
|
|
38555
38578
|
if (existsSync12(skillPath)) {
|
|
38556
38579
|
if (!options.overwrite)
|
|
@@ -38572,10 +38595,10 @@ function physicalImportPath(path) {
|
|
|
38572
38595
|
let ancestor = resolve24(path);
|
|
38573
38596
|
const suffix = [];
|
|
38574
38597
|
while (!existsSync12(ancestor)) {
|
|
38575
|
-
suffix.unshift(
|
|
38576
|
-
ancestor =
|
|
38598
|
+
suffix.unshift(basename15(ancestor));
|
|
38599
|
+
ancestor = dirname24(ancestor);
|
|
38577
38600
|
}
|
|
38578
|
-
return
|
|
38601
|
+
return join33(realpathSync10(ancestor), ...suffix);
|
|
38579
38602
|
}
|
|
38580
38603
|
function assertDisjointImportPaths(source, destination) {
|
|
38581
38604
|
const sourcePath = realpathSync10(source);
|
|
@@ -38597,15 +38620,15 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
38597
38620
|
const explicitName = options.name != null;
|
|
38598
38621
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
38599
38622
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
38600
|
-
const sourceSlug = safeNormalizeName(
|
|
38601
|
-
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${
|
|
38623
|
+
const sourceSlug = safeNormalizeName(basename15(absoluteSource));
|
|
38624
|
+
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename15(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
38602
38625
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
38603
38626
|
}
|
|
38604
|
-
const readOnlyDestination =
|
|
38627
|
+
const readOnlyDestination = join33(resolvePortableSkillsRoot(options, false), skillName);
|
|
38605
38628
|
assertPortableAuthoringPath(readOnlyDestination, options);
|
|
38606
38629
|
assertDisjointImportPaths(absoluteSource, readOnlyDestination);
|
|
38607
38630
|
const root = getPortableSkillsRoot(options);
|
|
38608
|
-
const destination =
|
|
38631
|
+
const destination = join33(root, skillName);
|
|
38609
38632
|
assertPortableAuthoringPath(destination, options);
|
|
38610
38633
|
assertDisjointImportPaths(absoluteSource, destination);
|
|
38611
38634
|
if (existsSync12(destination)) {
|
|
@@ -38613,7 +38636,7 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
38613
38636
|
throw new Error(`Skill '${skillName}' already exists at ${destination}`);
|
|
38614
38637
|
rmSync3(destination, { recursive: true, force: true });
|
|
38615
38638
|
}
|
|
38616
|
-
mkdirSync8(
|
|
38639
|
+
mkdirSync8(dirname24(destination), { recursive: true });
|
|
38617
38640
|
copySkillDirectory(absoluteSource, destination);
|
|
38618
38641
|
const base = {
|
|
38619
38642
|
...inferred,
|
|
@@ -38632,18 +38655,29 @@ function safeNormalizeName(name) {
|
|
|
38632
38655
|
}
|
|
38633
38656
|
function validatePortableSkillDirectory(name, skillPath) {
|
|
38634
38657
|
const normalizedName = normalizePortableSkillName(name);
|
|
38635
|
-
|
|
38658
|
+
let manifest;
|
|
38659
|
+
let manifestError;
|
|
38660
|
+
if (existsSync12(skillPath)) {
|
|
38661
|
+
try {
|
|
38662
|
+
manifest = readPortableSkillManifest(skillPath, normalizedName);
|
|
38663
|
+
} catch (error61) {
|
|
38664
|
+
manifestError = error61;
|
|
38665
|
+
}
|
|
38666
|
+
}
|
|
38667
|
+
const base = validateSkillDirectory(normalizedName, skillPath, undefined, { kind: manifest?.kind });
|
|
38636
38668
|
const issues = [...base.issues];
|
|
38637
38669
|
const warnings = [...base.warnings];
|
|
38638
|
-
let manifest;
|
|
38639
38670
|
if (existsSync12(skillPath)) {
|
|
38640
|
-
const skillJsonPath =
|
|
38641
|
-
const skillMdPath =
|
|
38671
|
+
const skillJsonPath = join33(skillPath, "skill.json");
|
|
38672
|
+
const skillMdPath = join33(skillPath, "SKILL.md");
|
|
38642
38673
|
if (!existsSync12(skillJsonPath) && !existsSync12(skillMdPath)) {
|
|
38643
38674
|
add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
|
|
38644
38675
|
}
|
|
38645
38676
|
try {
|
|
38646
|
-
|
|
38677
|
+
if (manifestError)
|
|
38678
|
+
throw manifestError;
|
|
38679
|
+
if (!manifest)
|
|
38680
|
+
throw new Error("Portable manifest could not be read");
|
|
38647
38681
|
const isInstruction = manifest.kind === "instruction";
|
|
38648
38682
|
if (manifest.name !== normalizedName) {
|
|
38649
38683
|
add3(issues, "portable.name_mismatch", `Portable manifest name '${manifest.name}' does not match '${normalizedName}'`);
|
|
@@ -38658,27 +38692,11 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
38658
38692
|
add3(issues, "portable.version_missing", "Portable manifest missing version");
|
|
38659
38693
|
}
|
|
38660
38694
|
const contractIssues = validatePortableManifestContract(manifest, {
|
|
38661
|
-
strict: existsSync12(
|
|
38695
|
+
strict: existsSync12(join33(skillPath, "skill.json")),
|
|
38662
38696
|
skillPath
|
|
38663
38697
|
});
|
|
38664
38698
|
for (const issue2 of contractIssues)
|
|
38665
38699
|
add3(issues, issue2.code, issue2.message);
|
|
38666
|
-
if (manifest.kind === "instruction") {
|
|
38667
|
-
const executableOnlyCodes = new Set([
|
|
38668
|
-
"package.missing",
|
|
38669
|
-
"package.bin_missing",
|
|
38670
|
-
"skill.src_missing",
|
|
38671
|
-
"skill.src_index_missing",
|
|
38672
|
-
"skill.runtime_entrypoint_unsafe",
|
|
38673
|
-
"skill.runtime_entrypoint_missing",
|
|
38674
|
-
"skill.runtime_entrypoint_symlink",
|
|
38675
|
-
"skill.runtime_entrypoint_not_file"
|
|
38676
|
-
]);
|
|
38677
|
-
for (let i = issues.length - 1;i >= 0; i--) {
|
|
38678
|
-
if (executableOnlyCodes.has(issues[i].code))
|
|
38679
|
-
issues.splice(i, 1);
|
|
38680
|
-
}
|
|
38681
|
-
}
|
|
38682
38700
|
if (!isInstruction && (!Array.isArray(manifest.inputs) || manifest.inputs.length === 0)) {
|
|
38683
38701
|
add3(issues, "portable.inputs_missing", "Portable manifest must declare inputs");
|
|
38684
38702
|
}
|
|
@@ -38698,7 +38716,7 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
38698
38716
|
add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
|
|
38699
38717
|
continue;
|
|
38700
38718
|
}
|
|
38701
|
-
const entryPath =
|
|
38719
|
+
const entryPath = join33(skillPath, command.entry);
|
|
38702
38720
|
if (!existsSync12(entryPath))
|
|
38703
38721
|
add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
|
|
38704
38722
|
else if (statSync9(entryPath).isDirectory())
|
|
@@ -38709,7 +38727,7 @@ function validatePortableSkillDirectory(name, skillPath) {
|
|
|
38709
38727
|
} catch (error61) {
|
|
38710
38728
|
add3(issues, "portable.manifest_invalid", error61.message);
|
|
38711
38729
|
}
|
|
38712
|
-
if (manifest?.kind !== "instruction" && !existsSync12(
|
|
38730
|
+
if (manifest?.kind !== "instruction" && !existsSync12(join33(skillPath, "AGENTS.md"))) {
|
|
38713
38731
|
add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
|
|
38714
38732
|
}
|
|
38715
38733
|
}
|
|
@@ -38847,8 +38865,8 @@ var init_registry_types = __esm(() => {
|
|
|
38847
38865
|
});
|
|
38848
38866
|
|
|
38849
38867
|
// src/lib/registry.ts
|
|
38850
|
-
import { existsSync as existsSync13, readFileSync as
|
|
38851
|
-
import { join as
|
|
38868
|
+
import { existsSync as existsSync13, readFileSync as readFileSync19, readdirSync as readdirSync11 } from "fs";
|
|
38869
|
+
import { join as join34 } from "path";
|
|
38852
38870
|
function parseSkillMdFrontmatter(content) {
|
|
38853
38871
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
38854
38872
|
if (!match)
|
|
@@ -38885,16 +38903,16 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
38885
38903
|
return [];
|
|
38886
38904
|
const result = [];
|
|
38887
38905
|
try {
|
|
38888
|
-
const entries =
|
|
38906
|
+
const entries = readdirSync11(dir, { withFileTypes: true });
|
|
38889
38907
|
for (const entry of entries) {
|
|
38890
38908
|
if (!entry.isDirectory())
|
|
38891
38909
|
continue;
|
|
38892
|
-
const skillMdPath =
|
|
38910
|
+
const skillMdPath = join34(dir, entry.name, "SKILL.md");
|
|
38893
38911
|
if (!existsSync13(skillMdPath))
|
|
38894
38912
|
continue;
|
|
38895
38913
|
let content;
|
|
38896
38914
|
try {
|
|
38897
|
-
content =
|
|
38915
|
+
content = readFileSync19(skillMdPath, "utf-8");
|
|
38898
38916
|
} catch {
|
|
38899
38917
|
continue;
|
|
38900
38918
|
}
|
|
@@ -38909,7 +38927,7 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
38909
38927
|
category: fm.category || "Development Tools",
|
|
38910
38928
|
tags: fm.tags || [],
|
|
38911
38929
|
...fm.kind ? { kind: fm.kind } : {},
|
|
38912
|
-
...isHostedMetadataSkillDir(
|
|
38930
|
+
...isHostedMetadataSkillDir(join34(dir, entry.name)) ? { serverOwned: true } : {},
|
|
38913
38931
|
source
|
|
38914
38932
|
});
|
|
38915
38933
|
}
|
|
@@ -38921,17 +38939,17 @@ function findExtensionSkillPath(name) {
|
|
|
38921
38939
|
if (!config2.extensionsDir || !existsSync13(config2.extensionsDir))
|
|
38922
38940
|
return null;
|
|
38923
38941
|
try {
|
|
38924
|
-
const entries =
|
|
38942
|
+
const entries = readdirSync11(config2.extensionsDir, { withFileTypes: true });
|
|
38925
38943
|
for (const entry of entries) {
|
|
38926
38944
|
if (!entry.isDirectory())
|
|
38927
38945
|
continue;
|
|
38928
|
-
const skillDir =
|
|
38929
|
-
const skillMdPath =
|
|
38946
|
+
const skillDir = join34(config2.extensionsDir, entry.name);
|
|
38947
|
+
const skillMdPath = join34(skillDir, "SKILL.md");
|
|
38930
38948
|
if (!existsSync13(skillMdPath))
|
|
38931
38949
|
continue;
|
|
38932
38950
|
let content;
|
|
38933
38951
|
try {
|
|
38934
|
-
content =
|
|
38952
|
+
content = readFileSync19(skillMdPath, "utf-8");
|
|
38935
38953
|
} catch {
|
|
38936
38954
|
continue;
|
|
38937
38955
|
}
|
|
@@ -40143,14 +40161,14 @@ var init_remote_workspace_leave = __esm(() => {
|
|
|
40143
40161
|
});
|
|
40144
40162
|
|
|
40145
40163
|
// src/lib/auth-store.ts
|
|
40146
|
-
import { chmodSync, existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as
|
|
40147
|
-
import { basename as
|
|
40164
|
+
import { chmodSync, existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync20, renameSync as renameSync4, statSync as statSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
40165
|
+
import { basename as basename16, dirname as dirname25, join as join35 } from "path";
|
|
40148
40166
|
function getAuthFilePath(env = process.env) {
|
|
40149
40167
|
return skillsCredentialFilePath(env);
|
|
40150
40168
|
}
|
|
40151
40169
|
function getIdentityFilePath(env = process.env) {
|
|
40152
40170
|
const file2 = skillsCredentialFilePath(env);
|
|
40153
|
-
return
|
|
40171
|
+
return join35(dirname25(file2), basename16(file2).replace(/^credentials/, "identity") + ".json");
|
|
40154
40172
|
}
|
|
40155
40173
|
function getApiUrl(action, env = process.env, options = {}) {
|
|
40156
40174
|
return requireSkillsApiOrigin(action, env, options);
|
|
@@ -40485,6 +40503,130 @@ var init_remote_permissions = __esm(() => {
|
|
|
40485
40503
|
};
|
|
40486
40504
|
});
|
|
40487
40505
|
|
|
40506
|
+
// src/lib/revision.ts
|
|
40507
|
+
import { createHash as createHash26 } from "crypto";
|
|
40508
|
+
function revisionIdOf(content) {
|
|
40509
|
+
const canonicalContent = {
|
|
40510
|
+
slug: content.slug,
|
|
40511
|
+
displayName: content.displayName,
|
|
40512
|
+
description: content.description,
|
|
40513
|
+
category: content.category,
|
|
40514
|
+
tags: content.tags,
|
|
40515
|
+
source: content.source,
|
|
40516
|
+
kind: content.kind,
|
|
40517
|
+
version: content.version ?? null,
|
|
40518
|
+
skillMd: content.skillMd ?? null,
|
|
40519
|
+
bundleSha256: content.bundleSha256 ?? null,
|
|
40520
|
+
bundleByteSize: content.bundleByteSize ?? null
|
|
40521
|
+
};
|
|
40522
|
+
if (content.lifecycle === "archived" || content.archiveReason !== undefined || content.replacementSlug !== undefined) {
|
|
40523
|
+
canonicalContent.lifecycle = content.lifecycle ?? "active";
|
|
40524
|
+
canonicalContent.archiveReason = content.archiveReason ?? null;
|
|
40525
|
+
canonicalContent.replacementSlug = content.replacementSlug ?? null;
|
|
40526
|
+
}
|
|
40527
|
+
const canonical9 = JSON.stringify(canonicalContent);
|
|
40528
|
+
return createHash26("sha256").update(canonical9).digest("hex");
|
|
40529
|
+
}
|
|
40530
|
+
var REVISION_ID_PATTERN;
|
|
40531
|
+
var init_revision = __esm(() => {
|
|
40532
|
+
REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
|
|
40533
|
+
});
|
|
40534
|
+
|
|
40535
|
+
// src/lib/skill-metadata-update.ts
|
|
40536
|
+
function metadataPatch(value) {
|
|
40537
|
+
if (!object7(value))
|
|
40538
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
|
|
40539
|
+
const keys2 = Object.keys(value);
|
|
40540
|
+
if (!keys2.length || keys2.some((key2) => !["category", "tags"].includes(key2)))
|
|
40541
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
|
|
40542
|
+
const copy = {};
|
|
40543
|
+
if (Object.hasOwn(value, "category"))
|
|
40544
|
+
copy.category = value.category;
|
|
40545
|
+
if (Object.hasOwn(value, "tags")) {
|
|
40546
|
+
const tags = value.tags;
|
|
40547
|
+
copy.tags = Array.isArray(tags) ? Array.from(tags) : tags;
|
|
40548
|
+
}
|
|
40549
|
+
if (Object.hasOwn(copy, "category") && !text3(copy.category))
|
|
40550
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
|
|
40551
|
+
if (Object.hasOwn(copy, "tags") && (!Array.isArray(copy.tags) || copy.tags.length > 100 || copy.tags.some((tag) => !text3(tag)) || new Set(copy.tags).size !== copy.tags.length))
|
|
40552
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_PATCH");
|
|
40553
|
+
return copy;
|
|
40554
|
+
}
|
|
40555
|
+
function metadataSnapshot(value, etag) {
|
|
40556
|
+
if (!object7(value) || !text3(value.slug) || !/^[a-z0-9][a-z0-9._-]*$/.test(value.slug) || ![value.displayName, value.description, value.category, value.publishedSource].every((field3) => typeof field3 === "string") || !Array.isArray(value.tags) || value.tags.some((tag) => typeof tag !== "string") || !["instruction", "executable"].includes(String(value.kind)) || typeof value.revisionId !== "string" || !REVISION_ID_PATTERN.test(value.revisionId) || etag !== `"${value.revisionId}"`)
|
|
40557
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
|
|
40558
|
+
const content = {
|
|
40559
|
+
slug: value.slug,
|
|
40560
|
+
displayName: value.displayName,
|
|
40561
|
+
description: value.description,
|
|
40562
|
+
category: value.category,
|
|
40563
|
+
tags: [...value.tags],
|
|
40564
|
+
source: value.publishedSource,
|
|
40565
|
+
kind: value.kind
|
|
40566
|
+
};
|
|
40567
|
+
for (const key2 of ["version", "skillMd", "bundleSha256", "archiveReason", "replacementSlug"]) {
|
|
40568
|
+
if (value[key2] !== undefined) {
|
|
40569
|
+
if (typeof value[key2] !== "string")
|
|
40570
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
|
|
40571
|
+
content[key2] = value[key2];
|
|
40572
|
+
}
|
|
40573
|
+
}
|
|
40574
|
+
if (value.bundleByteSize !== undefined) {
|
|
40575
|
+
if (!Number.isSafeInteger(value.bundleByteSize) || value.bundleByteSize < 0)
|
|
40576
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
|
|
40577
|
+
content.bundleByteSize = value.bundleByteSize;
|
|
40578
|
+
}
|
|
40579
|
+
if (value.lifecycle !== undefined) {
|
|
40580
|
+
if (value.lifecycle !== "active" && value.lifecycle !== "archived")
|
|
40581
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
|
|
40582
|
+
content.lifecycle = value.lifecycle;
|
|
40583
|
+
}
|
|
40584
|
+
if (revisionIdOf(content) !== value.revisionId)
|
|
40585
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
|
|
40586
|
+
return { content, revisionId: value.revisionId };
|
|
40587
|
+
}
|
|
40588
|
+
function metadataPlan(value) {
|
|
40589
|
+
if (!object7(value) || Object.keys(value).sort().join(",") !== "authority,before,expectedRevisionId,organizationId,originalDocument,patch,schemaVersion" || value.schemaVersion !== 1 || !text3(value.authority) || !text3(value.organizationId) || !object7(value.before) || typeof value.originalDocument !== "string" || Buffer.byteLength(value.originalDocument) > 2 * 1024 * 1024 || typeof value.expectedRevisionId !== "string" || !REVISION_ID_PATTERN.test(value.expectedRevisionId))
|
|
40590
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
|
|
40591
|
+
const before = metadataSnapshot({ ...value.before, publishedSource: value.before.source, revisionId: value.expectedRevisionId }, `"${value.expectedRevisionId}"`).content;
|
|
40592
|
+
let original;
|
|
40593
|
+
try {
|
|
40594
|
+
original = JSON.parse(value.originalDocument);
|
|
40595
|
+
} catch {
|
|
40596
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
|
|
40597
|
+
}
|
|
40598
|
+
const preserved = metadataSnapshot(original, `"${value.expectedRevisionId}"`);
|
|
40599
|
+
if (preserved.revisionId !== value.expectedRevisionId)
|
|
40600
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
|
|
40601
|
+
return {
|
|
40602
|
+
schemaVersion: 1,
|
|
40603
|
+
authority: value.authority,
|
|
40604
|
+
organizationId: value.organizationId,
|
|
40605
|
+
expectedRevisionId: value.expectedRevisionId,
|
|
40606
|
+
originalDocument: value.originalDocument,
|
|
40607
|
+
before,
|
|
40608
|
+
patch: metadataPatch(value.patch)
|
|
40609
|
+
};
|
|
40610
|
+
}
|
|
40611
|
+
var SkillMetadataUpdateError, object7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), text3 = (value) => typeof value === "string" && value.length > 0 && value.length <= 512 && !/[\x00-\x1f\x7f]/.test(value);
|
|
40612
|
+
var init_skill_metadata_update = __esm(() => {
|
|
40613
|
+
init_revision();
|
|
40614
|
+
SkillMetadataUpdateError = class SkillMetadataUpdateError extends Error {
|
|
40615
|
+
code;
|
|
40616
|
+
constructor(code) {
|
|
40617
|
+
super({
|
|
40618
|
+
METADATA_AUTH_REQUIRED: "Metadata updates require a signed-in Skills connection; use skills login.",
|
|
40619
|
+
INVALID_METADATA_PATCH: "Metadata patch accepts only category (a nonempty string) and tags (an array of unique nonempty strings).",
|
|
40620
|
+
INVALID_METADATA_SNAPSHOT: "The current skill must carry a matching quoted revision ETag and complete verifiable metadata, body and bundle identity.",
|
|
40621
|
+
INVALID_METADATA_PLAN: "The saved metadata plan must name its original revision, authority, organization, complete original content and category/tags-only patch.",
|
|
40622
|
+
METADATA_REVISION_CONFLICT: "The skill revision changed after preview; inspect it and prepare a new plan.",
|
|
40623
|
+
METADATA_UPDATE_UNCONFIRMED: "Metadata update could not be confirmed by authoritative readback; inspect the current revision before preparing another write."
|
|
40624
|
+
}[code]);
|
|
40625
|
+
this.code = code;
|
|
40626
|
+
}
|
|
40627
|
+
};
|
|
40628
|
+
});
|
|
40629
|
+
|
|
40488
40630
|
// src/lib/remote-client.ts
|
|
40489
40631
|
var exports_remote_client = {};
|
|
40490
40632
|
__export(exports_remote_client, {
|
|
@@ -40562,6 +40704,89 @@ class RemoteSkillsClient {
|
|
|
40562
40704
|
return null;
|
|
40563
40705
|
return res.json();
|
|
40564
40706
|
}
|
|
40707
|
+
async metadataOrganization() {
|
|
40708
|
+
const identity4 = await this.getIdentity();
|
|
40709
|
+
const organization2 = identity4.organization;
|
|
40710
|
+
if (typeof organization2?.id !== "string" || !organization2.id)
|
|
40711
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
|
|
40712
|
+
return organization2.id;
|
|
40713
|
+
}
|
|
40714
|
+
async readMetadataSnapshot(slug2) {
|
|
40715
|
+
const response = await this.request(`/api/v1/skills/${encodeURIComponent(slug2)}`);
|
|
40716
|
+
if (!response.ok)
|
|
40717
|
+
throw new RemoteRequestError("/api/v1/skills/:slug", response.status);
|
|
40718
|
+
const bytes = await readBoundedResponse(response, 2 * 1024 * 1024);
|
|
40719
|
+
const originalDocument = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
40720
|
+
let value;
|
|
40721
|
+
try {
|
|
40722
|
+
value = JSON.parse(originalDocument);
|
|
40723
|
+
} catch {
|
|
40724
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
|
|
40725
|
+
}
|
|
40726
|
+
const snapshot2 = metadataSnapshot(value, response.headers.get("etag"));
|
|
40727
|
+
if (snapshot2.content.slug !== slug2)
|
|
40728
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_SNAPSHOT");
|
|
40729
|
+
return { ...snapshot2, originalDocument };
|
|
40730
|
+
}
|
|
40731
|
+
async prepareSkillMetadataUpdate(slug2, patch) {
|
|
40732
|
+
const captured = metadataPatch(patch);
|
|
40733
|
+
const organizationId = await this.metadataOrganization();
|
|
40734
|
+
const snapshot2 = await this.readMetadataSnapshot(slug2);
|
|
40735
|
+
return metadataPlan({
|
|
40736
|
+
schemaVersion: 1,
|
|
40737
|
+
authority: this.apiUrl,
|
|
40738
|
+
organizationId,
|
|
40739
|
+
expectedRevisionId: snapshot2.revisionId,
|
|
40740
|
+
originalDocument: snapshot2.originalDocument,
|
|
40741
|
+
before: snapshot2.content,
|
|
40742
|
+
patch: captured
|
|
40743
|
+
});
|
|
40744
|
+
}
|
|
40745
|
+
async applySkillMetadataUpdate(input2) {
|
|
40746
|
+
const plan = metadataPlan(input2);
|
|
40747
|
+
if (plan.authority !== this.apiUrl || await this.metadataOrganization() !== plan.organizationId)
|
|
40748
|
+
throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
|
|
40749
|
+
const access = await this.getCapabilities({ refresh: true });
|
|
40750
|
+
if (access.permissions?.publish !== true)
|
|
40751
|
+
throw new RemoteSkillsPermissionError("publish");
|
|
40752
|
+
const current = await this.readMetadataSnapshot(plan.before.slug);
|
|
40753
|
+
if (current.revisionId !== plan.expectedRevisionId)
|
|
40754
|
+
throw new SkillMetadataUpdateError("METADATA_REVISION_CONFLICT");
|
|
40755
|
+
const expected = revisionIdOf({ ...plan.before, ...plan.patch });
|
|
40756
|
+
if (expected === current.revisionId)
|
|
40757
|
+
return { status: "unchanged", revisionId: expected };
|
|
40758
|
+
let uncertain = false;
|
|
40759
|
+
try {
|
|
40760
|
+
const response = await this.request(`/api/v1/skills/${encodeURIComponent(plan.before.slug)}`, {
|
|
40761
|
+
method: "PATCH",
|
|
40762
|
+
headers: { "If-Match": `"${plan.expectedRevisionId}"` },
|
|
40763
|
+
body: JSON.stringify(plan.patch)
|
|
40764
|
+
});
|
|
40765
|
+
if (!response.ok && response.status < 500)
|
|
40766
|
+
throw new RemoteRequestError("/api/v1/skills/:slug", response.status);
|
|
40767
|
+
if (!response.ok)
|
|
40768
|
+
uncertain = true;
|
|
40769
|
+
else {
|
|
40770
|
+
const bytes = await readBoundedResponse(response, 2 * 1024 * 1024);
|
|
40771
|
+
const written = metadataSnapshot(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes)), response.headers.get("etag"));
|
|
40772
|
+
if (written.revisionId !== expected)
|
|
40773
|
+
throw new SkillMetadataUpdateError("METADATA_UPDATE_UNCONFIRMED");
|
|
40774
|
+
}
|
|
40775
|
+
} catch (error61) {
|
|
40776
|
+
if (error61 instanceof RemoteRequestError && error61.status < 500)
|
|
40777
|
+
throw error61;
|
|
40778
|
+
uncertain = true;
|
|
40779
|
+
}
|
|
40780
|
+
let verified;
|
|
40781
|
+
try {
|
|
40782
|
+
verified = await this.readMetadataSnapshot(plan.before.slug);
|
|
40783
|
+
} catch {
|
|
40784
|
+
throw new SkillMetadataUpdateError("METADATA_UPDATE_UNCONFIRMED");
|
|
40785
|
+
}
|
|
40786
|
+
if (verified.revisionId !== expected)
|
|
40787
|
+
throw new SkillMetadataUpdateError("METADATA_UPDATE_UNCONFIRMED");
|
|
40788
|
+
return { status: uncertain ? "reconciled" : "applied", revisionId: expected };
|
|
40789
|
+
}
|
|
40565
40790
|
async getSkillStatus(slug2) {
|
|
40566
40791
|
const res = await this.request(`/api/v1/skills/${encodeURIComponent(slug2)}`, { method: "GET" });
|
|
40567
40792
|
let body = null;
|
|
@@ -41432,6 +41657,8 @@ var init_remote_client = __esm(() => {
|
|
|
41432
41657
|
init_remote_credit_checkout();
|
|
41433
41658
|
init_remote_quote_errors();
|
|
41434
41659
|
init_remote_permissions();
|
|
41660
|
+
init_skill_metadata_update();
|
|
41661
|
+
init_revision();
|
|
41435
41662
|
RemoteRouteUnsupportedError = class RemoteRouteUnsupportedError extends Error {
|
|
41436
41663
|
path;
|
|
41437
41664
|
status;
|
|
@@ -41619,7 +41846,7 @@ var init_remote_invitation_recovery = __esm(() => {
|
|
|
41619
41846
|
});
|
|
41620
41847
|
|
|
41621
41848
|
// src/lib/remote-private-publications.ts
|
|
41622
|
-
import { createHash as
|
|
41849
|
+
import { createHash as createHash27 } from "crypto";
|
|
41623
41850
|
function checkedPrivateSkillCreate(value) {
|
|
41624
41851
|
const refuse5 = (field3, accepted) => {
|
|
41625
41852
|
throw new PrivatePublicationError("INVALID_SKILL_CREATE_INPUT", `Invalid ${field3}. ${accepted}`);
|
|
@@ -41657,7 +41884,7 @@ function checkedPublicationView(value, skillId, intentId, declaration) {
|
|
|
41657
41884
|
return invalid4();
|
|
41658
41885
|
return Object.freeze({ ...value });
|
|
41659
41886
|
}
|
|
41660
|
-
async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal, create = false) {
|
|
41887
|
+
async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal, create = false, readBinding) {
|
|
41661
41888
|
const controller = new AbortController;
|
|
41662
41889
|
let reader;
|
|
41663
41890
|
let response;
|
|
@@ -41673,8 +41900,18 @@ async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal,
|
|
|
41673
41900
|
redirect: "error",
|
|
41674
41901
|
credentials: "omit",
|
|
41675
41902
|
signal: controller.signal,
|
|
41676
|
-
headers: {
|
|
41903
|
+
headers: {
|
|
41904
|
+
"Content-Type": "application/json",
|
|
41905
|
+
Authorization: `Bearer ${token}`,
|
|
41906
|
+
...readBinding ? {
|
|
41907
|
+
"x-skills-user-id": readBinding.userId,
|
|
41908
|
+
"x-skills-workspace-id": readBinding.organizationId,
|
|
41909
|
+
"x-skills-membership-id": readBinding.membershipId
|
|
41910
|
+
} : {}
|
|
41911
|
+
}
|
|
41677
41912
|
});
|
|
41913
|
+
if (readBinding && response.ok && response.status !== 200)
|
|
41914
|
+
return invalid4();
|
|
41678
41915
|
const length = response.headers.get("content-length");
|
|
41679
41916
|
if (length !== null && (!/^\d+$/.test(length) || Number(length) > 65536))
|
|
41680
41917
|
return invalid4();
|
|
@@ -41742,6 +41979,81 @@ async function boundedJson(url2, init, token, mutation, budget3 = 15000, signal,
|
|
|
41742
41979
|
response?.body?.cancel().catch(() => {});
|
|
41743
41980
|
}
|
|
41744
41981
|
}
|
|
41982
|
+
function historyDate(value) {
|
|
41983
|
+
if (typeof value !== "string")
|
|
41984
|
+
return false;
|
|
41985
|
+
const parts = /^(\d{4})-(\d{2})-(\d{2})(T| )(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,9}))?(Z|[+-](\d{2})(?::(\d{2}))?)$/.exec(value);
|
|
41986
|
+
if (!parts)
|
|
41987
|
+
return false;
|
|
41988
|
+
const [, y, m, d, separator, h, minute, second, fraction, zone, offsetHour, offsetMinute] = parts;
|
|
41989
|
+
if (separator === " " ? zone === "Z" || (fraction?.length ?? 0) > 6 : zone !== "Z" && offsetMinute === undefined)
|
|
41990
|
+
return false;
|
|
41991
|
+
const year = Number(y), month = Number(m), day = Number(d);
|
|
41992
|
+
const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
41993
|
+
const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
41994
|
+
return year > 0 && month >= 1 && month <= 12 && day >= 1 && day <= days[month - 1] && Number(h) <= 23 && Number(minute) <= 59 && Number(second) <= 59 && (zone === "Z" || Number(offsetHour) <= 23 && Number(offsetMinute ?? 0) <= 59);
|
|
41995
|
+
}
|
|
41996
|
+
function privateHistory(value, organizationId, skillId, limit, cursor2) {
|
|
41997
|
+
if (!record10(value) || value.organizationId !== organizationId || value.skillId !== skillId || typeof value.slug !== "string" || !/^[a-z0-9-]+$/.test(value.slug) || !(value.currentVersion === null || historyText(value.currentVersion)) || !(value.currentVersionId === null || publicationUuid(value.currentVersionId)) || value.currentVersion === null !== (value.currentVersionId === null) || !(value.nextCursor === null || publicationUuid(value.nextCursor)) || !Array.isArray(value.versions) || value.versions.length > limit)
|
|
41998
|
+
return historyResponse();
|
|
41999
|
+
const seen = new Set;
|
|
42000
|
+
let previous = cursor2;
|
|
42001
|
+
const versions2 = value.versions.map((row) => {
|
|
42002
|
+
if (!record10(row) || !publicationUuid(row.id) || seen.has(row.id) || previous !== undefined && row.id >= previous || !historyText(row.version) || !(row.releasedAt === null || historyDate(row.releasedAt)) || !historyDate(row.createdAt) || row.id === value.currentVersionId !== (row.version === value.currentVersion))
|
|
42003
|
+
return historyResponse();
|
|
42004
|
+
seen.add(row.id);
|
|
42005
|
+
previous = row.id;
|
|
42006
|
+
return Object.freeze({ id: row.id, version: row.version, releasedAt: row.releasedAt, createdAt: row.createdAt });
|
|
42007
|
+
});
|
|
42008
|
+
if (value.nextCursor !== null && (!versions2.length || value.nextCursor !== versions2.at(-1).id))
|
|
42009
|
+
return historyResponse();
|
|
42010
|
+
return Object.freeze({
|
|
42011
|
+
organizationId,
|
|
42012
|
+
skillId,
|
|
42013
|
+
slug: value.slug,
|
|
42014
|
+
currentVersion: value.currentVersion,
|
|
42015
|
+
currentVersionId: value.currentVersionId,
|
|
42016
|
+
versions: Object.freeze(versions2),
|
|
42017
|
+
nextCursor: value.nextCursor
|
|
42018
|
+
});
|
|
42019
|
+
}
|
|
42020
|
+
|
|
42021
|
+
class RemotePrivateSkillHistoryClient {
|
|
42022
|
+
apiOrigin;
|
|
42023
|
+
organizationId;
|
|
42024
|
+
userId;
|
|
42025
|
+
membershipId;
|
|
42026
|
+
#token;
|
|
42027
|
+
constructor(apiUrl, session) {
|
|
42028
|
+
const checked = parseWorkspaceSession(session, { userId: session?.user?.id, membershipId: session?.user?.membershipId });
|
|
42029
|
+
this.apiOrigin = normalizeSkillsApiOrigin(apiUrl);
|
|
42030
|
+
this.#token = checked.token;
|
|
42031
|
+
this.organizationId = checked.organization.id;
|
|
42032
|
+
this.userId = checked.user.id;
|
|
42033
|
+
this.membershipId = checked.user.membershipId;
|
|
42034
|
+
Object.freeze(this);
|
|
42035
|
+
}
|
|
42036
|
+
async listVersions(skillId, options = {}) {
|
|
42037
|
+
if (!publicationUuid(skillId) || options.limit !== undefined && (!Number.isSafeInteger(options.limit) || options.limit < 1 || options.limit > 50) || options.cursor !== undefined && !publicationUuid(options.cursor) || options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
|
|
42038
|
+
return historyInput();
|
|
42039
|
+
const limit = options.limit ?? 20, cursor2 = options.cursor;
|
|
42040
|
+
const query = new URLSearchParams;
|
|
42041
|
+
if (options.limit !== undefined)
|
|
42042
|
+
query.set("limit", String(limit));
|
|
42043
|
+
if (cursor2 !== undefined)
|
|
42044
|
+
query.set("cursor", cursor2);
|
|
42045
|
+
const path = `/api/v1/skills/${skillId}/versions${query.size ? `?${query}` : ""}`;
|
|
42046
|
+
let value;
|
|
42047
|
+
try {
|
|
42048
|
+
value = await boundedJson(skillsApiRequestUrl(this.apiOrigin, path), { method: "GET" }, this.#token, false, options.timeoutMs, options.signal, false, this);
|
|
42049
|
+
} catch (error61) {
|
|
42050
|
+
if (error61 instanceof PrivatePublicationError && error61.code === "INVALID_PUBLICATION_RESPONSE")
|
|
42051
|
+
return historyResponse();
|
|
42052
|
+
throw new PrivatePublicationError("PRIVATE_HISTORY_UNAVAILABLE", "Unable to read private version history. Check the selected server, current membership and fresh sign-in; no skill or credential was changed.", false, error61 instanceof PrivatePublicationError ? error61.status : undefined);
|
|
42053
|
+
}
|
|
42054
|
+
return privateHistory(value, this.organizationId, skillId, limit, cursor2);
|
|
42055
|
+
}
|
|
42056
|
+
}
|
|
41745
42057
|
|
|
41746
42058
|
class RemotePrivatePublicationsClient {
|
|
41747
42059
|
apiOrigin;
|
|
@@ -41915,7 +42227,11 @@ var PRIVATE_PUBLICATION_MAX_BYTES, skillCreateFailures, failures2, PrivatePublic
|
|
|
41915
42227
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
41916
42228
|
}, invalid4 = () => {
|
|
41917
42229
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
41918
|
-
}, 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), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record10(v) && Object.keys(v).sort().join(",") === keys2.sort().join(","), date5 = (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) =>
|
|
42230
|
+
}, 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), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record10(v) && Object.keys(v).sort().join(",") === keys2.sort().join(","), date5 = (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) => createHash27("sha256").update(bytes).digest("hex"), historyInput = () => {
|
|
42231
|
+
throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_INPUT", "Provide a private skill UUID, limit from 1 to 50, and an optional UUID cursor; timeoutMs must be from 1 to 15000.");
|
|
42232
|
+
}, historyResponse = () => {
|
|
42233
|
+
throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_RESPONSE", "The server returned invalid private version history.");
|
|
42234
|
+
}, historyText = (value) => typeof value === "string" && value.length > 0 && value.length <= 128 && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value);
|
|
41919
42235
|
var init_remote_private_publications = __esm(() => {
|
|
41920
42236
|
init_fleet_credentials();
|
|
41921
42237
|
init_remote_workspace_selection();
|
|
@@ -41986,8 +42302,8 @@ async function requestAuthApi(instance, path, options) {
|
|
|
41986
42302
|
apiUrl: safeUrl
|
|
41987
42303
|
});
|
|
41988
42304
|
}
|
|
41989
|
-
const
|
|
41990
|
-
const body =
|
|
42305
|
+
const text4 = await res.text();
|
|
42306
|
+
const body = text4 ? parseJsonBody(text4) : {};
|
|
41991
42307
|
if (!res.ok) {
|
|
41992
42308
|
const record11 = isRecord6(body) ? body : {};
|
|
41993
42309
|
const detail = typeof record11.detail === "string" ? record11.detail : undefined;
|
|
@@ -42003,15 +42319,15 @@ async function requestAuthApi(instance, path, options) {
|
|
|
42003
42319
|
}
|
|
42004
42320
|
return body;
|
|
42005
42321
|
}
|
|
42006
|
-
function parseJsonBody(
|
|
42322
|
+
function parseJsonBody(text4) {
|
|
42007
42323
|
try {
|
|
42008
|
-
return JSON.parse(
|
|
42324
|
+
return JSON.parse(text4);
|
|
42009
42325
|
} catch {
|
|
42010
|
-
return { detail: condenseErrorBody(
|
|
42326
|
+
return { detail: condenseErrorBody(text4) };
|
|
42011
42327
|
}
|
|
42012
42328
|
}
|
|
42013
|
-
function condenseErrorBody(
|
|
42014
|
-
const stripped = /<[a-z!/]/i.test(
|
|
42329
|
+
function condenseErrorBody(text4) {
|
|
42330
|
+
const stripped = /<[a-z!/]/i.test(text4) ? text4.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text4;
|
|
42015
42331
|
const collapsed = stripped.replace(/\s+/g, " ").trim();
|
|
42016
42332
|
if (collapsed.length <= MAX_ERROR_DETAIL_LENGTH)
|
|
42017
42333
|
return collapsed;
|
|
@@ -42030,6 +42346,10 @@ class RemoteSkillsAuthClient {
|
|
|
42030
42346
|
const origin = this.apiOrigin, captured = workspaceContext(context);
|
|
42031
42347
|
return new RemotePrivatePublicationsClient(origin, await this.switchWorkspace(email4, code, captured));
|
|
42032
42348
|
}
|
|
42349
|
+
async openPrivateSkillHistory(email4, code, context) {
|
|
42350
|
+
const origin = this.apiOrigin, captured = workspaceContext(context);
|
|
42351
|
+
return new RemotePrivateSkillHistoryClient(origin, await this.switchWorkspace(email4, code, captured));
|
|
42352
|
+
}
|
|
42033
42353
|
requestInvitationEmailChallenge(input2) {
|
|
42034
42354
|
return requestInvitationEmail(this.apiOrigin, "challenge", input2);
|
|
42035
42355
|
}
|
|
@@ -42202,10 +42522,10 @@ var init_remote_auth = __esm(() => {
|
|
|
42202
42522
|
});
|
|
42203
42523
|
|
|
42204
42524
|
// src/lib/workspace-profile.ts
|
|
42205
|
-
import { constants as constants17, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as
|
|
42525
|
+
import { constants as constants17, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as lstatSync26, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync2, openSync as openSync19, readFileSync as readFileSync21, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
|
|
42206
42526
|
function stat2(path) {
|
|
42207
42527
|
try {
|
|
42208
|
-
return
|
|
42528
|
+
return lstatSync26(path);
|
|
42209
42529
|
} catch (error61) {
|
|
42210
42530
|
if (error61.code === "ENOENT")
|
|
42211
42531
|
return null;
|
|
@@ -42220,18 +42540,18 @@ function safeText(file2) {
|
|
|
42220
42540
|
const s = fstatSync19(fd);
|
|
42221
42541
|
if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
|
|
42222
42542
|
return fail("The selected profile must use bounded owner-only regular files.");
|
|
42223
|
-
return
|
|
42543
|
+
return readFileSync21(fd, "utf8");
|
|
42224
42544
|
} finally {
|
|
42225
42545
|
closeSync19(fd);
|
|
42226
42546
|
}
|
|
42227
42547
|
}
|
|
42228
42548
|
function checkIdentityMetadata(file2, identity4) {
|
|
42229
|
-
const
|
|
42230
|
-
if (
|
|
42549
|
+
const text4 = safeText(file2);
|
|
42550
|
+
if (text4 === null)
|
|
42231
42551
|
return;
|
|
42232
42552
|
let value;
|
|
42233
42553
|
try {
|
|
42234
|
-
value = JSON.parse(
|
|
42554
|
+
value = JSON.parse(text4);
|
|
42235
42555
|
} catch {
|
|
42236
42556
|
return fail("The profile identity metadata is invalid. Sign in again before managing this workspace.");
|
|
42237
42557
|
}
|
|
@@ -42434,8 +42754,8 @@ var init_recurring_customer = __esm(() => {
|
|
|
42434
42754
|
});
|
|
42435
42755
|
|
|
42436
42756
|
// src/lib/recurring-recovery.ts
|
|
42437
|
-
import { constants as constants18, closeSync as closeSync20, fsyncSync as fsyncSync5, fstatSync as fstatSync20, lstatSync as
|
|
42438
|
-
import { dirname as
|
|
42757
|
+
import { constants as constants18, closeSync as closeSync20, fsyncSync as fsyncSync5, fstatSync as fstatSync20, lstatSync as lstatSync27, mkdirSync as mkdirSync11, openSync as openSync20, readSync as readSync13, realpathSync as realpathSync11, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
42758
|
+
import { dirname as dirname26, isAbsolute as isAbsolute24, join as join36, resolve as resolve25 } from "path";
|
|
42439
42759
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
42440
42760
|
|
|
42441
42761
|
class RecoveryOwner {
|
|
@@ -42445,12 +42765,12 @@ class RecoveryOwner {
|
|
|
42445
42765
|
this.directory = directory;
|
|
42446
42766
|
if (!isAbsolute24(directory) || resolve25(directory) !== directory || realpathSync11(directory) !== directory)
|
|
42447
42767
|
invalid5();
|
|
42448
|
-
for (let path = directory;; path =
|
|
42449
|
-
const stat3 =
|
|
42768
|
+
for (let path = directory;; path = dirname26(path)) {
|
|
42769
|
+
const stat3 = lstatSync27(path);
|
|
42450
42770
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
42451
42771
|
invalid5();
|
|
42452
42772
|
this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
|
|
42453
|
-
if (path ===
|
|
42773
|
+
if (path === dirname26(path))
|
|
42454
42774
|
break;
|
|
42455
42775
|
}
|
|
42456
42776
|
this.assert();
|
|
@@ -42459,17 +42779,17 @@ class RecoveryOwner {
|
|
|
42459
42779
|
if (realpathSync11(this.directory) !== this.directory)
|
|
42460
42780
|
invalid5();
|
|
42461
42781
|
for (const prior of this.parents) {
|
|
42462
|
-
const now =
|
|
42782
|
+
const now = lstatSync27(prior.path);
|
|
42463
42783
|
if (!now.isDirectory() || now.isSymbolicLink() || now.dev !== prior.dev || now.ino !== prior.ino)
|
|
42464
42784
|
invalid5();
|
|
42465
42785
|
}
|
|
42466
|
-
const own2 =
|
|
42786
|
+
const own2 = lstatSync27(this.directory);
|
|
42467
42787
|
if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
42468
42788
|
invalid5();
|
|
42469
42789
|
}
|
|
42470
42790
|
read(name) {
|
|
42471
42791
|
this.assert();
|
|
42472
|
-
const fd = openSync20(
|
|
42792
|
+
const fd = openSync20(join36(this.directory, name), constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
|
|
42473
42793
|
try {
|
|
42474
42794
|
const before = fstatSync20(fd);
|
|
42475
42795
|
if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
|
|
@@ -42482,7 +42802,7 @@ class RecoveryOwner {
|
|
|
42482
42802
|
break;
|
|
42483
42803
|
size += n2;
|
|
42484
42804
|
}
|
|
42485
|
-
const after = fstatSync20(fd), path =
|
|
42805
|
+
const after = fstatSync20(fd), path = lstatSync27(join36(this.directory, name));
|
|
42486
42806
|
if (size !== before.size || after.size !== before.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || path.dev !== before.dev || path.ino !== before.ino || !path.isFile() || path.isSymbolicLink())
|
|
42487
42807
|
invalid5();
|
|
42488
42808
|
this.assert();
|
|
@@ -42495,7 +42815,7 @@ class RecoveryOwner {
|
|
|
42495
42815
|
this.assert();
|
|
42496
42816
|
const bytes = canonicalJson2(value, 8192) + `
|
|
42497
42817
|
`;
|
|
42498
|
-
const fd = openSync20(
|
|
42818
|
+
const fd = openSync20(join36(this.directory, name), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
|
|
42499
42819
|
try {
|
|
42500
42820
|
writeFileSync9(fd, bytes);
|
|
42501
42821
|
fsyncSync5(fd);
|
|
@@ -42522,14 +42842,14 @@ class RecoveryOwner {
|
|
|
42522
42842
|
if (this.read("state.json") !== expected)
|
|
42523
42843
|
invalid5();
|
|
42524
42844
|
this.assert();
|
|
42525
|
-
renameSync6(
|
|
42845
|
+
renameSync6(join36(this.directory, name), join36(this.directory, "state.json"));
|
|
42526
42846
|
this.sync();
|
|
42527
42847
|
}
|
|
42528
42848
|
async locked(action) {
|
|
42529
42849
|
this.assert();
|
|
42530
42850
|
let fd;
|
|
42531
42851
|
try {
|
|
42532
|
-
fd = openSync20(
|
|
42852
|
+
fd = openSync20(join36(this.directory, "operation.lock"), constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
|
|
42533
42853
|
} catch {
|
|
42534
42854
|
throw new RecurringCustomerError("RECURRING_RECOVERY_BUSY", "Recovery is locked. Confirm the original process has stopped before explicitly reconciling the retained lock; no request was retried.");
|
|
42535
42855
|
}
|
|
@@ -42542,10 +42862,10 @@ class RecoveryOwner {
|
|
|
42542
42862
|
} finally {
|
|
42543
42863
|
closeSync20(fd);
|
|
42544
42864
|
this.assert();
|
|
42545
|
-
const now =
|
|
42865
|
+
const now = lstatSync27(join36(this.directory, "operation.lock"));
|
|
42546
42866
|
if (owner2.dev !== now.dev || owner2.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
|
|
42547
42867
|
invalid5();
|
|
42548
|
-
unlinkSync5(
|
|
42868
|
+
unlinkSync5(join36(this.directory, "operation.lock"));
|
|
42549
42869
|
this.sync();
|
|
42550
42870
|
}
|
|
42551
42871
|
}
|
|
@@ -42578,7 +42898,7 @@ function base(customer, organizationId) {
|
|
|
42578
42898
|
};
|
|
42579
42899
|
}
|
|
42580
42900
|
function create(directory, intent) {
|
|
42581
|
-
if (!isAbsolute24(directory) || resolve25(directory) !== directory || realpathSync11(
|
|
42901
|
+
if (!isAbsolute24(directory) || resolve25(directory) !== directory || realpathSync11(dirname26(directory)) !== dirname26(directory))
|
|
42582
42902
|
invalid5();
|
|
42583
42903
|
mkdirSync11(directory, { mode: 448 });
|
|
42584
42904
|
const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
|
|
@@ -44315,17 +44635,17 @@ var init_tool_primitives = __esm(() => {
|
|
|
44315
44635
|
|
|
44316
44636
|
// src/lib/compact-output.ts
|
|
44317
44637
|
function truncateText(value, maxChars = 96) {
|
|
44318
|
-
const
|
|
44319
|
-
if (
|
|
44320
|
-
return
|
|
44321
|
-
return `${
|
|
44638
|
+
const text4 = String(value ?? "").replace(/\s+/g, " ").trim();
|
|
44639
|
+
if (text4.length <= maxChars)
|
|
44640
|
+
return text4;
|
|
44641
|
+
return `${text4.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
|
|
44322
44642
|
}
|
|
44323
44643
|
function previewText(value, maxChars = DEFAULT_PREVIEW_CHARS) {
|
|
44324
|
-
const
|
|
44644
|
+
const text4 = String(value ?? "");
|
|
44325
44645
|
return {
|
|
44326
|
-
text:
|
|
44327
|
-
length:
|
|
44328
|
-
truncated:
|
|
44646
|
+
text: text4.length > maxChars ? `${text4.slice(0, Math.max(0, maxChars - 3))}...` : text4,
|
|
44647
|
+
length: text4.length,
|
|
44648
|
+
truncated: text4.length > maxChars
|
|
44329
44649
|
};
|
|
44330
44650
|
}
|
|
44331
44651
|
function parsePageLimit(value, fallback, options = {}) {
|
|
@@ -44675,21 +44995,21 @@ var init_credential_state = __esm(() => {
|
|
|
44675
44995
|
});
|
|
44676
44996
|
|
|
44677
44997
|
// src/lib/run-state.ts
|
|
44678
|
-
import { createHash as
|
|
44679
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync12, readFileSync as
|
|
44680
|
-
import { extname, join as
|
|
44998
|
+
import { createHash as createHash28, randomBytes } from "crypto";
|
|
44999
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync12, readFileSync as readFileSync22, readdirSync as readdirSync12, statSync as statSync11, writeFileSync as writeFileSync10 } from "fs";
|
|
45000
|
+
import { extname, join as join37, relative as relative9 } from "path";
|
|
44681
45001
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
44682
45002
|
const now = new Date;
|
|
44683
45003
|
const id = createRunId(now);
|
|
44684
45004
|
const day = now.toISOString().slice(0, 10);
|
|
44685
45005
|
const skillName = normalizeSkillName(params.skill);
|
|
44686
45006
|
const root = getProjectStateDir(targetDir);
|
|
44687
|
-
const runDir =
|
|
44688
|
-
const logsDir =
|
|
44689
|
-
const exportDir =
|
|
45007
|
+
const runDir = join37(root, "runs", day, id);
|
|
45008
|
+
const logsDir = join37(runDir, "logs");
|
|
45009
|
+
const exportDir = join37(root, "exports", skillName, id);
|
|
44690
45010
|
mkdirSync12(logsDir, { recursive: true });
|
|
44691
45011
|
mkdirSync12(exportDir, { recursive: true });
|
|
44692
|
-
mkdirSync12(
|
|
45012
|
+
mkdirSync12(join37(root, "tmp"), { recursive: true });
|
|
44693
45013
|
const record11 = {
|
|
44694
45014
|
id,
|
|
44695
45015
|
skill: skillName,
|
|
@@ -44741,22 +45061,22 @@ function updateSkillRun(context2, patch) {
|
|
|
44741
45061
|
return context2.record;
|
|
44742
45062
|
}
|
|
44743
45063
|
function writeRunLogs(context2, stdout = "", stderr = "") {
|
|
44744
|
-
writeFileSync10(
|
|
44745
|
-
writeFileSync10(
|
|
45064
|
+
writeFileSync10(join37(context2.logsDir, "stdout.log"), stdout);
|
|
45065
|
+
writeFileSync10(join37(context2.logsDir, "stderr.log"), stderr);
|
|
44746
45066
|
}
|
|
44747
45067
|
function appendRunEvent(context2, event, data = {}) {
|
|
44748
45068
|
const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
|
|
44749
45069
|
`;
|
|
44750
|
-
const path =
|
|
44751
|
-
const previous = existsSync15(path) ?
|
|
45070
|
+
const path = join37(context2.runDir, "events.ndjson");
|
|
45071
|
+
const previous = existsSync15(path) ? readFileSync22(path, "utf-8") : "";
|
|
44752
45072
|
writeFileSync10(path, previous + line);
|
|
44753
45073
|
}
|
|
44754
45074
|
function findSkillRun(runId, targetDir = process.cwd()) {
|
|
44755
|
-
const runsRoot =
|
|
45075
|
+
const runsRoot = join37(getProjectStateDir(targetDir), "runs");
|
|
44756
45076
|
if (!existsSync15(runsRoot))
|
|
44757
45077
|
return null;
|
|
44758
|
-
for (const day of
|
|
44759
|
-
const record11 = readRunRecord(
|
|
45078
|
+
for (const day of readdirSync12(runsRoot)) {
|
|
45079
|
+
const record11 = readRunRecord(join37(runsRoot, day, runId));
|
|
44760
45080
|
if (record11)
|
|
44761
45081
|
return record11;
|
|
44762
45082
|
}
|
|
@@ -44773,11 +45093,11 @@ function skillRunEnv(context2) {
|
|
|
44773
45093
|
};
|
|
44774
45094
|
}
|
|
44775
45095
|
function writeRunRecord(context2) {
|
|
44776
|
-
writeFileSync10(
|
|
45096
|
+
writeFileSync10(join37(context2.runDir, "run.json"), JSON.stringify(context2.record, null, 2) + `
|
|
44777
45097
|
`);
|
|
44778
45098
|
}
|
|
44779
45099
|
function writeArtifactsManifest(context2, artifacts) {
|
|
44780
|
-
writeFileSync10(
|
|
45100
|
+
writeFileSync10(join37(context2.runDir, "artifacts.json"), JSON.stringify({ runId: context2.record.id, artifacts }, null, 2) + `
|
|
44781
45101
|
`);
|
|
44782
45102
|
}
|
|
44783
45103
|
function collectRunArtifacts(context2) {
|
|
@@ -44786,30 +45106,30 @@ function collectRunArtifacts(context2) {
|
|
|
44786
45106
|
const artifacts = [];
|
|
44787
45107
|
for (const path of walkFiles(context2.exportDir)) {
|
|
44788
45108
|
const stat3 = statSync11(path);
|
|
44789
|
-
const bytes =
|
|
45109
|
+
const bytes = readFileSync22(path);
|
|
44790
45110
|
artifacts.push({
|
|
44791
45111
|
path: toProjectRelative(context2.targetDir, path),
|
|
44792
45112
|
mime: mimeForPath(path),
|
|
44793
|
-
sha256:
|
|
45113
|
+
sha256: createHash28("sha256").update(bytes).digest("hex"),
|
|
44794
45114
|
sizeBytes: stat3.size
|
|
44795
45115
|
});
|
|
44796
45116
|
}
|
|
44797
45117
|
return artifacts.sort((a, b) => a.path.localeCompare(b.path));
|
|
44798
45118
|
}
|
|
44799
45119
|
function readRunRecord(runDir) {
|
|
44800
|
-
const path =
|
|
45120
|
+
const path = join37(runDir, "run.json");
|
|
44801
45121
|
if (!existsSync15(path))
|
|
44802
45122
|
return null;
|
|
44803
45123
|
try {
|
|
44804
|
-
return JSON.parse(
|
|
45124
|
+
return JSON.parse(readFileSync22(path, "utf-8"));
|
|
44805
45125
|
} catch {
|
|
44806
45126
|
return null;
|
|
44807
45127
|
}
|
|
44808
45128
|
}
|
|
44809
45129
|
function walkFiles(dir) {
|
|
44810
45130
|
const files = [];
|
|
44811
|
-
for (const entry of
|
|
44812
|
-
const full =
|
|
45131
|
+
for (const entry of readdirSync12(dir)) {
|
|
45132
|
+
const full = join37(dir, entry);
|
|
44813
45133
|
if (statSync11(full).isDirectory())
|
|
44814
45134
|
files.push(...walkFiles(full));
|
|
44815
45135
|
else
|
|
@@ -45062,11 +45382,11 @@ var init_cloud_executions = __esm(() => {
|
|
|
45062
45382
|
// node_modules/@hasna/secrets/dist/sdk.js
|
|
45063
45383
|
import { isIP as isIP2 } from "net";
|
|
45064
45384
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
45065
|
-
import { closeSync as closeSync21, fstatSync as fstatSync21, openSync as openSync21, readFileSync as
|
|
45385
|
+
import { closeSync as closeSync21, fstatSync as fstatSync21, openSync as openSync21, readFileSync as readFileSync23 } from "fs";
|
|
45066
45386
|
import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
|
|
45067
45387
|
import { createRequire as createRequire2 } from "module";
|
|
45068
45388
|
import { hostname as osHostname2 } from "os";
|
|
45069
|
-
import { isAbsolute as isAbsolute26, join as
|
|
45389
|
+
import { isAbsolute as isAbsolute26, join as join38 } from "path";
|
|
45070
45390
|
import { createRequire as createRequire22 } from "module";
|
|
45071
45391
|
function envToken2(name) {
|
|
45072
45392
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -45097,14 +45417,14 @@ function hasnaHomeDir2(env) {
|
|
|
45097
45417
|
if (override)
|
|
45098
45418
|
return override;
|
|
45099
45419
|
const home = homeDir2(env);
|
|
45100
|
-
return home ?
|
|
45420
|
+
return home ? join38(home, HASNA_HOME_DIR2) : null;
|
|
45101
45421
|
}
|
|
45102
45422
|
function appConfigDir2(name, env) {
|
|
45103
45423
|
const configRoot = absoluteOverride2(env, HASNA_CONFIG_HOME_ENV_KEY2);
|
|
45104
45424
|
if (configRoot)
|
|
45105
|
-
return
|
|
45425
|
+
return join38(configRoot, name);
|
|
45106
45426
|
const root = hasnaHomeDir2(env);
|
|
45107
|
-
return root ?
|
|
45427
|
+
return root ? join38(root, name, CONFIG_SUBDIR2) : null;
|
|
45108
45428
|
}
|
|
45109
45429
|
function credentialDiskSourceList2(name, env, profile = null) {
|
|
45110
45430
|
if (!SAFE_APP_SLUG2.test(name))
|
|
@@ -45113,7 +45433,7 @@ function credentialDiskSourceList2(name, env, profile = null) {
|
|
|
45113
45433
|
if (!directory2)
|
|
45114
45434
|
return [];
|
|
45115
45435
|
const file2 = profile ? `${CREDENTIALS_FILE2}-${profile}` : CREDENTIALS_FILE2;
|
|
45116
|
-
return [{ path:
|
|
45436
|
+
return [{ path: join38(directory2, file2), tier: "disk" }];
|
|
45117
45437
|
}
|
|
45118
45438
|
function credentialDiskSources2(name, env) {
|
|
45119
45439
|
return credentialDiskSourceList2(name, env, null).map((s) => s.path);
|
|
@@ -45121,10 +45441,10 @@ function credentialDiskSources2(name, env) {
|
|
|
45121
45441
|
function profileDiskSources2(name, env, profile) {
|
|
45122
45442
|
return credentialDiskSourceList2(name, env, profile).map((s) => s.path);
|
|
45123
45443
|
}
|
|
45124
|
-
function parseEnvFile2(
|
|
45444
|
+
function parseEnvFile2(text4) {
|
|
45125
45445
|
const values = new Map;
|
|
45126
45446
|
const unusable = new Set;
|
|
45127
|
-
for (const rawLine of
|
|
45447
|
+
for (const rawLine of text4.split(/\r?\n/)) {
|
|
45128
45448
|
const line = rawLine.trim();
|
|
45129
45449
|
if (line.length === 0 || line.startsWith("#"))
|
|
45130
45450
|
continue;
|
|
@@ -45188,7 +45508,7 @@ function readAppConfigFile2(path) {
|
|
|
45188
45508
|
unsafe("the file is not owned by the current user");
|
|
45189
45509
|
if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
|
|
45190
45510
|
unsafe("the file exceeds the size limit");
|
|
45191
|
-
const bytes =
|
|
45511
|
+
const bytes = readFileSync23(fd);
|
|
45192
45512
|
const after = fstatSync21(fd);
|
|
45193
45513
|
if (!configFileReadsCoherent2(before, after)) {
|
|
45194
45514
|
unsafe("the file changed while being read");
|
|
@@ -45364,8 +45684,8 @@ function keychainAccount2(env, options) {
|
|
|
45364
45684
|
const user = env.USER?.trim();
|
|
45365
45685
|
return user || null;
|
|
45366
45686
|
}
|
|
45367
|
-
function keychainFailureHint2(
|
|
45368
|
-
const line =
|
|
45687
|
+
function keychainFailureHint2(text4) {
|
|
45688
|
+
const line = text4.split(/\r?\n/).find((entry) => entry.trim().length > 0)?.trim() ?? "";
|
|
45369
45689
|
const clean = line.replace(/[\u0000-\u001f\u007f]/g, "").slice(0, 200);
|
|
45370
45690
|
return clean ? `: ${clean}` : "";
|
|
45371
45691
|
}
|
|
@@ -45943,12 +46263,12 @@ function createHasnaHttpTransportInternal(options, requestBindingProvider) {
|
|
|
45943
46263
|
await response.body?.cancel();
|
|
45944
46264
|
} catch {}
|
|
45945
46265
|
} else {
|
|
45946
|
-
const
|
|
45947
|
-
if (
|
|
46266
|
+
const text4 = await response.text();
|
|
46267
|
+
if (text4.length > 0) {
|
|
45948
46268
|
try {
|
|
45949
|
-
parsed = JSON.parse(
|
|
46269
|
+
parsed = JSON.parse(text4);
|
|
45950
46270
|
} catch {
|
|
45951
|
-
parsed =
|
|
46271
|
+
parsed = text4;
|
|
45952
46272
|
}
|
|
45953
46273
|
}
|
|
45954
46274
|
}
|
|
@@ -46051,13 +46371,13 @@ class SecretsClient {
|
|
|
46051
46371
|
headers,
|
|
46052
46372
|
redirect: "manual"
|
|
46053
46373
|
});
|
|
46054
|
-
const
|
|
46374
|
+
const text4 = await response.text();
|
|
46055
46375
|
let body = undefined;
|
|
46056
|
-
if (
|
|
46376
|
+
if (text4) {
|
|
46057
46377
|
try {
|
|
46058
|
-
body = JSON.parse(
|
|
46378
|
+
body = JSON.parse(text4);
|
|
46059
46379
|
} catch {
|
|
46060
|
-
body =
|
|
46380
|
+
body = text4;
|
|
46061
46381
|
}
|
|
46062
46382
|
}
|
|
46063
46383
|
if (!response.ok) {
|
|
@@ -46459,7 +46779,7 @@ async function resolveSelectedSecrets(bindings, createClient = createSecretsClie
|
|
|
46459
46779
|
return refuse5("LOCAL_SECRET_UNAVAILABLE", "A declared secret could not be resolved, was invalid, or has expired. The skill was not started; no fallback was attempted.");
|
|
46460
46780
|
}
|
|
46461
46781
|
}
|
|
46462
|
-
function redactExecutionSecrets(
|
|
46782
|
+
function redactExecutionSecrets(text4, env) {
|
|
46463
46783
|
const values = new Set(Object.values(env).flatMap((value) => {
|
|
46464
46784
|
let encoded = "";
|
|
46465
46785
|
try {
|
|
@@ -46468,8 +46788,8 @@ function redactExecutionSecrets(text3, env) {
|
|
|
46468
46788
|
return [value, JSON.stringify(value).slice(1, -1), Buffer.from(value).toString("base64"), encoded];
|
|
46469
46789
|
}));
|
|
46470
46790
|
for (const value of [...values].filter(Boolean).sort((a, b) => b.length - a.length))
|
|
46471
|
-
|
|
46472
|
-
return
|
|
46791
|
+
text4 = text4.split(value).join("[REDACTED]");
|
|
46792
|
+
return text4;
|
|
46473
46793
|
}
|
|
46474
46794
|
var init_execution_secrets = __esm(() => {
|
|
46475
46795
|
init_sdk();
|
|
@@ -46608,10 +46928,10 @@ __export(exports_selected_run, {
|
|
|
46608
46928
|
executeSelectedLocal: () => executeSelectedLocal,
|
|
46609
46929
|
declaredOperation: () => declaredOperation
|
|
46610
46930
|
});
|
|
46611
|
-
import { createHash as
|
|
46931
|
+
import { createHash as createHash29 } from "crypto";
|
|
46612
46932
|
import { spawn as spawn2 } from "child_process";
|
|
46613
46933
|
import { mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync11, realpathSync as realpathSync13 } from "fs";
|
|
46614
|
-
import { dirname as
|
|
46934
|
+
import { dirname as dirname27, join as join39, resolve as resolve26 } from "path";
|
|
46615
46935
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
46616
46936
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
46617
46937
|
const context2 = await resolveSelectionContext(profileId, options);
|
|
@@ -46734,7 +47054,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
46734
47054
|
throw new SkillSelectionError("INVALID_SECRET_BINDINGS", "Explicit environment values must be bounded strings without NUL bytes.");
|
|
46735
47055
|
secretEnv[name] = value;
|
|
46736
47056
|
}
|
|
46737
|
-
const runDirectory = mkdtempSync3(
|
|
47057
|
+
const runDirectory = mkdtempSync3(join39(tmpdir(), "skills-execution-"));
|
|
46738
47058
|
const paths = new SkillEntryPaths;
|
|
46739
47059
|
for (const entry of entries) {
|
|
46740
47060
|
paths.add(entry.path, 100, () => {
|
|
@@ -46742,8 +47062,8 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
46742
47062
|
}, () => {
|
|
46743
47063
|
throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
|
|
46744
47064
|
});
|
|
46745
|
-
const destination =
|
|
46746
|
-
mkdirSync13(
|
|
47065
|
+
const destination = join39(runDirectory, entry.path);
|
|
47066
|
+
mkdirSync13(dirname27(destination), { recursive: true, mode: 448 });
|
|
46747
47067
|
writeFileSync11(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
|
|
46748
47068
|
}
|
|
46749
47069
|
env.SKILLS_INPUT_JSON = input2;
|
|
@@ -46770,7 +47090,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
46770
47090
|
}
|
|
46771
47091
|
if (bindings)
|
|
46772
47092
|
secretEnv = await resolveSelectedSecrets(bindings, options.createSecretsClient);
|
|
46773
|
-
const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [],
|
|
47093
|
+
const result = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], join39(runDirectory, declaredEntry), ...args], runDirectory, { ...env, ...secretEnv }, input2, timeoutMs);
|
|
46774
47094
|
result.stdout = redactExecutionSecrets(result.stdout, secretEnv);
|
|
46775
47095
|
result.stderr = redactExecutionSecrets(result.stderr, secretEnv);
|
|
46776
47096
|
const receipt = {
|
|
@@ -46778,13 +47098,13 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
46778
47098
|
target: "local",
|
|
46779
47099
|
runtime: runtimeName,
|
|
46780
47100
|
entrypoint: declaredEntry,
|
|
46781
|
-
inputDigest: `sha256:${
|
|
47101
|
+
inputDigest: `sha256:${createHash29("sha256").update(input2).digest("hex")}`,
|
|
46782
47102
|
runDirectory,
|
|
46783
47103
|
...executionGrant ? { executionGrant } : {},
|
|
46784
47104
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
46785
47105
|
...result
|
|
46786
47106
|
};
|
|
46787
|
-
writeFileSync11(
|
|
47107
|
+
writeFileSync11(join39(runDirectory, ".execution-receipt.json"), JSON.stringify({ ...receipt, stdout: undefined, stderr: undefined }), { mode: 384 });
|
|
46788
47108
|
return receipt;
|
|
46789
47109
|
}
|
|
46790
47110
|
async function subprocess(command, cwd, env, input2, timeoutMs) {
|
|
@@ -46973,8 +47293,8 @@ var init_blog_article = __esm(() => {
|
|
|
46973
47293
|
});
|
|
46974
47294
|
|
|
46975
47295
|
// src/mcp/operation-tools.ts
|
|
46976
|
-
import { existsSync as existsSync16, readdirSync as
|
|
46977
|
-
import { join as
|
|
47296
|
+
import { existsSync as existsSync16, readdirSync as readdirSync13, statSync as statSync12 } from "fs";
|
|
47297
|
+
import { join as join40 } from "path";
|
|
46978
47298
|
function registerOperationTools(server) {
|
|
46979
47299
|
server.registerTool("cloud_skill_eligibility", {
|
|
46980
47300
|
title: "Cloud Skill Eligibility",
|
|
@@ -47455,8 +47775,8 @@ function registerOperationTools(server) {
|
|
|
47455
47775
|
let skillCount = 0;
|
|
47456
47776
|
if (exists) {
|
|
47457
47777
|
try {
|
|
47458
|
-
skillCount =
|
|
47459
|
-
const full =
|
|
47778
|
+
skillCount = readdirSync13(agentSkillsPath).filter((f) => {
|
|
47779
|
+
const full = join40(agentSkillsPath, f);
|
|
47460
47780
|
return !f.startsWith(".") && statSync12(full).isDirectory();
|
|
47461
47781
|
}).length;
|
|
47462
47782
|
} catch {}
|
|
@@ -47524,14 +47844,14 @@ var init_operation_tools = __esm(() => {
|
|
|
47524
47844
|
|
|
47525
47845
|
// src/lib/feedback.ts
|
|
47526
47846
|
import { appendFileSync, existsSync as existsSync17, mkdirSync as mkdirSync14 } from "fs";
|
|
47527
|
-
import { dirname as
|
|
47847
|
+
import { dirname as dirname28, join as join41 } from "path";
|
|
47528
47848
|
import { Database } from "bun:sqlite";
|
|
47529
47849
|
function getFeedbackDbPath() {
|
|
47530
|
-
return
|
|
47850
|
+
return join41(getDataDir(), "skills.db");
|
|
47531
47851
|
}
|
|
47532
47852
|
function getFeedbackDb() {
|
|
47533
47853
|
const dbPath = getFeedbackDbPath();
|
|
47534
|
-
const dir =
|
|
47854
|
+
const dir = dirname28(dbPath);
|
|
47535
47855
|
if (!existsSync17(dir))
|
|
47536
47856
|
mkdirSync14(dir, { recursive: true });
|
|
47537
47857
|
const db = new Database(dbPath);
|
|
@@ -47559,8 +47879,8 @@ function saveFeedback(input2) {
|
|
|
47559
47879
|
throw new Error("Feedback message is required");
|
|
47560
47880
|
const category = input2.category ?? "general";
|
|
47561
47881
|
if (isApiMode()) {
|
|
47562
|
-
const path =
|
|
47563
|
-
const dir =
|
|
47882
|
+
const path = join41(getDataDir(), "feedback.jsonl");
|
|
47883
|
+
const dir = dirname28(path);
|
|
47564
47884
|
if (!existsSync17(dir))
|
|
47565
47885
|
mkdirSync14(dir, { recursive: true });
|
|
47566
47886
|
appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
|
|
@@ -47723,23 +48043,23 @@ var init_resource_meta_tools = __esm(() => {
|
|
|
47723
48043
|
});
|
|
47724
48044
|
|
|
47725
48045
|
// src/lib/scheduler.ts
|
|
47726
|
-
import { existsSync as existsSync18, readFileSync as
|
|
47727
|
-
import { join as
|
|
48046
|
+
import { existsSync as existsSync18, readFileSync as readFileSync24, writeFileSync as writeFileSync12, mkdirSync as mkdirSync15 } from "fs";
|
|
48047
|
+
import { join as join42 } from "path";
|
|
47728
48048
|
function getSchedulesPath(targetDir = process.cwd()) {
|
|
47729
|
-
return
|
|
48049
|
+
return join42(targetDir, ".skills", "schedules.json");
|
|
47730
48050
|
}
|
|
47731
48051
|
function loadSchedules(targetDir = process.cwd()) {
|
|
47732
48052
|
const path = getSchedulesPath(targetDir);
|
|
47733
48053
|
if (existsSync18(path)) {
|
|
47734
48054
|
try {
|
|
47735
|
-
return JSON.parse(
|
|
48055
|
+
return JSON.parse(readFileSync24(path, "utf-8"));
|
|
47736
48056
|
} catch {}
|
|
47737
48057
|
}
|
|
47738
48058
|
return { version: 1, schedules: [] };
|
|
47739
48059
|
}
|
|
47740
48060
|
function saveSchedules(data, targetDir = process.cwd()) {
|
|
47741
48061
|
const path = getSchedulesPath(targetDir);
|
|
47742
|
-
const dir =
|
|
48062
|
+
const dir = join42(targetDir, ".skills");
|
|
47743
48063
|
if (!existsSync18(dir))
|
|
47744
48064
|
mkdirSync15(dir, { recursive: true });
|
|
47745
48065
|
writeFileSync12(path, JSON.stringify(data, null, 2));
|
|
@@ -48011,16 +48331,16 @@ var init_schedule_tools = __esm(() => {
|
|
|
48011
48331
|
});
|
|
48012
48332
|
|
|
48013
48333
|
// src/lib/native-storage.ts
|
|
48014
|
-
import { createHash as
|
|
48334
|
+
import { createHash as createHash30, createHmac } from "crypto";
|
|
48015
48335
|
import {
|
|
48016
48336
|
existsSync as existsSync19,
|
|
48017
48337
|
mkdirSync as mkdirSync16,
|
|
48018
|
-
readFileSync as
|
|
48019
|
-
readdirSync as
|
|
48338
|
+
readFileSync as readFileSync25,
|
|
48339
|
+
readdirSync as readdirSync14,
|
|
48020
48340
|
statSync as statSync13,
|
|
48021
48341
|
writeFileSync as writeFileSync13
|
|
48022
48342
|
} from "fs";
|
|
48023
|
-
import { dirname as
|
|
48343
|
+
import { dirname as dirname29, join as join43, normalize as normalize5, relative as relative10, sep as sep14 } from "path";
|
|
48024
48344
|
function resolveSkillsNativeStorageConfig(env = process.env) {
|
|
48025
48345
|
assertNoRetiredModeEnvVars(env, {
|
|
48026
48346
|
app: SKILLS_ENV_NAMESPACE,
|
|
@@ -48061,7 +48381,7 @@ function getSkillsNativeStorageStatus(options = {}) {
|
|
|
48061
48381
|
local: {
|
|
48062
48382
|
dataDir: getDataDir(),
|
|
48063
48383
|
projectStateDir: getProjectStateDir(targetDir),
|
|
48064
|
-
feedbackDbPath:
|
|
48384
|
+
feedbackDbPath: join43(getDataDir(), "skills.db")
|
|
48065
48385
|
},
|
|
48066
48386
|
remote: {
|
|
48067
48387
|
databaseConfigured: Boolean(config2.databaseUrl),
|
|
@@ -48083,12 +48403,12 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
48083
48403
|
const files = [];
|
|
48084
48404
|
if (existsSync19(projectStateDir)) {
|
|
48085
48405
|
for (const filePath of walkFiles2(projectStateDir)) {
|
|
48086
|
-
const bytes =
|
|
48406
|
+
const bytes = readFileSync25(filePath);
|
|
48087
48407
|
const relativePath = toPosix(relative10(targetDir, filePath));
|
|
48088
48408
|
files.push({
|
|
48089
48409
|
path: relativePath,
|
|
48090
48410
|
sizeBytes: bytes.byteLength,
|
|
48091
|
-
sha256:
|
|
48411
|
+
sha256: createHash30("sha256").update(bytes).digest("hex"),
|
|
48092
48412
|
...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
|
|
48093
48413
|
});
|
|
48094
48414
|
}
|
|
@@ -48141,8 +48461,8 @@ function parsePositiveInteger(value) {
|
|
|
48141
48461
|
}
|
|
48142
48462
|
function walkFiles2(dir) {
|
|
48143
48463
|
const files = [];
|
|
48144
|
-
for (const entry of
|
|
48145
|
-
const full =
|
|
48464
|
+
for (const entry of readdirSync14(dir)) {
|
|
48465
|
+
const full = join43(dir, entry);
|
|
48146
48466
|
const stats = statSync13(full);
|
|
48147
48467
|
if (stats.isDirectory())
|
|
48148
48468
|
files.push(...walkFiles2(full));
|
|
@@ -48360,7 +48680,7 @@ var init_remote_invitation_tools = __esm(() => {
|
|
|
48360
48680
|
});
|
|
48361
48681
|
|
|
48362
48682
|
// src/lib/private-publication-customer.ts
|
|
48363
|
-
function
|
|
48683
|
+
function preparePrivateSession(requested, action, open2) {
|
|
48364
48684
|
const selectors = [
|
|
48365
48685
|
"HASNA_PROFILE",
|
|
48366
48686
|
"HASNA_HOME",
|
|
@@ -48374,7 +48694,7 @@ function preparePrivatePublicationSession(requested) {
|
|
|
48374
48694
|
"SKILLS_API_KEY"
|
|
48375
48695
|
];
|
|
48376
48696
|
const before = new Map(selectors.map((key2) => [key2, process.env[key2]]));
|
|
48377
|
-
const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace(
|
|
48697
|
+
const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace(action);
|
|
48378
48698
|
const captured = requested ? { ...requested } : undefined;
|
|
48379
48699
|
const unchanged3 = () => {
|
|
48380
48700
|
if (selectors.some((key2) => process.env[key2] !== before.get(key2)) || selectedSkillsProfile(process.env) !== profile)
|
|
@@ -48388,12 +48708,15 @@ function preparePrivatePublicationSession(requested) {
|
|
|
48388
48708
|
throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide the observed user and membership IDs, or select an enrolled workspace profile.");
|
|
48389
48709
|
unchanged3();
|
|
48390
48710
|
target.unchanged();
|
|
48391
|
-
const client = await new RemoteSkillsAuthClient(target.origin)
|
|
48711
|
+
const client = await open2(new RemoteSkillsAuthClient(target.origin), email5, code2, context2);
|
|
48392
48712
|
unchanged3();
|
|
48393
48713
|
target.unchanged();
|
|
48394
48714
|
return client;
|
|
48395
48715
|
} };
|
|
48396
48716
|
}
|
|
48717
|
+
function preparePrivatePublicationSession(requested) {
|
|
48718
|
+
return preparePrivateSession(requested, "Manage private publications", (auth, email5, code2, context2) => auth.openPrivatePublications(email5, code2, context2));
|
|
48719
|
+
}
|
|
48397
48720
|
async function privatePublicationSession(email5, code2, requested) {
|
|
48398
48721
|
return preparePrivatePublicationSession(requested).verify(email5, code2);
|
|
48399
48722
|
}
|
|
@@ -48408,20 +48731,20 @@ var init_private_publication_customer = __esm(() => {
|
|
|
48408
48731
|
});
|
|
48409
48732
|
|
|
48410
48733
|
// src/lib/private-publication-recovery.ts
|
|
48411
|
-
import { constants as constants20, closeSync as closeSync23, fsyncSync as fsyncSync6, fstatSync as fstatSync23, lstatSync as
|
|
48412
|
-
import { dirname as
|
|
48734
|
+
import { constants as constants20, closeSync as closeSync23, fsyncSync as fsyncSync6, fstatSync as fstatSync23, lstatSync as lstatSync28, mkdirSync as mkdirSync17, openSync as openSync23, readSync as readSync15, realpathSync as realpathSync14, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
|
|
48735
|
+
import { dirname as dirname30, isAbsolute as isAbsolute27, join as join44, resolve as resolve27 } from "path";
|
|
48413
48736
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
48414
48737
|
function safeDirectory(directory2) {
|
|
48415
48738
|
if (!isAbsolute27(directory2) || directory2 !== resolve27(directory2) || realpathSync14(directory2) !== directory2)
|
|
48416
48739
|
return fail2();
|
|
48417
|
-
for (let path = directory2;; path =
|
|
48418
|
-
const stat3 =
|
|
48740
|
+
for (let path = directory2;; path = dirname30(path)) {
|
|
48741
|
+
const stat3 = lstatSync28(path);
|
|
48419
48742
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
48420
48743
|
return fail2();
|
|
48421
|
-
if (path ===
|
|
48744
|
+
if (path === dirname30(path))
|
|
48422
48745
|
break;
|
|
48423
48746
|
}
|
|
48424
|
-
const own2 =
|
|
48747
|
+
const own2 = lstatSync28(directory2);
|
|
48425
48748
|
if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
48426
48749
|
return fail2();
|
|
48427
48750
|
return { dev: own2.dev, ino: own2.ino };
|
|
@@ -48432,7 +48755,7 @@ function unchangedDirectory(directory2, identity4) {
|
|
|
48432
48755
|
return fail2();
|
|
48433
48756
|
}
|
|
48434
48757
|
function readOwned(directory2, name, max) {
|
|
48435
|
-
const identity4 = safeDirectory(directory2), file2 =
|
|
48758
|
+
const identity4 = safeDirectory(directory2), file2 = join44(directory2, name);
|
|
48436
48759
|
const fd = openSync23(file2, constants20.O_RDONLY | constants20.O_NOFOLLOW);
|
|
48437
48760
|
try {
|
|
48438
48761
|
const stat3 = fstatSync23(fd);
|
|
@@ -48456,7 +48779,7 @@ function readOwned(directory2, name, max) {
|
|
|
48456
48779
|
}
|
|
48457
48780
|
}
|
|
48458
48781
|
function writeOwned(directory2, name, bytes) {
|
|
48459
|
-
const fd = openSync23(
|
|
48782
|
+
const fd = openSync23(join44(directory2, name), constants20.O_WRONLY | constants20.O_CREAT | constants20.O_EXCL | constants20.O_NOFOLLOW, 384);
|
|
48460
48783
|
try {
|
|
48461
48784
|
writeFileSync14(fd, bytes);
|
|
48462
48785
|
fsyncSync6(fd);
|
|
@@ -48469,7 +48792,7 @@ function save(directory2, value) {
|
|
|
48469
48792
|
writeOwned(directory2, temporary, JSON.stringify(value) + `
|
|
48470
48793
|
`);
|
|
48471
48794
|
unchangedDirectory(directory2, identity4);
|
|
48472
|
-
renameSync7(
|
|
48795
|
+
renameSync7(join44(directory2, temporary), join44(directory2, "receipt.json"));
|
|
48473
48796
|
const fd = openSync23(directory2, constants20.O_RDONLY | constants20.O_NOFOLLOW);
|
|
48474
48797
|
try {
|
|
48475
48798
|
fsyncSync6(fd);
|
|
@@ -48482,7 +48805,7 @@ function bind(client, receipt) {
|
|
|
48482
48805
|
throw new PrivatePublicationError("PUBLICATION_IDENTITY_CHANGED", "The fresh session does not match the recovery directory's server, account and membership.");
|
|
48483
48806
|
}
|
|
48484
48807
|
async function locked(directory2, action) {
|
|
48485
|
-
const identity4 = safeDirectory(directory2), file2 =
|
|
48808
|
+
const identity4 = safeDirectory(directory2), file2 = join44(directory2, "operation.lock");
|
|
48486
48809
|
let fd;
|
|
48487
48810
|
try {
|
|
48488
48811
|
fd = openSync23(file2, constants20.O_WRONLY | constants20.O_CREAT | constants20.O_EXCL | constants20.O_NOFOLLOW, 384);
|
|
@@ -48498,7 +48821,7 @@ async function locked(directory2, action) {
|
|
|
48498
48821
|
} finally {
|
|
48499
48822
|
closeSync23(fd);
|
|
48500
48823
|
unchangedDirectory(directory2, identity4);
|
|
48501
|
-
const now =
|
|
48824
|
+
const now = lstatSync28(file2);
|
|
48502
48825
|
if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
|
|
48503
48826
|
fail2();
|
|
48504
48827
|
unlinkSync6(file2);
|
|
@@ -48550,11 +48873,11 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
|
|
|
48550
48873
|
phase: "prepared",
|
|
48551
48874
|
intent: null
|
|
48552
48875
|
};
|
|
48553
|
-
if (!isAbsolute27(recoveryDirectory) || resolve27(recoveryDirectory) !== recoveryDirectory || realpathSync14(
|
|
48876
|
+
if (!isAbsolute27(recoveryDirectory) || resolve27(recoveryDirectory) !== recoveryDirectory || realpathSync14(dirname30(recoveryDirectory)) !== dirname30(recoveryDirectory))
|
|
48554
48877
|
return fail2();
|
|
48555
48878
|
mkdirSync17(recoveryDirectory, { mode: 448 });
|
|
48556
48879
|
safeDirectory(recoveryDirectory);
|
|
48557
|
-
const parent = openSync23(
|
|
48880
|
+
const parent = openSync23(dirname30(recoveryDirectory), constants20.O_RDONLY | constants20.O_NOFOLLOW);
|
|
48558
48881
|
try {
|
|
48559
48882
|
fsyncSync6(parent);
|
|
48560
48883
|
} finally {
|
|
@@ -49005,13 +49328,13 @@ function legacyInputSchema(rest) {
|
|
|
49005
49328
|
function jsonSchema(schema, io) {
|
|
49006
49329
|
if (schema === undefined || schema === null)
|
|
49007
49330
|
return;
|
|
49008
|
-
const
|
|
49009
|
-
const def =
|
|
49331
|
+
const object8 = isRawShape(schema) ? exports_external.object(schema) : schema;
|
|
49332
|
+
const def = object8._zod?.def;
|
|
49010
49333
|
if (!def)
|
|
49011
49334
|
throw new Error("Skills MCP tool schemas must be built with this package's zod 4");
|
|
49012
49335
|
if (def.type !== "object" && def.shape === undefined)
|
|
49013
49336
|
return;
|
|
49014
|
-
return exports_external.toJSONSchema(
|
|
49337
|
+
return exports_external.toJSONSchema(object8, { target: "draft-7", io });
|
|
49015
49338
|
}
|
|
49016
49339
|
var EMPTY_OBJECT_JSON_SCHEMA;
|
|
49017
49340
|
var init_package_tool_list = __esm(() => {
|