@hasna/skills 0.10.19 → 0.10.20
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 +10 -5
- package/bin/index.js +174 -110
- package/bin/mcp.js +1 -1
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +118 -50
- package/dist/lib/codex-native-skill-catalog.d.ts +16 -0
- package/dist/lib/codex-plugin-skill-controls.d.ts +1 -1
- package/dist/sdk/index.js +120 -54
- package/package.json +1 -1
package/dist/sdk/index.js
CHANGED
|
@@ -25954,12 +25954,12 @@ import fs from "fs/promises";
|
|
|
25954
25954
|
var import_client9, import_config17, import_node_http_handler, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", DEFAULT_LINK_LOCAL_HOST = "http://169.254.170.2", AWS_CONTAINER_CREDENTIALS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI", AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE = "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE", AWS_CONTAINER_AUTHORIZATION_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN", fromHttp = (options = {}) => {
|
|
25955
25955
|
options.logger?.debug("@aws-sdk/credential-provider-http - fromHttp");
|
|
25956
25956
|
let host;
|
|
25957
|
-
const
|
|
25957
|
+
const relative7 = options.awsContainerCredentialsRelativeUri ?? process.env[AWS_CONTAINER_CREDENTIALS_RELATIVE_URI];
|
|
25958
25958
|
const full = options.awsContainerCredentialsFullUri ?? process.env[AWS_CONTAINER_CREDENTIALS_FULL_URI];
|
|
25959
25959
|
const token = options.awsContainerAuthorizationToken ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN];
|
|
25960
25960
|
const tokenFile = options.awsContainerAuthorizationTokenFile ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE];
|
|
25961
25961
|
const warn = options.logger?.constructor?.name === "NoOpLogger" || !options.logger?.warn ? console.warn : options.logger.warn.bind(options.logger);
|
|
25962
|
-
if (
|
|
25962
|
+
if (relative7 && full) {
|
|
25963
25963
|
warn("@aws-sdk/credential-provider-http: " + "you have set both awsContainerCredentialsRelativeUri and awsContainerCredentialsFullUri.");
|
|
25964
25964
|
warn("awsContainerCredentialsRelativeUri will take precedence.");
|
|
25965
25965
|
}
|
|
@@ -25967,8 +25967,8 @@ var import_client9, import_config17, import_node_http_handler, AWS_CONTAINER_CRE
|
|
|
25967
25967
|
warn("@aws-sdk/credential-provider-http: " + "you have set both awsContainerAuthorizationToken and awsContainerAuthorizationTokenFile.");
|
|
25968
25968
|
warn("awsContainerAuthorizationTokenFile will take precedence.");
|
|
25969
25969
|
}
|
|
25970
|
-
if (
|
|
25971
|
-
host = `${DEFAULT_LINK_LOCAL_HOST}${
|
|
25970
|
+
if (relative7) {
|
|
25971
|
+
host = `${DEFAULT_LINK_LOCAL_HOST}${relative7}`;
|
|
25972
25972
|
} else if (full) {
|
|
25973
25973
|
host = full;
|
|
25974
25974
|
} else {
|
|
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
|
|
|
32373
32373
|
// package.json
|
|
32374
32374
|
var package_default = {
|
|
32375
32375
|
name: "@hasna/skills",
|
|
32376
|
-
version: "0.10.
|
|
32376
|
+
version: "0.10.20",
|
|
32377
32377
|
description: "Skills library for AI coding agents",
|
|
32378
32378
|
type: "module",
|
|
32379
32379
|
bin: {
|
|
@@ -37692,7 +37692,7 @@ import {
|
|
|
37692
37692
|
writeFileSync as writeFileSync7
|
|
37693
37693
|
} from "fs";
|
|
37694
37694
|
import { homedir as homedir5 } from "os";
|
|
37695
|
-
import { basename as
|
|
37695
|
+
import { basename as basename11, dirname as dirname19, join as join27 } from "path";
|
|
37696
37696
|
|
|
37697
37697
|
// src/lib/claude-settings-witness.ts
|
|
37698
37698
|
import { createHash as createHash5 } from "crypto";
|
|
@@ -38006,7 +38006,7 @@ function hashNativeJsonControls(text, excludedMetadata) {
|
|
|
38006
38006
|
}
|
|
38007
38007
|
|
|
38008
38008
|
// src/lib/codex-plugin-skill-controls.ts
|
|
38009
|
-
import { dirname as dirname5, join as join10, resolve as resolve4, sep as sep2 } from "path";
|
|
38009
|
+
import { basename as basename3, dirname as dirname5, join as join10, relative as relative3, resolve as resolve4, sep as sep2 } from "path";
|
|
38010
38010
|
import { lstatSync as lstatSync6, readdirSync as readdirSync3, readlinkSync as readlinkSync2, realpathSync as realpathSync5 } from "fs";
|
|
38011
38011
|
|
|
38012
38012
|
// src/lib/codex-native-skill-catalog.ts
|
|
@@ -38160,6 +38160,7 @@ async function connectCodexHookRpc(options) {
|
|
|
38160
38160
|
var MAX_SKILLS = 4096;
|
|
38161
38161
|
var MAX_NAME_BYTES = 1024;
|
|
38162
38162
|
var MAX_PATH_BYTES = 16384;
|
|
38163
|
+
var MAX_PLUGIN_ID_BYTES = 1024;
|
|
38163
38164
|
var SUPPORTED_NAME_CONTROL_VERSIONS = new Set(["codex-cli 0.159.2"]);
|
|
38164
38165
|
function refuse2() {
|
|
38165
38166
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_INVALID");
|
|
@@ -38183,6 +38184,35 @@ function projectCodexNativeSkillCatalog(response, cwd) {
|
|
|
38183
38184
|
return { name: value.name, path: value.path, enabled: value.enabled, pluginId: value.pluginId ?? null };
|
|
38184
38185
|
});
|
|
38185
38186
|
}
|
|
38187
|
+
function projectCodexInstalledPlugins(response) {
|
|
38188
|
+
if (!object2(response) || !Array.isArray(response.marketplaces) || !Array.isArray(response.marketplaceLoadErrors) || response.marketplaceLoadErrors.length !== 0 || response.marketplaces.length > MAX_SKILLS)
|
|
38189
|
+
refuse2();
|
|
38190
|
+
const plugins = [];
|
|
38191
|
+
for (const marketplace of response.marketplaces) {
|
|
38192
|
+
if (!object2(marketplace) || !scalar(marketplace.name, MAX_NAME_BYTES) || !Array.isArray(marketplace.plugins) || marketplace.plugins.length > MAX_SKILLS)
|
|
38193
|
+
refuse2();
|
|
38194
|
+
for (const value of marketplace.plugins) {
|
|
38195
|
+
if (!object2(value) || !scalar(value.id, MAX_PLUGIN_ID_BYTES) || !scalar(value.name, MAX_NAME_BYTES) || value.id !== `${value.name}@${marketplace.name}`)
|
|
38196
|
+
refuse2();
|
|
38197
|
+
plugins.push({ ...value, marketplace: marketplace.name });
|
|
38198
|
+
}
|
|
38199
|
+
}
|
|
38200
|
+
return projectCodexInstalledPluginEntries(plugins);
|
|
38201
|
+
}
|
|
38202
|
+
function projectCodexInstalledPluginEntries(value) {
|
|
38203
|
+
if (!Array.isArray(value) || value.length > MAX_SKILLS)
|
|
38204
|
+
refuse2();
|
|
38205
|
+
const ids = new Set;
|
|
38206
|
+
return value.map((item) => {
|
|
38207
|
+
if (!object2(item) || !scalar(item.id, MAX_PLUGIN_ID_BYTES) || !scalar(item.name, MAX_NAME_BYTES) || typeof item.installed !== "boolean" || typeof item.enabled !== "boolean" || item.localVersion !== null && !scalar(item.localVersion, MAX_NAME_BYTES))
|
|
38208
|
+
refuse2();
|
|
38209
|
+
const at = item.id.lastIndexOf("@");
|
|
38210
|
+
if (at < 1 || item.id.slice(0, at) !== item.name || at === item.id.length - 1 || ids.has(item.id))
|
|
38211
|
+
refuse2();
|
|
38212
|
+
ids.add(item.id);
|
|
38213
|
+
return { id: item.id, name: item.name, installed: item.installed, enabled: item.enabled, localVersion: item.localVersion ?? null };
|
|
38214
|
+
});
|
|
38215
|
+
}
|
|
38186
38216
|
async function captureCodexNativeSkillCatalog(options, connect = connectCodexHookRpc) {
|
|
38187
38217
|
if (!absolutePath2(options.cwd) || !absolutePath2(options.home))
|
|
38188
38218
|
refuse2();
|
|
@@ -38196,7 +38226,13 @@ async function captureCodexNativeSkillCatalog(options, connect = connectCodexHoo
|
|
|
38196
38226
|
if (!SUPPORTED_NAME_CONTROL_VERSIONS.has(rpc.version))
|
|
38197
38227
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_UNSUPPORTED_VERSION");
|
|
38198
38228
|
const response = await rpc.request("skills/list", { cwds: [options.cwd], forceReload: true });
|
|
38199
|
-
|
|
38229
|
+
const installed = await rpc.request("plugin/installed", { cwds: [options.cwd] });
|
|
38230
|
+
return {
|
|
38231
|
+
version: rpc.version,
|
|
38232
|
+
cwd: options.cwd,
|
|
38233
|
+
skills: projectCodexNativeSkillCatalog(response, options.cwd),
|
|
38234
|
+
plugins: projectCodexInstalledPlugins(installed)
|
|
38235
|
+
};
|
|
38200
38236
|
} finally {
|
|
38201
38237
|
await rpc.close();
|
|
38202
38238
|
}
|
|
@@ -38241,6 +38277,7 @@ function isCodexNativeSkillDisabled(skill, rules) {
|
|
|
38241
38277
|
|
|
38242
38278
|
// src/lib/codex-plugin-skill-controls.ts
|
|
38243
38279
|
var identifier3 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v);
|
|
38280
|
+
var CODEX_DEFAULT_AGENT_PLUGIN_VERSION = "1.0.0";
|
|
38244
38281
|
function refuse3() {
|
|
38245
38282
|
throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
|
|
38246
38283
|
}
|
|
@@ -38279,6 +38316,9 @@ function rootControls(root, read) {
|
|
|
38279
38316
|
}
|
|
38280
38317
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier3(manifest.name))
|
|
38281
38318
|
refuse3();
|
|
38319
|
+
const cacheVersion = basename3(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
38320
|
+
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
38321
|
+
refuse3();
|
|
38282
38322
|
if (manifest.hooks !== undefined || manifest.mcpServers !== undefined || manifest.commands !== undefined || manifest.apps !== undefined && manifest.apps !== "./.app.json" || ["hooks", ".mcp.json"].some((path) => lstatSync6(join10(root, path), { throwIfNoEntry: false })))
|
|
38283
38323
|
refuse3();
|
|
38284
38324
|
const app = join10(root, ".app.json"), present = lstatSync6(app, { throwIfNoEntry: false });
|
|
@@ -38355,22 +38395,48 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read) {
|
|
|
38355
38395
|
return false;
|
|
38356
38396
|
}
|
|
38357
38397
|
}
|
|
38358
|
-
function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read) {
|
|
38398
|
+
function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read, rules) {
|
|
38359
38399
|
if (catalog?.version !== "codex-cli 0.159.2" || catalog.cwd !== cwd)
|
|
38360
38400
|
refuse3();
|
|
38361
38401
|
const skills = projectCodexNativeSkillCatalog({ data: [{ cwd, errors: [], skills: catalog.skills }] }, cwd);
|
|
38362
38402
|
const allowed = new Set(documents), result = [];
|
|
38363
|
-
|
|
38364
|
-
|
|
38403
|
+
let installedPlugins;
|
|
38404
|
+
try {
|
|
38405
|
+
installedPlugins = projectCodexInstalledPluginEntries(catalog.plugins ?? []);
|
|
38406
|
+
} catch {
|
|
38407
|
+
refuse3();
|
|
38408
|
+
}
|
|
38409
|
+
const candidates = catalog.plugins === undefined ? skills.map((skill) => skill.path).filter((path) => allowed.has(path)) : allowed;
|
|
38410
|
+
for (const document of candidates) {
|
|
38411
|
+
if (!document.startsWith(cache + sep2))
|
|
38365
38412
|
continue;
|
|
38366
|
-
|
|
38413
|
+
const parsed = identity(document, cache, read);
|
|
38414
|
+
if (parsed.name === "skills-cli" || parsed.name.endsWith(":skills-cli"))
|
|
38415
|
+
refuse3();
|
|
38416
|
+
const cacheParts = relative3(cache, parsed.pluginParent).split(sep2);
|
|
38417
|
+
if (cacheParts.length !== 2 || cacheParts.some((part) => !identifier3(part)))
|
|
38367
38418
|
refuse3();
|
|
38368
|
-
|
|
38419
|
+
const [marketplace, pluginName] = cacheParts;
|
|
38420
|
+
if (pluginName !== parsed.namespace)
|
|
38369
38421
|
refuse3();
|
|
38370
|
-
const
|
|
38371
|
-
|
|
38422
|
+
const expectedPluginId = `${pluginName}@${marketplace}`;
|
|
38423
|
+
const listed = skills.filter((skill) => skill.path === document);
|
|
38424
|
+
if (listed.length > 1)
|
|
38372
38425
|
refuse3();
|
|
38373
|
-
|
|
38426
|
+
if (listed.length === 1) {
|
|
38427
|
+
if (listed[0].name !== parsed.name || listed[0].pluginId !== expectedPluginId)
|
|
38428
|
+
refuse3();
|
|
38429
|
+
} else {
|
|
38430
|
+
const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
|
|
38431
|
+
if (installed.length !== 1 || !installed[0].installed || !installed[0].enabled || !installed[0].localVersion)
|
|
38432
|
+
refuse3();
|
|
38433
|
+
if (installed[0].localVersion !== basename3(dirname5(dirname5(dirname5(document)))))
|
|
38434
|
+
continue;
|
|
38435
|
+
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document && rule?.enabled === false);
|
|
38436
|
+
if (!exactPathDeny || !isCodexNativeSkillDisabled({ name: parsed.name, path: document, pluginId: expectedPluginId, enabled: true }, rules))
|
|
38437
|
+
refuse3();
|
|
38438
|
+
}
|
|
38439
|
+
result.push({ ...parsed, pluginId: expectedPluginId });
|
|
38374
38440
|
}
|
|
38375
38441
|
if (!result.length || new Set(result.map((item) => item.name)).size !== result.length)
|
|
38376
38442
|
refuse3();
|
|
@@ -38532,7 +38598,7 @@ var NATIVE_SKILL_ROOTS = [
|
|
|
38532
38598
|
// src/lib/agent-integration.ts
|
|
38533
38599
|
import { createHash as createHash17, randomUUID as randomUUID3 } from "crypto";
|
|
38534
38600
|
import { existsSync as existsSync6, lstatSync as lstatSync19, statSync as statSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync14, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as readlinkSync4, realpathSync as realpathSync7, renameSync as renameSync3, rmdirSync as rmdirSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4, chmodSync, openSync as openSync16, closeSync as closeSync16, fsyncSync as fsyncSync4, fstatSync as fstatSync16, readSync as readSync11, constants as constants12, linkSync as linkSync2 } from "fs";
|
|
38535
|
-
import { dirname as dirname15, join as join22, resolve as resolve15, relative as
|
|
38601
|
+
import { dirname as dirname15, join as join22, resolve as resolve15, relative as relative4, isAbsolute as isAbsolute17, sep as sep5 } from "path";
|
|
38536
38602
|
import { homedir as homedir3 } from "os";
|
|
38537
38603
|
|
|
38538
38604
|
// src/lib/managed-policy.ts
|
|
@@ -38540,7 +38606,7 @@ import { closeSync as closeSync10, constants as constants6, fstatSync as fstatSy
|
|
|
38540
38606
|
import { join as join11 } from "path";
|
|
38541
38607
|
|
|
38542
38608
|
// src/lib/agent-policy-limits.ts
|
|
38543
|
-
import { basename as
|
|
38609
|
+
import { basename as basename4, isAbsolute as isAbsolute6, resolve as resolve5 } from "path";
|
|
38544
38610
|
var AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRawSourceBytes: 64 * 1024 * 1024, discoveryRawTotalBytes: 256 * 1024 * 1024, discoveryPathLinks: 40, discoveryPathSteps: 256, discoveryPathSourceMetadataBytes: 64 * 1024, discoveryPathTotalMetadataBytes: 8 * 1024 * 1024, discoveryRoots: 512, discoveryDirectories: 64, discoveryDirectoryEntries: 20000, discoveryDirectoryBytes: 8 * 1024 * 1024, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
|
|
38545
38611
|
function object3(value) {
|
|
38546
38612
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -38619,11 +38685,11 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38619
38685
|
if (source.hashMode !== undefined)
|
|
38620
38686
|
requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
38621
38687
|
if (source.hashMode === "codex-settings-v1")
|
|
38622
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path &&
|
|
38688
|
+
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path && basename4(source.path) === "config.toml");
|
|
38623
38689
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
|
|
38624
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path &&
|
|
38690
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path && basename4(source.path) === "settings.json");
|
|
38625
38691
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
|
|
38626
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path &&
|
|
38692
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path && basename4(source.path) === "known_marketplaces.json");
|
|
38627
38693
|
if (source.hashMode === "claude-plugin-registry") {
|
|
38628
38694
|
requireBound(agent === "claude");
|
|
38629
38695
|
const managed = array(source.managedPlugins, 64);
|
|
@@ -38777,7 +38843,7 @@ function isOwnedCliBridge(path, expectedPaths) {
|
|
|
38777
38843
|
// src/lib/agent-discovery.ts
|
|
38778
38844
|
import { createHash as createHash16 } from "crypto";
|
|
38779
38845
|
import { lstatSync as lstatSync18, readFileSync as readFileSync13, readdirSync as readdirSync7, realpathSync as realpathSync6 } from "fs";
|
|
38780
|
-
import { basename as
|
|
38846
|
+
import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute16, join as join21, resolve as resolve14, sep as sep4 } from "path";
|
|
38781
38847
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
38782
38848
|
|
|
38783
38849
|
// node_modules/yaml/dist/index.js
|
|
@@ -39059,7 +39125,7 @@ function capture(path, budget) {
|
|
|
39059
39125
|
return { path, sha256: null };
|
|
39060
39126
|
need3(root.isDirectory(), "Unsupported native discovery directory input");
|
|
39061
39127
|
const hash2 = createHash8("sha256");
|
|
39062
|
-
function walk2(current,
|
|
39128
|
+
function walk2(current, relative4, before, depth) {
|
|
39063
39129
|
need3(depth <= 64, "Native discovery directory depth limit exceeded");
|
|
39064
39130
|
const names = [], directory = opendirSync2(current);
|
|
39065
39131
|
try {
|
|
@@ -39072,7 +39138,7 @@ function capture(path, budget) {
|
|
|
39072
39138
|
}
|
|
39073
39139
|
need3(new Set(names).size === names.length, "Ambiguous native discovery directory names");
|
|
39074
39140
|
for (const name of names.sort()) {
|
|
39075
|
-
const child = join14(current, name), childRelative =
|
|
39141
|
+
const child = join14(current, name), childRelative = relative4 ? `${relative4}/${name}` : name;
|
|
39076
39142
|
need3(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
|
|
39077
39143
|
const stat = lstatSync10(child);
|
|
39078
39144
|
need3(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
|
|
@@ -39288,7 +39354,7 @@ function hashDiscoveryPathFile(path, budget, changes) {
|
|
|
39288
39354
|
|
|
39289
39355
|
// src/lib/plugin-discovery.ts
|
|
39290
39356
|
import { closeSync as closeSync13, constants as constants9, fstatSync as fstatSync13, lstatSync as lstatSync15, openSync as openSync13, opendirSync as opendirSync4, readSync as readSync8 } from "fs";
|
|
39291
|
-
import { basename as
|
|
39357
|
+
import { basename as basename5, dirname as dirname11, isAbsolute as isAbsolute14, join as join20, resolve as resolve12 } from "path";
|
|
39292
39358
|
|
|
39293
39359
|
// src/lib/plugin-admission.ts
|
|
39294
39360
|
import { homedir as homedir2 } from "os";
|
|
@@ -39631,7 +39697,7 @@ function directoryNames(path) {
|
|
|
39631
39697
|
function snapshotPluginTree(root, options = {}) {
|
|
39632
39698
|
const chain = ancestors(root), entries = [], files = [], directories = [];
|
|
39633
39699
|
let bytes = 0, visited = 0;
|
|
39634
|
-
const visit2 = (directory,
|
|
39700
|
+
const visit2 = (directory, relative4) => {
|
|
39635
39701
|
const before = stat(directory);
|
|
39636
39702
|
pluginNeed(before && before.isDirectory() && !before.isSymbolicLink(), "Plugin tree must contain real directories");
|
|
39637
39703
|
const names = directoryNames(directory);
|
|
@@ -39639,18 +39705,18 @@ function snapshotPluginTree(root, options = {}) {
|
|
|
39639
39705
|
directories.push({ path: directory, stat: before, names });
|
|
39640
39706
|
for (const name of names) {
|
|
39641
39707
|
pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
|
|
39642
|
-
const path =
|
|
39708
|
+
const path = relative4 ? `${relative4}/${name}` : name;
|
|
39643
39709
|
pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
|
|
39644
39710
|
const absolute = join16(directory, name), entryStat = stat(absolute);
|
|
39645
39711
|
pluginNeed(entryStat, "Plugin tree member disappeared");
|
|
39646
|
-
if (
|
|
39712
|
+
if (relative4 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
39647
39713
|
const bytes2 = readBytes(absolute, 32, "native-pin");
|
|
39648
39714
|
pluginNeed(/^[1-9][0-9]{12}$/.test(new TextDecoder().decode(bytes2)), "Malformed native orphan timestamp");
|
|
39649
39715
|
same3(entryStat, stat(absolute));
|
|
39650
39716
|
files.push({ path: absolute, stat: entryStat });
|
|
39651
39717
|
continue;
|
|
39652
39718
|
}
|
|
39653
|
-
if (
|
|
39719
|
+
if (relative4 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
39654
39720
|
pluginNeed(entryStat.isDirectory() && !entryStat.isSymbolicLink(), "Native plugin pins require a real directory");
|
|
39655
39721
|
owner(entryStat);
|
|
39656
39722
|
const pins = directoryNames(absolute);
|
|
@@ -40769,7 +40835,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
40769
40835
|
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join20(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
40770
40836
|
const approval = (producer) => {
|
|
40771
40837
|
pluginText(producer);
|
|
40772
|
-
const digest2 = `sha256:${
|
|
40838
|
+
const digest2 = `sha256:${basename5(producer)}`;
|
|
40773
40839
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
|
|
40774
40840
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
40775
40841
|
if (!verified.has(producer)) {
|
|
@@ -40833,7 +40899,7 @@ function captureManagedPluginRegistry(path, managedPlugins) {
|
|
|
40833
40899
|
// src/lib/claude-marketplace-registry.ts
|
|
40834
40900
|
import { createHash as createHash13 } from "crypto";
|
|
40835
40901
|
import { closeSync as closeSync14, constants as constants10, fstatSync as fstatSync14, lstatSync as lstatSync16, openSync as openSync14, readSync as readSync9 } from "fs";
|
|
40836
|
-
import { basename as
|
|
40902
|
+
import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute15, resolve as resolve13 } from "path";
|
|
40837
40903
|
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
40838
40904
|
function need4(value, reason) {
|
|
40839
40905
|
if (!value)
|
|
@@ -40855,7 +40921,7 @@ function parents2(path) {
|
|
|
40855
40921
|
}
|
|
40856
40922
|
function readRegistry2(path, budget) {
|
|
40857
40923
|
absolutePath3(path);
|
|
40858
|
-
need4(
|
|
40924
|
+
need4(basename6(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
40859
40925
|
need4(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
|
|
40860
40926
|
const ancestors2 = parents2(path), initial = lstatSync16(path, { bigint: true });
|
|
40861
40927
|
need4(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
@@ -41195,9 +41261,9 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
41195
41261
|
safe4(root2);
|
|
41196
41262
|
}
|
|
41197
41263
|
function assertMarketplaceBinding(binding, source) {
|
|
41198
|
-
if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" ||
|
|
41264
|
+
if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" || basename7(source.path) !== "config.toml"))
|
|
41199
41265
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
41200
|
-
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" ||
|
|
41266
|
+
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename7(source.path) !== "settings.json"))
|
|
41201
41267
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
41202
41268
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
41203
41269
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
@@ -41833,7 +41899,7 @@ function readRootAlias(home, agent) {
|
|
|
41833
41899
|
const targetStat = lstatSync19(targetPath, { throwIfNoEntry: false });
|
|
41834
41900
|
if (!targetStat?.isDirectory())
|
|
41835
41901
|
throw new Error(`Agent root alias must target an existing directory: ${alias}`);
|
|
41836
|
-
const target = realpathSync7(targetPath), inside =
|
|
41902
|
+
const target = realpathSync7(targetPath), inside = relative4(realHome, target);
|
|
41837
41903
|
if (!inside || inside === ".." || inside.startsWith(`..${sep5}`) || isAbsolute17(inside))
|
|
41838
41904
|
throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
|
|
41839
41905
|
return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
|
|
@@ -41851,7 +41917,7 @@ function rootAliases(home, allowed = false) {
|
|
|
41851
41917
|
}
|
|
41852
41918
|
function canonicalAgentPath(path, aliases) {
|
|
41853
41919
|
const absolute = resolve15(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep5));
|
|
41854
|
-
return binding ? join22(binding.target,
|
|
41920
|
+
return binding ? join22(binding.target, relative4(binding.alias, absolute)) : absolute;
|
|
41855
41921
|
}
|
|
41856
41922
|
function disabledCodexSkillPaths(config, aliases) {
|
|
41857
41923
|
const skills = config.skills;
|
|
@@ -41922,7 +41988,7 @@ function treeHash(root2) {
|
|
|
41922
41988
|
const stat2 = lstatSync19(path);
|
|
41923
41989
|
if (stat2.isSymbolicLink())
|
|
41924
41990
|
throw new Error(`Refusing symlink in skill: ${path}`);
|
|
41925
|
-
const rel =
|
|
41991
|
+
const rel = relative4(root2, path);
|
|
41926
41992
|
if (stat2.isDirectory()) {
|
|
41927
41993
|
hash2.update(`d\x00${rel}\x00`);
|
|
41928
41994
|
for (const name of readdirSync8(path).sort())
|
|
@@ -41948,7 +42014,7 @@ function selectNativeMigrationTargets(inventory, manifest) {
|
|
|
41948
42014
|
const identities = new Set;
|
|
41949
42015
|
const selected = [];
|
|
41950
42016
|
for (const target of manifest.targets) {
|
|
41951
|
-
const projectRoot = resolve15(target.projectRoot), normalized =
|
|
42017
|
+
const projectRoot = resolve15(target.projectRoot), normalized = relative4(projectRoot, resolve15(projectRoot, target.path));
|
|
41952
42018
|
if (!isAbsolute17(target.projectRoot) || projectRoot !== target.projectRoot || !existsSync6(projectRoot) || !lstatSync19(projectRoot).isDirectory())
|
|
41953
42019
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
|
|
41954
42020
|
assertSafePath(projectRoot);
|
|
@@ -42303,7 +42369,7 @@ function planAgentIntegration(options) {
|
|
|
42303
42369
|
const bytes = readNativeBytes(path, 1024 * 1024);
|
|
42304
42370
|
observedNativeSources.push({ path, sha256: sha3(bytes) });
|
|
42305
42371
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
42306
|
-
}) : policy.bridge?.codexPluginSkills ?? [];
|
|
42372
|
+
}, codexConfig.skills?.config ?? []) : policy.bridge?.codexPluginSkills ?? [];
|
|
42307
42373
|
const changes = [];
|
|
42308
42374
|
for (const agent of [...new Set(options.agents)]) {
|
|
42309
42375
|
if (!INTEGRATION_AGENTS.includes(agent))
|
|
@@ -42381,7 +42447,7 @@ function planAgentIntegration(options) {
|
|
|
42381
42447
|
profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
|
|
42382
42448
|
disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join22(home, ".codex", "skills", ".system"), aliases) + sep5)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
|
|
42383
42449
|
rootAliases: aliases,
|
|
42384
|
-
...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha3(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd) })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join22(home, ".codex/config.toml"), aliases))?.before === null ? null : sha3(readOptional(canonicalAgentPath(join22(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
|
|
42450
|
+
...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha3(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd), ...options.codexNativeCatalog.plugins === undefined ? {} : { plugins: projectCodexInstalledPluginEntries(options.codexNativeCatalog.plugins) } })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join22(home, ".codex/config.toml"), aliases))?.before === null ? null : sha3(readOptional(canonicalAgentPath(join22(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
|
|
42385
42451
|
discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
|
|
42386
42452
|
} };
|
|
42387
42453
|
const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
|
|
@@ -42399,7 +42465,7 @@ function planClaudePreToolUseHookUpdate(options) {
|
|
|
42399
42465
|
function claudeSettingsConsumers(home, path, discoveries, aliases) {
|
|
42400
42466
|
const canonical5 = (value) => canonicalAgentPath(value, aliases);
|
|
42401
42467
|
const containsSettings = (root2) => {
|
|
42402
|
-
const distance =
|
|
42468
|
+
const distance = relative4(canonical5(root2), path);
|
|
42403
42469
|
return distance === "" || distance !== ".." && !distance.startsWith(`..${sep5}`) && !isAbsolute17(distance);
|
|
42404
42470
|
};
|
|
42405
42471
|
return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical5(join22(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical5(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
|
|
@@ -42913,7 +42979,7 @@ import {
|
|
|
42913
42979
|
statSync as statSync9,
|
|
42914
42980
|
writeFileSync as writeFileSync6
|
|
42915
42981
|
} from "fs";
|
|
42916
|
-
import { basename as
|
|
42982
|
+
import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute18, join as join26, normalize as normalize3, relative as relative6, resolve as resolve17, sep as sep8 } from "path";
|
|
42917
42983
|
|
|
42918
42984
|
// src/lib/registry-data/index.ts
|
|
42919
42985
|
var SKILLS = [];
|
|
@@ -43438,7 +43504,7 @@ import {
|
|
|
43438
43504
|
realpathSync as realpathSync8,
|
|
43439
43505
|
writeFileSync as writeFileSync5
|
|
43440
43506
|
} from "fs";
|
|
43441
|
-
import { basename as
|
|
43507
|
+
import { basename as basename8, dirname as dirname16, join as join24, relative as relative5 } from "path";
|
|
43442
43508
|
var ANY_SEGMENT_COPY_EXCLUDES = new Set([
|
|
43443
43509
|
".git",
|
|
43444
43510
|
".DS_Store",
|
|
@@ -43488,11 +43554,11 @@ function normalizeNewPortableSkillName(name) {
|
|
|
43488
43554
|
throw new Error(`Invalid skill name '${name}'. Include letters or numbers.`);
|
|
43489
43555
|
return normalized;
|
|
43490
43556
|
}
|
|
43491
|
-
function readPortableSkillManifest(skillPath, fallbackName =
|
|
43557
|
+
function readPortableSkillManifest(skillPath, fallbackName = basename8(skillPath)) {
|
|
43492
43558
|
return readManifest(skillPath, fallbackName, normalizePortableSkillName);
|
|
43493
43559
|
}
|
|
43494
43560
|
function readPortableSkillManifestForImport(skillPath) {
|
|
43495
|
-
return readManifest(skillPath,
|
|
43561
|
+
return readManifest(skillPath, basename8(skillPath), normalizeNewPortableSkillName);
|
|
43496
43562
|
}
|
|
43497
43563
|
function readManifest(skillPath, fallbackName, normalizeName) {
|
|
43498
43564
|
const skillJsonPath = join24(skillPath, "skill.json");
|
|
@@ -43795,7 +43861,7 @@ function copySkillDirectory(source, destination) {
|
|
|
43795
43861
|
cpSync(resolvedSource, destination, {
|
|
43796
43862
|
recursive: true,
|
|
43797
43863
|
filter: (src) => {
|
|
43798
|
-
const rel =
|
|
43864
|
+
const rel = relative5(resolvedSource, src);
|
|
43799
43865
|
if (!rel)
|
|
43800
43866
|
return true;
|
|
43801
43867
|
const segments = rel.split(/[\\/]/);
|
|
@@ -44046,7 +44112,7 @@ function inferRuntimeFromCommands(commands) {
|
|
|
44046
44112
|
function readJsonObject(path) {
|
|
44047
44113
|
const parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
44048
44114
|
if (!isRecord2(parsed))
|
|
44049
|
-
throw new Error(`${
|
|
44115
|
+
throw new Error(`${basename8(path)} must contain a JSON object`);
|
|
44050
44116
|
return parsed;
|
|
44051
44117
|
}
|
|
44052
44118
|
function hasPackageDependencies(pkgPath) {
|
|
@@ -44084,7 +44150,7 @@ function escapeJsString(value) {
|
|
|
44084
44150
|
// src/lib/authoring-path.ts
|
|
44085
44151
|
import { lstatSync as lstatSync21, realpathSync as realpathSync9 } from "fs";
|
|
44086
44152
|
import { homedir as homedir4 } from "os";
|
|
44087
|
-
import { basename as
|
|
44153
|
+
import { basename as basename9, dirname as dirname17, join as join25, resolve as resolve16, sep as sep7 } from "path";
|
|
44088
44154
|
var NATIVE_DISCOVERY_ROOTS = NATIVE_SKILL_ROOTS.map(([, path]) => path.split("/"));
|
|
44089
44155
|
function pathParts(path) {
|
|
44090
44156
|
return resolve16(path).split(sep7).filter(Boolean);
|
|
@@ -44104,7 +44170,7 @@ function physicalPath(path) {
|
|
|
44104
44170
|
let cursor = resolve16(path);
|
|
44105
44171
|
const suffix = [];
|
|
44106
44172
|
while (!lstatSync21(cursor, { throwIfNoEntry: false })) {
|
|
44107
|
-
suffix.unshift(
|
|
44173
|
+
suffix.unshift(basename9(cursor));
|
|
44108
44174
|
const parent = dirname17(cursor);
|
|
44109
44175
|
if (parent === cursor)
|
|
44110
44176
|
return resolve16(path);
|
|
@@ -44323,7 +44389,7 @@ function physicalImportPath(path) {
|
|
|
44323
44389
|
let ancestor = resolve17(path);
|
|
44324
44390
|
const suffix = [];
|
|
44325
44391
|
while (!existsSync9(ancestor)) {
|
|
44326
|
-
suffix.unshift(
|
|
44392
|
+
suffix.unshift(basename10(ancestor));
|
|
44327
44393
|
ancestor = dirname18(ancestor);
|
|
44328
44394
|
}
|
|
44329
44395
|
return join26(realpathSync10(ancestor), ...suffix);
|
|
@@ -44332,7 +44398,7 @@ function assertDisjointImportPaths(source, destination) {
|
|
|
44332
44398
|
const sourcePath = realpathSync10(source);
|
|
44333
44399
|
const destinationPath = physicalImportPath(destination);
|
|
44334
44400
|
const contains2 = (parent, child) => {
|
|
44335
|
-
const path =
|
|
44401
|
+
const path = relative6(parent, child);
|
|
44336
44402
|
return path === "" || !isAbsolute18(path) && path !== ".." && !path.startsWith(`..${sep8}`);
|
|
44337
44403
|
};
|
|
44338
44404
|
if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
|
|
@@ -44348,8 +44414,8 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
44348
44414
|
const explicitName = options.name != null;
|
|
44349
44415
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
44350
44416
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
44351
|
-
const sourceSlug = safeNormalizeName(
|
|
44352
|
-
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${
|
|
44417
|
+
const sourceSlug = safeNormalizeName(basename10(absoluteSource));
|
|
44418
|
+
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename10(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
44353
44419
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
44354
44420
|
}
|
|
44355
44421
|
const readOnlyDestination = join26(resolvePortableSkillsRoot(options, false), skillName);
|
|
@@ -44869,7 +44935,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
44869
44935
|
return { action, path: skillMdPath };
|
|
44870
44936
|
const parentDir = dirname19(dir);
|
|
44871
44937
|
mkdirSync8(parentDir, { recursive: true });
|
|
44872
|
-
const transactionDir = mkdtempSync2(join27(parentDir, `.hasna-skills-write-${
|
|
44938
|
+
const transactionDir = mkdtempSync2(join27(parentDir, `.hasna-skills-write-${basename11(dir)}-`));
|
|
44873
44939
|
const candidateDir = join27(transactionDir, "candidate");
|
|
44874
44940
|
const backupDir = join27(transactionDir, "backup");
|
|
44875
44941
|
const candidateSkillMdPath = join27(candidateDir, "SKILL.md");
|