@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/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.10.
|
|
20022
|
+
version: "0.10.20",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
package/bin/migrate.js
CHANGED
package/bin/server.js
CHANGED
|
@@ -24122,7 +24122,7 @@ var init_dist_es9 = __esm(() => {
|
|
|
24122
24122
|
// package.json
|
|
24123
24123
|
var package_default = {
|
|
24124
24124
|
name: "@hasna/skills",
|
|
24125
|
-
version: "0.10.
|
|
24125
|
+
version: "0.10.20",
|
|
24126
24126
|
description: "Skills library for AI coding agents",
|
|
24127
24127
|
type: "module",
|
|
24128
24128
|
bin: {
|
package/bin/worker.js
CHANGED
|
@@ -24125,7 +24125,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
24125
24125
|
// package.json
|
|
24126
24126
|
var package_default = {
|
|
24127
24127
|
name: "@hasna/skills",
|
|
24128
|
-
version: "0.10.
|
|
24128
|
+
version: "0.10.20",
|
|
24129
24129
|
description: "Skills library for AI coding agents",
|
|
24130
24130
|
type: "module",
|
|
24131
24131
|
bin: {
|
package/dist/index.d.ts
CHANGED
|
@@ -71,4 +71,4 @@ export type { RemoteCreditCheckoutOptions, RemoteCreditCheckout, RemoteCreditChe
|
|
|
71
71
|
export { assertPortableAuthoringPath, type PortableAuthoringPathOptions } from "./lib/authoring-path.js";
|
|
72
72
|
export { CLAUDE_COORDINATED_HOOK_EVENTS, type ClaudeCoordinatedHookEvent } from "./lib/claude-settings-witness.js";
|
|
73
73
|
export { captureCodexSettings, upgradeCodexSettingsWitness } from "./lib/codex-settings-witness.js";
|
|
74
|
-
export { projectCodexNativeSkillCatalog, captureCodexNativeSkillCatalog, isCodexNativeSkillDisabled, type CodexNativeSkillCatalog, type CodexNativeSkill } from "./lib/codex-native-skill-catalog.js";
|
|
74
|
+
export { projectCodexNativeSkillCatalog, projectCodexInstalledPlugins, projectCodexInstalledPluginEntries, captureCodexNativeSkillCatalog, isCodexNativeSkillDisabled, type CodexNativeSkillCatalog, type CodexNativeSkill, type CodexInstalledPlugin } from "./lib/codex-native-skill-catalog.js";
|
package/dist/index.js
CHANGED
|
@@ -7262,7 +7262,7 @@ import {
|
|
|
7262
7262
|
statSync as statSync10,
|
|
7263
7263
|
writeFileSync as writeFileSync8
|
|
7264
7264
|
} from "fs";
|
|
7265
|
-
import { basename as
|
|
7265
|
+
import { basename as basename11, dirname as dirname19, isAbsolute as isAbsolute17, join as join29, normalize as normalize3, relative as relative6, resolve as resolve17, sep as sep8 } from "path";
|
|
7266
7266
|
|
|
7267
7267
|
// src/lib/registry-data/index.ts
|
|
7268
7268
|
var SKILLS = [];
|
|
@@ -8920,7 +8920,7 @@ var NATIVE_SKILL_ROOTS = [
|
|
|
8920
8920
|
// src/lib/authoring-path.ts
|
|
8921
8921
|
import { lstatSync as lstatSync22, realpathSync as realpathSync8 } from "fs";
|
|
8922
8922
|
import { homedir as homedir6 } from "os";
|
|
8923
|
-
import { basename as
|
|
8923
|
+
import { basename as basename10, dirname as dirname18, join as join28, resolve as resolve16, sep as sep7 } from "path";
|
|
8924
8924
|
|
|
8925
8925
|
// src/lib/agent-adapters.ts
|
|
8926
8926
|
var INTEGRATION_AGENTS = ["claude", "codex", "gemini", "opencode", "cursor", "hermes"];
|
|
@@ -9105,7 +9105,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
9105
9105
|
// src/lib/agent-discovery.ts
|
|
9106
9106
|
import { createHash as createHash17 } from "crypto";
|
|
9107
9107
|
import { lstatSync as lstatSync21, readFileSync as readFileSync17, readdirSync as readdirSync10, realpathSync as realpathSync7 } from "fs";
|
|
9108
|
-
import { basename as
|
|
9108
|
+
import { basename as basename9, dirname as dirname17, isAbsolute as isAbsolute16, join as join27, resolve as resolve15, sep as sep6 } from "path";
|
|
9109
9109
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
9110
9110
|
|
|
9111
9111
|
// node_modules/yaml/dist/index.js
|
|
@@ -9616,7 +9616,7 @@ function hashDiscoveryPathFile(path, budget, changes) {
|
|
|
9616
9616
|
|
|
9617
9617
|
// src/lib/plugin-discovery.ts
|
|
9618
9618
|
import { closeSync as closeSync10, constants as constants9, fstatSync as fstatSync10, lstatSync as lstatSync18, openSync as openSync10, opendirSync as opendirSync5, readSync as readSync8 } from "fs";
|
|
9619
|
-
import { basename as
|
|
9619
|
+
import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute14, join as join26, resolve as resolve13 } from "path";
|
|
9620
9620
|
|
|
9621
9621
|
// src/lib/plugin-admission.ts
|
|
9622
9622
|
import { homedir as homedir5 } from "os";
|
|
@@ -10877,7 +10877,7 @@ function replaceSkillSession(expected, replacement, plan, options = {}, beforeCo
|
|
|
10877
10877
|
// package.json
|
|
10878
10878
|
var package_default = {
|
|
10879
10879
|
name: "@hasna/skills",
|
|
10880
|
-
version: "0.10.
|
|
10880
|
+
version: "0.10.20",
|
|
10881
10881
|
description: "Skills library for AI coding agents",
|
|
10882
10882
|
type: "module",
|
|
10883
10883
|
bin: {
|
|
@@ -12710,7 +12710,7 @@ import {
|
|
|
12710
12710
|
writeFileSync as writeFileSync5
|
|
12711
12711
|
} from "fs";
|
|
12712
12712
|
import { homedir as homedir3 } from "os";
|
|
12713
|
-
import { basename as
|
|
12713
|
+
import { basename as basename6, dirname as dirname12, join as join18 } from "path";
|
|
12714
12714
|
|
|
12715
12715
|
// src/lib/claude-settings-witness.ts
|
|
12716
12716
|
import { createHash as createHash8 } from "crypto";
|
|
@@ -13024,7 +13024,7 @@ function hashNativeJsonControls(text2, excludedMetadata) {
|
|
|
13024
13024
|
}
|
|
13025
13025
|
|
|
13026
13026
|
// src/lib/codex-plugin-skill-controls.ts
|
|
13027
|
-
import { dirname as dirname10, join as join14, resolve as resolve9, sep as sep4 } from "path";
|
|
13027
|
+
import { basename as basename5, dirname as dirname10, join as join14, relative as relative4, resolve as resolve9, sep as sep4 } from "path";
|
|
13028
13028
|
import { lstatSync as lstatSync12, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync5 } from "fs";
|
|
13029
13029
|
|
|
13030
13030
|
// src/lib/codex-native-skill-catalog.ts
|
|
@@ -13178,6 +13178,7 @@ async function connectCodexHookRpc(options) {
|
|
|
13178
13178
|
var MAX_SKILLS = 4096;
|
|
13179
13179
|
var MAX_NAME_BYTES = 1024;
|
|
13180
13180
|
var MAX_PATH_BYTES = 16384;
|
|
13181
|
+
var MAX_PLUGIN_ID_BYTES = 1024;
|
|
13181
13182
|
var SUPPORTED_NAME_CONTROL_VERSIONS = new Set(["codex-cli 0.159.2"]);
|
|
13182
13183
|
function refuse() {
|
|
13183
13184
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_INVALID");
|
|
@@ -13201,6 +13202,35 @@ function projectCodexNativeSkillCatalog(response, cwd) {
|
|
|
13201
13202
|
return { name: value.name, path: value.path, enabled: value.enabled, pluginId: value.pluginId ?? null };
|
|
13202
13203
|
});
|
|
13203
13204
|
}
|
|
13205
|
+
function projectCodexInstalledPlugins(response) {
|
|
13206
|
+
if (!object4(response) || !Array.isArray(response.marketplaces) || !Array.isArray(response.marketplaceLoadErrors) || response.marketplaceLoadErrors.length !== 0 || response.marketplaces.length > MAX_SKILLS)
|
|
13207
|
+
refuse();
|
|
13208
|
+
const plugins = [];
|
|
13209
|
+
for (const marketplace of response.marketplaces) {
|
|
13210
|
+
if (!object4(marketplace) || !scalar(marketplace.name, MAX_NAME_BYTES) || !Array.isArray(marketplace.plugins) || marketplace.plugins.length > MAX_SKILLS)
|
|
13211
|
+
refuse();
|
|
13212
|
+
for (const value of marketplace.plugins) {
|
|
13213
|
+
if (!object4(value) || !scalar(value.id, MAX_PLUGIN_ID_BYTES) || !scalar(value.name, MAX_NAME_BYTES) || value.id !== `${value.name}@${marketplace.name}`)
|
|
13214
|
+
refuse();
|
|
13215
|
+
plugins.push({ ...value, marketplace: marketplace.name });
|
|
13216
|
+
}
|
|
13217
|
+
}
|
|
13218
|
+
return projectCodexInstalledPluginEntries(plugins);
|
|
13219
|
+
}
|
|
13220
|
+
function projectCodexInstalledPluginEntries(value) {
|
|
13221
|
+
if (!Array.isArray(value) || value.length > MAX_SKILLS)
|
|
13222
|
+
refuse();
|
|
13223
|
+
const ids = new Set;
|
|
13224
|
+
return value.map((item) => {
|
|
13225
|
+
if (!object4(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))
|
|
13226
|
+
refuse();
|
|
13227
|
+
const at = item.id.lastIndexOf("@");
|
|
13228
|
+
if (at < 1 || item.id.slice(0, at) !== item.name || at === item.id.length - 1 || ids.has(item.id))
|
|
13229
|
+
refuse();
|
|
13230
|
+
ids.add(item.id);
|
|
13231
|
+
return { id: item.id, name: item.name, installed: item.installed, enabled: item.enabled, localVersion: item.localVersion ?? null };
|
|
13232
|
+
});
|
|
13233
|
+
}
|
|
13204
13234
|
async function captureCodexNativeSkillCatalog(options, connect = connectCodexHookRpc) {
|
|
13205
13235
|
if (!absolutePath2(options.cwd) || !absolutePath2(options.home))
|
|
13206
13236
|
refuse();
|
|
@@ -13214,7 +13244,13 @@ async function captureCodexNativeSkillCatalog(options, connect = connectCodexHoo
|
|
|
13214
13244
|
if (!SUPPORTED_NAME_CONTROL_VERSIONS.has(rpc.version))
|
|
13215
13245
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_UNSUPPORTED_VERSION");
|
|
13216
13246
|
const response = await rpc.request("skills/list", { cwds: [options.cwd], forceReload: true });
|
|
13217
|
-
|
|
13247
|
+
const installed = await rpc.request("plugin/installed", { cwds: [options.cwd] });
|
|
13248
|
+
return {
|
|
13249
|
+
version: rpc.version,
|
|
13250
|
+
cwd: options.cwd,
|
|
13251
|
+
skills: projectCodexNativeSkillCatalog(response, options.cwd),
|
|
13252
|
+
plugins: projectCodexInstalledPlugins(installed)
|
|
13253
|
+
};
|
|
13218
13254
|
} finally {
|
|
13219
13255
|
await rpc.close();
|
|
13220
13256
|
}
|
|
@@ -13259,6 +13295,7 @@ function isCodexNativeSkillDisabled(skill, rules) {
|
|
|
13259
13295
|
|
|
13260
13296
|
// src/lib/codex-plugin-skill-controls.ts
|
|
13261
13297
|
var identifier2 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v);
|
|
13298
|
+
var CODEX_DEFAULT_AGENT_PLUGIN_VERSION = "1.0.0";
|
|
13262
13299
|
function refuse2() {
|
|
13263
13300
|
throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
|
|
13264
13301
|
}
|
|
@@ -13297,6 +13334,9 @@ function rootControls(root, read2) {
|
|
|
13297
13334
|
}
|
|
13298
13335
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
|
|
13299
13336
|
refuse2();
|
|
13337
|
+
const cacheVersion = basename5(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
13338
|
+
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
13339
|
+
refuse2();
|
|
13300
13340
|
if (manifest.hooks !== undefined || manifest.mcpServers !== undefined || manifest.commands !== undefined || manifest.apps !== undefined && manifest.apps !== "./.app.json" || ["hooks", ".mcp.json"].some((path) => lstatSync12(join14(root, path), { throwIfNoEntry: false })))
|
|
13301
13341
|
refuse2();
|
|
13302
13342
|
const app = join14(root, ".app.json"), present = lstatSync12(app, { throwIfNoEntry: false });
|
|
@@ -13373,22 +13413,48 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read2) {
|
|
|
13373
13413
|
return false;
|
|
13374
13414
|
}
|
|
13375
13415
|
}
|
|
13376
|
-
function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read2) {
|
|
13416
|
+
function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read2, rules) {
|
|
13377
13417
|
if (catalog?.version !== "codex-cli 0.159.2" || catalog.cwd !== cwd)
|
|
13378
13418
|
refuse2();
|
|
13379
13419
|
const skills = projectCodexNativeSkillCatalog({ data: [{ cwd, errors: [], skills: catalog.skills }] }, cwd);
|
|
13380
13420
|
const allowed = new Set(documents), result = [];
|
|
13381
|
-
|
|
13382
|
-
|
|
13421
|
+
let installedPlugins;
|
|
13422
|
+
try {
|
|
13423
|
+
installedPlugins = projectCodexInstalledPluginEntries(catalog.plugins ?? []);
|
|
13424
|
+
} catch {
|
|
13425
|
+
refuse2();
|
|
13426
|
+
}
|
|
13427
|
+
const candidates = catalog.plugins === undefined ? skills.map((skill) => skill.path).filter((path) => allowed.has(path)) : allowed;
|
|
13428
|
+
for (const document2 of candidates) {
|
|
13429
|
+
if (!document2.startsWith(cache + sep4))
|
|
13383
13430
|
continue;
|
|
13384
|
-
|
|
13431
|
+
const parsed = identity3(document2, cache, read2);
|
|
13432
|
+
if (parsed.name === "skills-cli" || parsed.name.endsWith(":skills-cli"))
|
|
13433
|
+
refuse2();
|
|
13434
|
+
const cacheParts = relative4(cache, parsed.pluginParent).split(sep4);
|
|
13435
|
+
if (cacheParts.length !== 2 || cacheParts.some((part) => !identifier2(part)))
|
|
13385
13436
|
refuse2();
|
|
13386
|
-
|
|
13437
|
+
const [marketplace, pluginName] = cacheParts;
|
|
13438
|
+
if (pluginName !== parsed.namespace)
|
|
13387
13439
|
refuse2();
|
|
13388
|
-
const
|
|
13389
|
-
|
|
13440
|
+
const expectedPluginId = `${pluginName}@${marketplace}`;
|
|
13441
|
+
const listed = skills.filter((skill) => skill.path === document2);
|
|
13442
|
+
if (listed.length > 1)
|
|
13390
13443
|
refuse2();
|
|
13391
|
-
|
|
13444
|
+
if (listed.length === 1) {
|
|
13445
|
+
if (listed[0].name !== parsed.name || listed[0].pluginId !== expectedPluginId)
|
|
13446
|
+
refuse2();
|
|
13447
|
+
} else {
|
|
13448
|
+
const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
|
|
13449
|
+
if (installed.length !== 1 || !installed[0].installed || !installed[0].enabled || !installed[0].localVersion)
|
|
13450
|
+
refuse2();
|
|
13451
|
+
if (installed[0].localVersion !== basename5(dirname10(dirname10(dirname10(document2)))))
|
|
13452
|
+
continue;
|
|
13453
|
+
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document2 && rule?.enabled === false);
|
|
13454
|
+
if (!exactPathDeny || !isCodexNativeSkillDisabled({ name: parsed.name, path: document2, pluginId: expectedPluginId, enabled: true }, rules))
|
|
13455
|
+
refuse2();
|
|
13456
|
+
}
|
|
13457
|
+
result.push({ ...parsed, pluginId: expectedPluginId });
|
|
13392
13458
|
}
|
|
13393
13459
|
if (!result.length || new Set(result.map((item) => item.name)).size !== result.length)
|
|
13394
13460
|
refuse2();
|
|
@@ -13531,7 +13597,7 @@ function upgradeCodexSettingsWitness(previous, reviewedSettingsPath) {
|
|
|
13531
13597
|
// src/lib/agent-integration.ts
|
|
13532
13598
|
import { createHash as createHash11, randomUUID as randomUUID2 } from "crypto";
|
|
13533
13599
|
import { existsSync as existsSync8, lstatSync as lstatSync15, statSync as statSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync12, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync4, realpathSync as realpathSync6, renameSync as renameSync2, rmdirSync as rmdirSync2, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3, chmodSync, openSync as openSync8, closeSync as closeSync8, fsyncSync as fsyncSync2, fstatSync as fstatSync8, readSync as readSync6, constants as constants7, linkSync } from "fs";
|
|
13534
|
-
import { dirname as dirname11, join as join17, resolve as resolve10, relative as
|
|
13600
|
+
import { dirname as dirname11, join as join17, resolve as resolve10, relative as relative5, isAbsolute as isAbsolute11, sep as sep5 } from "path";
|
|
13535
13601
|
import { homedir as homedir2 } from "os";
|
|
13536
13602
|
|
|
13537
13603
|
// src/lib/managed-policy.ts
|
|
@@ -13950,7 +14016,7 @@ function readRootAlias(home, agent) {
|
|
|
13950
14016
|
const targetStat = lstatSync15(targetPath, { throwIfNoEntry: false });
|
|
13951
14017
|
if (!targetStat?.isDirectory())
|
|
13952
14018
|
throw new Error(`Agent root alias must target an existing directory: ${alias}`);
|
|
13953
|
-
const target = realpathSync6(targetPath), inside =
|
|
14019
|
+
const target = realpathSync6(targetPath), inside = relative5(realHome, target);
|
|
13954
14020
|
if (!inside || inside === ".." || inside.startsWith(`..${sep5}`) || isAbsolute11(inside))
|
|
13955
14021
|
throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
|
|
13956
14022
|
return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat.dev}:${stat.ino}:${stat.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
|
|
@@ -13968,7 +14034,7 @@ function rootAliases(home, allowed = false) {
|
|
|
13968
14034
|
}
|
|
13969
14035
|
function canonicalAgentPath(path, aliases) {
|
|
13970
14036
|
const absolute = resolve10(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep5));
|
|
13971
|
-
return binding ? join17(binding.target,
|
|
14037
|
+
return binding ? join17(binding.target, relative5(binding.alias, absolute)) : absolute;
|
|
13972
14038
|
}
|
|
13973
14039
|
function disabledCodexSkillPaths(config, aliases) {
|
|
13974
14040
|
const skills = config.skills;
|
|
@@ -14039,7 +14105,7 @@ function treeHash(root) {
|
|
|
14039
14105
|
const stat = lstatSync15(path);
|
|
14040
14106
|
if (stat.isSymbolicLink())
|
|
14041
14107
|
throw new Error(`Refusing symlink in skill: ${path}`);
|
|
14042
|
-
const rel =
|
|
14108
|
+
const rel = relative5(root, path);
|
|
14043
14109
|
if (stat.isDirectory()) {
|
|
14044
14110
|
hash2.update(`d\x00${rel}\x00`);
|
|
14045
14111
|
for (const name of readdirSync8(path).sort())
|
|
@@ -14065,7 +14131,7 @@ function selectNativeMigrationTargets(inventory, manifest) {
|
|
|
14065
14131
|
const identities = new Set;
|
|
14066
14132
|
const selected = [];
|
|
14067
14133
|
for (const target of manifest.targets) {
|
|
14068
|
-
const projectRoot = resolve10(target.projectRoot), normalized =
|
|
14134
|
+
const projectRoot = resolve10(target.projectRoot), normalized = relative5(projectRoot, resolve10(projectRoot, target.path));
|
|
14069
14135
|
if (!isAbsolute11(target.projectRoot) || projectRoot !== target.projectRoot || !existsSync8(projectRoot) || !lstatSync15(projectRoot).isDirectory())
|
|
14070
14136
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
|
|
14071
14137
|
assertSafePath(projectRoot);
|
|
@@ -14420,7 +14486,7 @@ function planAgentIntegration(options) {
|
|
|
14420
14486
|
const bytes = readNativeBytes(path, 1024 * 1024);
|
|
14421
14487
|
observedNativeSources.push({ path, sha256: sha2(bytes) });
|
|
14422
14488
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
14423
|
-
}) : policy.bridge?.codexPluginSkills ?? [];
|
|
14489
|
+
}, codexConfig.skills?.config ?? []) : policy.bridge?.codexPluginSkills ?? [];
|
|
14424
14490
|
const changes = [];
|
|
14425
14491
|
for (const agent of [...new Set(options.agents)]) {
|
|
14426
14492
|
if (!INTEGRATION_AGENTS.includes(agent))
|
|
@@ -14498,7 +14564,7 @@ function planAgentIntegration(options) {
|
|
|
14498
14564
|
profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
|
|
14499
14565
|
disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join17(home, ".codex", "skills", ".system"), aliases) + sep5)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
|
|
14500
14566
|
rootAliases: aliases,
|
|
14501
|
-
...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha2(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(join17(home, ".codex/config.toml"), aliases))?.before === null ? null : sha2(readOptional(canonicalAgentPath(join17(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
|
|
14567
|
+
...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha2(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(join17(home, ".codex/config.toml"), aliases))?.before === null ? null : sha2(readOptional(canonicalAgentPath(join17(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
|
|
14502
14568
|
discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
|
|
14503
14569
|
} };
|
|
14504
14570
|
const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
|
|
@@ -14516,7 +14582,7 @@ function planClaudePreToolUseHookUpdate(options) {
|
|
|
14516
14582
|
function claudeSettingsConsumers(home, path, discoveries, aliases) {
|
|
14517
14583
|
const canonical4 = (value) => canonicalAgentPath(value, aliases);
|
|
14518
14584
|
const containsSettings = (root) => {
|
|
14519
|
-
const distance =
|
|
14585
|
+
const distance = relative5(canonical4(root), path);
|
|
14520
14586
|
return distance === "" || distance !== ".." && !distance.startsWith(`..${sep5}`) && !isAbsolute11(distance);
|
|
14521
14587
|
};
|
|
14522
14588
|
return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical4(join17(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical4(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
|
|
@@ -15261,7 +15327,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
15261
15327
|
return { action, path: skillMdPath };
|
|
15262
15328
|
const parentDir = dirname12(dir);
|
|
15263
15329
|
mkdirSync6(parentDir, { recursive: true });
|
|
15264
|
-
const transactionDir = mkdtempSync(join18(parentDir, `.hasna-skills-write-${
|
|
15330
|
+
const transactionDir = mkdtempSync(join18(parentDir, `.hasna-skills-write-${basename6(dir)}-`));
|
|
15265
15331
|
const candidateDir = join18(transactionDir, "candidate");
|
|
15266
15332
|
const backupDir = join18(transactionDir, "backup");
|
|
15267
15333
|
const candidateSkillMdPath = join18(candidateDir, "SKILL.md");
|
|
@@ -16566,7 +16632,7 @@ function directoryNames(path) {
|
|
|
16566
16632
|
function snapshotPluginTree(root, options = {}) {
|
|
16567
16633
|
const chain = ancestors(root), entries = [], files = [], directories = [];
|
|
16568
16634
|
let bytes = 0, visited = 0;
|
|
16569
|
-
const visit2 = (directory,
|
|
16635
|
+
const visit2 = (directory, relative6) => {
|
|
16570
16636
|
const before = stat(directory);
|
|
16571
16637
|
pluginNeed(before && before.isDirectory() && !before.isSymbolicLink(), "Plugin tree must contain real directories");
|
|
16572
16638
|
const names = directoryNames(directory);
|
|
@@ -16574,18 +16640,18 @@ function snapshotPluginTree(root, options = {}) {
|
|
|
16574
16640
|
directories.push({ path: directory, stat: before, names });
|
|
16575
16641
|
for (const name of names) {
|
|
16576
16642
|
pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
|
|
16577
|
-
const path =
|
|
16643
|
+
const path = relative6 ? `${relative6}/${name}` : name;
|
|
16578
16644
|
pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
|
|
16579
16645
|
const absolute = join23(directory, name), entryStat = stat(absolute);
|
|
16580
16646
|
pluginNeed(entryStat, "Plugin tree member disappeared");
|
|
16581
|
-
if (
|
|
16647
|
+
if (relative6 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
16582
16648
|
const bytes2 = readBytes(absolute, 32, "native-pin");
|
|
16583
16649
|
pluginNeed(/^[1-9][0-9]{12}$/.test(new TextDecoder().decode(bytes2)), "Malformed native orphan timestamp");
|
|
16584
16650
|
same3(entryStat, stat(absolute));
|
|
16585
16651
|
files.push({ path: absolute, stat: entryStat });
|
|
16586
16652
|
continue;
|
|
16587
16653
|
}
|
|
16588
|
-
if (
|
|
16654
|
+
if (relative6 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
16589
16655
|
pluginNeed(entryStat.isDirectory() && !entryStat.isSymbolicLink(), "Native plugin pins require a real directory");
|
|
16590
16656
|
owner(entryStat);
|
|
16591
16657
|
const pins = directoryNames(absolute);
|
|
@@ -17268,7 +17334,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
17268
17334
|
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join26(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
17269
17335
|
const approval = (producer) => {
|
|
17270
17336
|
pluginText(producer);
|
|
17271
|
-
const digest = `sha256:${
|
|
17337
|
+
const digest = `sha256:${basename7(producer)}`;
|
|
17272
17338
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest);
|
|
17273
17339
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
17274
17340
|
if (!verified.has(producer)) {
|
|
@@ -17332,7 +17398,7 @@ function captureManagedPluginRegistry(path, managedPlugins) {
|
|
|
17332
17398
|
// src/lib/claude-marketplace-registry.ts
|
|
17333
17399
|
import { createHash as createHash14 } from "crypto";
|
|
17334
17400
|
import { closeSync as closeSync11, constants as constants10, fstatSync as fstatSync11, lstatSync as lstatSync19, openSync as openSync11, readSync as readSync9 } from "fs";
|
|
17335
|
-
import { basename as
|
|
17401
|
+
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute15, resolve as resolve14 } from "path";
|
|
17336
17402
|
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
17337
17403
|
function need4(value, reason) {
|
|
17338
17404
|
if (!value)
|
|
@@ -17354,7 +17420,7 @@ function parents2(path) {
|
|
|
17354
17420
|
}
|
|
17355
17421
|
function readRegistry2(path, budget) {
|
|
17356
17422
|
absolutePath3(path);
|
|
17357
|
-
need4(
|
|
17423
|
+
need4(basename8(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
17358
17424
|
need4(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
|
|
17359
17425
|
const ancestors2 = parents2(path), initial = lstatSync19(path, { bigint: true });
|
|
17360
17426
|
need4(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
@@ -17694,9 +17760,9 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
17694
17760
|
safe4(root2);
|
|
17695
17761
|
}
|
|
17696
17762
|
function assertMarketplaceBinding(binding, source) {
|
|
17697
|
-
if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" ||
|
|
17763
|
+
if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
|
|
17698
17764
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
17699
|
-
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" ||
|
|
17765
|
+
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename9(source.path) !== "settings.json"))
|
|
17700
17766
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
17701
17767
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
17702
17768
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
@@ -17993,7 +18059,7 @@ function physicalPath(path) {
|
|
|
17993
18059
|
let cursor = resolve16(path);
|
|
17994
18060
|
const suffix = [];
|
|
17995
18061
|
while (!lstatSync22(cursor, { throwIfNoEntry: false })) {
|
|
17996
|
-
suffix.unshift(
|
|
18062
|
+
suffix.unshift(basename10(cursor));
|
|
17997
18063
|
const parent = dirname18(cursor);
|
|
17998
18064
|
if (parent === cursor)
|
|
17999
18065
|
return resolve16(path);
|
|
@@ -18212,7 +18278,7 @@ function physicalImportPath(path) {
|
|
|
18212
18278
|
let ancestor = resolve17(path);
|
|
18213
18279
|
const suffix = [];
|
|
18214
18280
|
while (!existsSync13(ancestor)) {
|
|
18215
|
-
suffix.unshift(
|
|
18281
|
+
suffix.unshift(basename11(ancestor));
|
|
18216
18282
|
ancestor = dirname19(ancestor);
|
|
18217
18283
|
}
|
|
18218
18284
|
return join29(realpathSync9(ancestor), ...suffix);
|
|
@@ -18221,7 +18287,7 @@ function assertDisjointImportPaths(source, destination) {
|
|
|
18221
18287
|
const sourcePath = realpathSync9(source);
|
|
18222
18288
|
const destinationPath = physicalImportPath(destination);
|
|
18223
18289
|
const contains2 = (parent, child) => {
|
|
18224
|
-
const path =
|
|
18290
|
+
const path = relative6(parent, child);
|
|
18225
18291
|
return path === "" || !isAbsolute17(path) && path !== ".." && !path.startsWith(`..${sep8}`);
|
|
18226
18292
|
};
|
|
18227
18293
|
if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
|
|
@@ -18237,8 +18303,8 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
18237
18303
|
const explicitName = options.name != null;
|
|
18238
18304
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
18239
18305
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
18240
|
-
const sourceSlug = safeNormalizeName(
|
|
18241
|
-
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${
|
|
18306
|
+
const sourceSlug = safeNormalizeName(basename11(absoluteSource));
|
|
18307
|
+
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename11(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
18242
18308
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
18243
18309
|
}
|
|
18244
18310
|
const readOnlyDestination = join29(resolvePortableSkillsRoot(options, false), skillName);
|
|
@@ -18821,7 +18887,7 @@ function getAllTags() {
|
|
|
18821
18887
|
// src/lib/run-state.ts
|
|
18822
18888
|
import { createHash as createHash18, randomBytes } from "crypto";
|
|
18823
18889
|
import { existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync19, readdirSync as readdirSync13, statSync as statSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
18824
|
-
import { extname, join as join31, relative as
|
|
18890
|
+
import { extname, join as join31, relative as relative7 } from "path";
|
|
18825
18891
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
18826
18892
|
const now = new Date;
|
|
18827
18893
|
const id = createRunId(now);
|
|
@@ -18977,7 +19043,7 @@ function createRunId(now) {
|
|
|
18977
19043
|
return `run_${now.getTime().toString(36)}_${randomBytes(4).toString("hex")}`;
|
|
18978
19044
|
}
|
|
18979
19045
|
function toProjectRelative(targetDir, path) {
|
|
18980
|
-
const rel =
|
|
19046
|
+
const rel = relative7(targetDir, path).split(/[\\/]/).join("/");
|
|
18981
19047
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
18982
19048
|
}
|
|
18983
19049
|
function mimeForPath(path) {
|
|
@@ -41951,7 +42017,7 @@ function findSkillsParityForMcpTool(tool) {
|
|
|
41951
42017
|
}
|
|
41952
42018
|
// src/lib/registry-sync.ts
|
|
41953
42019
|
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12 } from "fs";
|
|
41954
|
-
import { dirname as dirname21, relative as
|
|
42020
|
+
import { dirname as dirname21, relative as relative8 } from "path";
|
|
41955
42021
|
function createRegistrySyncArtifact(options = {}) {
|
|
41956
42022
|
const profile = options.profile ?? "all";
|
|
41957
42023
|
const includeDocs = options.includeDocs ?? true;
|
|
@@ -41963,7 +42029,7 @@ function createRegistrySyncArtifact(options = {}) {
|
|
|
41963
42029
|
const registry2 = [...loadRegistryProfile(profile)].sort((a, b) => a.name.localeCompare(b.name));
|
|
41964
42030
|
const skills = registry2.map((skill) => {
|
|
41965
42031
|
const skillPath = getSkillPath(skill.name);
|
|
41966
|
-
const directory2 =
|
|
42032
|
+
const directory2 = relative8(process.cwd(), skillPath) || skillPath;
|
|
41967
42033
|
const validation = includeValidation ? validateSkillDirectory(skill.name, skillPath, skill) : undefined;
|
|
41968
42034
|
const docs = includeDocs ? buildDocs(skill.name) : undefined;
|
|
41969
42035
|
return {
|
|
@@ -43161,7 +43227,7 @@ import {
|
|
|
43161
43227
|
statSync as statSync12,
|
|
43162
43228
|
writeFileSync as writeFileSync13
|
|
43163
43229
|
} from "fs";
|
|
43164
|
-
import { dirname as dirname23, join as join35, normalize as normalize4, relative as
|
|
43230
|
+
import { dirname as dirname23, join as join35, normalize as normalize4, relative as relative9, sep as sep9 } from "path";
|
|
43165
43231
|
var SKILLS_STORAGE_TABLES = [
|
|
43166
43232
|
"skills_sync_records",
|
|
43167
43233
|
"skills_sync_cursors"
|
|
@@ -43324,7 +43390,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
43324
43390
|
if (existsSync19(projectStateDir)) {
|
|
43325
43391
|
for (const filePath of walkFiles2(projectStateDir)) {
|
|
43326
43392
|
const bytes = readFileSync23(filePath);
|
|
43327
|
-
const relativePath = toPosix(
|
|
43393
|
+
const relativePath = toPosix(relative9(targetDir, filePath));
|
|
43328
43394
|
files.push({
|
|
43329
43395
|
path: relativePath,
|
|
43330
43396
|
sizeBytes: bytes.byteLength,
|
|
@@ -43745,7 +43811,7 @@ import {
|
|
|
43745
43811
|
statSync as statSync14,
|
|
43746
43812
|
writeFileSync as writeFileSync14
|
|
43747
43813
|
} from "fs";
|
|
43748
|
-
import { dirname as dirname24, isAbsolute as isAbsolute19, relative as
|
|
43814
|
+
import { dirname as dirname24, isAbsolute as isAbsolute19, relative as relative10, resolve as resolve18, sep as sep11 } from "path";
|
|
43749
43815
|
|
|
43750
43816
|
// src/lib/portable-snapshot-filter.ts
|
|
43751
43817
|
import { readdirSync as readdirSync15, statSync as statSync13 } from "fs";
|
|
@@ -44010,7 +44076,7 @@ function writeStationSnapshot(options) {
|
|
|
44010
44076
|
const untouched = [];
|
|
44011
44077
|
for (const plan of plans) {
|
|
44012
44078
|
const destination = resolve18(repoRoot, plan.destination);
|
|
44013
|
-
const destinationRelative =
|
|
44079
|
+
const destinationRelative = relative10(repoRoot, destination);
|
|
44014
44080
|
if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep11) || isAbsolute19(destinationRelative)) {
|
|
44015
44081
|
throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
|
|
44016
44082
|
}
|
|
@@ -44613,9 +44679,9 @@ async function buildSkillContext(input2, options = {}) {
|
|
|
44613
44679
|
if (prompt.length > 128 * 1024 || (input2.paths?.length ?? 0) > 100 || (input2.skills?.length ?? 0) > 100) {
|
|
44614
44680
|
throw new SkillSelectionError("CONTEXT_INPUT_TOO_LARGE", "The Skills context input exceeds its size limit.");
|
|
44615
44681
|
}
|
|
44616
|
-
const maxChars = options.maxChars
|
|
44682
|
+
const maxChars = options.maxChars;
|
|
44617
44683
|
const maxSkills = options.maxSkills ?? 3;
|
|
44618
|
-
if (!Number.isInteger(maxChars) || maxChars < 512 || maxChars > 64000 || !Number.isInteger(maxSkills) || maxSkills < 1 || maxSkills > 20) {
|
|
44684
|
+
if (maxChars !== undefined && (!Number.isInteger(maxChars) || maxChars < 512 || maxChars > 64000) || !Number.isInteger(maxSkills) || maxSkills < 1 || maxSkills > 20) {
|
|
44619
44685
|
throw new SkillSelectionError("INVALID_CONTEXT_BUDGET", "Context limits must be 512\u201364000 characters and 1\u201320 skills.");
|
|
44620
44686
|
}
|
|
44621
44687
|
const profileId = input2.profileId ?? "default";
|
|
@@ -44672,7 +44738,7 @@ async function buildSkillContext(input2, options = {}) {
|
|
|
44672
44738
|
const { content } = readSelectedDocument(entries);
|
|
44673
44739
|
const section = `Skill ${selection.slug}@${selection.version} (${selection.bundleDigest}; ${reason})
|
|
44674
44740
|
${content}`;
|
|
44675
|
-
if (chars + section.length + (sections.length ? 2 : 0) > maxChars) {
|
|
44741
|
+
if (maxChars !== undefined && chars + section.length + (sections.length ? 2 : 0) > maxChars) {
|
|
44676
44742
|
omitted.push({ slug: selection.slug, version: selection.version, reason: "context-budget", loadCommand });
|
|
44677
44743
|
continue;
|
|
44678
44744
|
}
|
|
@@ -44871,6 +44937,8 @@ export {
|
|
|
44871
44937
|
publicDiscoveryDocumentation,
|
|
44872
44938
|
publicDiscoveryDependencies,
|
|
44873
44939
|
projectCodexNativeSkillCatalog,
|
|
44940
|
+
projectCodexInstalledPlugins,
|
|
44941
|
+
projectCodexInstalledPluginEntries,
|
|
44874
44942
|
preparePrivatePublication,
|
|
44875
44943
|
portPortableSkillDirectory,
|
|
44876
44944
|
portPortableSkill,
|
|
@@ -10,10 +10,26 @@ export interface CodexNativeSkillCatalog {
|
|
|
10
10
|
version: string;
|
|
11
11
|
cwd: string;
|
|
12
12
|
skills: CodexNativeSkill[];
|
|
13
|
+
/** Added in 0.10.20; older reviewed skills/list receipts remain valid for listed skills. */
|
|
14
|
+
plugins?: CodexInstalledPlugin[];
|
|
15
|
+
}
|
|
16
|
+
/** Safe installed-plugin identity needed when Codex hides a path-disabled skill. */
|
|
17
|
+
export interface CodexInstalledPlugin {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
installed: boolean;
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
localVersion: string | null;
|
|
13
23
|
}
|
|
14
24
|
/** Project the measured native skills/list contract without retaining descriptions,
|
|
15
25
|
* links, interfaces, errors, or any other untrusted native text. */
|
|
16
26
|
export declare function projectCodexNativeSkillCatalog(response: unknown, cwd: string): CodexNativeSkill[];
|
|
27
|
+
/** Project only the installed plugin identity needed to bind cache inventory.
|
|
28
|
+
* Marketplace errors fail closed because an incomplete inventory cannot prove
|
|
29
|
+
* that an absent skill belongs to the one measured installed plugin. */
|
|
30
|
+
export declare function projectCodexInstalledPlugins(response: unknown): CodexInstalledPlugin[];
|
|
31
|
+
/** Validate the bounded stored projection when it is consumed by a review. */
|
|
32
|
+
export declare function projectCodexInstalledPluginEntries(value: unknown): CodexInstalledPlugin[];
|
|
17
33
|
/** Read one consumer's catalog through an owned, bounded native client. The RPC
|
|
18
34
|
* transport owns request deadlines and child shutdown. Native discovery can
|
|
19
35
|
* maintain its own caches; callers must constrain writes when requiring isolation. */
|
|
@@ -10,7 +10,7 @@ export interface CodexPluginSkillControl {
|
|
|
10
10
|
type Read = (path: string) => string;
|
|
11
11
|
/** Capability controls remain bound even after every native Skill body disappears. */
|
|
12
12
|
export declare function reviewedCodexPluginCapabilitiesUnchanged(cache: string, controls: CodexPluginSkillControl[], read: Read): boolean;
|
|
13
|
-
export declare function reviewCodexPluginSkillControls(catalog: CodexNativeSkillCatalog, documents: string[], cache: string, cwd: string, read: Read): CodexPluginSkillControl[];
|
|
13
|
+
export declare function reviewCodexPluginSkillControls(catalog: CodexNativeSkillCatalog, documents: string[], cache: string, cwd: string, read: Read, rules: unknown): CodexPluginSkillControl[];
|
|
14
14
|
export declare function isReviewedCodexPluginSkillDisabled(document: string, cache: string, controls: CodexPluginSkillControl[], rules: unknown, read: Read): boolean;
|
|
15
15
|
export declare function disableReviewedCodexPluginNames(text: string, controls: CodexPluginSkillControl[]): string;
|
|
16
16
|
export {};
|