@hasna/skills 0.10.18 → 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 +23 -7
- package/bin/index.js +266 -142
- 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/index.js
CHANGED
|
@@ -36868,7 +36868,7 @@ var package_default;
|
|
|
36868
36868
|
var init_package = __esm(() => {
|
|
36869
36869
|
package_default = {
|
|
36870
36870
|
name: "@hasna/skills",
|
|
36871
|
-
version: "0.10.
|
|
36871
|
+
version: "0.10.20",
|
|
36872
36872
|
description: "Skills library for AI coding agents",
|
|
36873
36873
|
type: "module",
|
|
36874
36874
|
bin: {
|
|
@@ -51052,6 +51052,59 @@ function projectCodexNativeSkillCatalog(response, cwd2) {
|
|
|
51052
51052
|
return { name: value.name, path: value.path, enabled: value.enabled, pluginId: value.pluginId ?? null };
|
|
51053
51053
|
});
|
|
51054
51054
|
}
|
|
51055
|
+
function projectCodexInstalledPlugins(response) {
|
|
51056
|
+
if (!object4(response) || !Array.isArray(response.marketplaces) || !Array.isArray(response.marketplaceLoadErrors) || response.marketplaceLoadErrors.length !== 0 || response.marketplaces.length > MAX_SKILLS)
|
|
51057
|
+
refuse();
|
|
51058
|
+
const plugins = [];
|
|
51059
|
+
for (const marketplace of response.marketplaces) {
|
|
51060
|
+
if (!object4(marketplace) || !scalar(marketplace.name, MAX_NAME_BYTES) || !Array.isArray(marketplace.plugins) || marketplace.plugins.length > MAX_SKILLS)
|
|
51061
|
+
refuse();
|
|
51062
|
+
for (const value of marketplace.plugins) {
|
|
51063
|
+
if (!object4(value) || !scalar(value.id, MAX_PLUGIN_ID_BYTES) || !scalar(value.name, MAX_NAME_BYTES) || value.id !== `${value.name}@${marketplace.name}`)
|
|
51064
|
+
refuse();
|
|
51065
|
+
plugins.push({ ...value, marketplace: marketplace.name });
|
|
51066
|
+
}
|
|
51067
|
+
}
|
|
51068
|
+
return projectCodexInstalledPluginEntries(plugins);
|
|
51069
|
+
}
|
|
51070
|
+
function projectCodexInstalledPluginEntries(value) {
|
|
51071
|
+
if (!Array.isArray(value) || value.length > MAX_SKILLS)
|
|
51072
|
+
refuse();
|
|
51073
|
+
const ids = new Set;
|
|
51074
|
+
return value.map((item) => {
|
|
51075
|
+
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))
|
|
51076
|
+
refuse();
|
|
51077
|
+
const at2 = item.id.lastIndexOf("@");
|
|
51078
|
+
if (at2 < 1 || item.id.slice(0, at2) !== item.name || at2 === item.id.length - 1 || ids.has(item.id))
|
|
51079
|
+
refuse();
|
|
51080
|
+
ids.add(item.id);
|
|
51081
|
+
return { id: item.id, name: item.name, installed: item.installed, enabled: item.enabled, localVersion: item.localVersion ?? null };
|
|
51082
|
+
});
|
|
51083
|
+
}
|
|
51084
|
+
async function captureCodexNativeSkillCatalog(options, connect = connectCodexHookRpc) {
|
|
51085
|
+
if (!absolutePath2(options.cwd) || !absolutePath2(options.home))
|
|
51086
|
+
refuse();
|
|
51087
|
+
const rpc = await connect({
|
|
51088
|
+
command: options.command,
|
|
51089
|
+
home: options.home,
|
|
51090
|
+
...options.codexHome === undefined ? {} : { codexHome: options.codexHome },
|
|
51091
|
+
...options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }
|
|
51092
|
+
});
|
|
51093
|
+
try {
|
|
51094
|
+
if (!SUPPORTED_NAME_CONTROL_VERSIONS.has(rpc.version))
|
|
51095
|
+
throw new Error("CODEX_NATIVE_SKILL_CATALOG_UNSUPPORTED_VERSION");
|
|
51096
|
+
const response = await rpc.request("skills/list", { cwds: [options.cwd], forceReload: true });
|
|
51097
|
+
const installed = await rpc.request("plugin/installed", { cwds: [options.cwd] });
|
|
51098
|
+
return {
|
|
51099
|
+
version: rpc.version,
|
|
51100
|
+
cwd: options.cwd,
|
|
51101
|
+
skills: projectCodexNativeSkillCatalog(response, options.cwd),
|
|
51102
|
+
plugins: projectCodexInstalledPlugins(installed)
|
|
51103
|
+
};
|
|
51104
|
+
} finally {
|
|
51105
|
+
await rpc.close();
|
|
51106
|
+
}
|
|
51107
|
+
}
|
|
51055
51108
|
function canonicalPath(path) {
|
|
51056
51109
|
try {
|
|
51057
51110
|
return realpathSync4(path);
|
|
@@ -51089,14 +51142,14 @@ function isCodexNativeSkillDisabled(skill, rules) {
|
|
|
51089
51142
|
}
|
|
51090
51143
|
return disabled;
|
|
51091
51144
|
}
|
|
51092
|
-
var MAX_SKILLS = 4096, MAX_NAME_BYTES = 1024, MAX_PATH_BYTES = 16384, SUPPORTED_NAME_CONTROL_VERSIONS, object4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), scalar = (value, max2) => typeof value === "string" && value.length > 0 && value.trim() === value && Buffer.byteLength(value, "utf8") <= max2 && !/[\u0000-\u001f\u007f]/u.test(value), absolutePath2 = (value) => scalar(value, MAX_PATH_BYTES) && isAbsolute10(value);
|
|
51145
|
+
var MAX_SKILLS = 4096, MAX_NAME_BYTES = 1024, MAX_PATH_BYTES = 16384, MAX_PLUGIN_ID_BYTES = 1024, SUPPORTED_NAME_CONTROL_VERSIONS, object4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), scalar = (value, max2) => typeof value === "string" && value.length > 0 && value.trim() === value && Buffer.byteLength(value, "utf8") <= max2 && !/[\u0000-\u001f\u007f]/u.test(value), absolutePath2 = (value) => scalar(value, MAX_PATH_BYTES) && isAbsolute10(value);
|
|
51093
51146
|
var init_codex_native_skill_catalog = __esm(() => {
|
|
51094
51147
|
init_codex_hook_rpc();
|
|
51095
51148
|
SUPPORTED_NAME_CONTROL_VERSIONS = new Set(["codex-cli 0.159.2"]);
|
|
51096
51149
|
});
|
|
51097
51150
|
|
|
51098
51151
|
// src/lib/codex-plugin-skill-controls.ts
|
|
51099
|
-
import { dirname as dirname10, join as join18, resolve as resolve10, sep as sep4 } from "path";
|
|
51152
|
+
import { basename as basename5, dirname as dirname10, join as join18, relative as relative4, resolve as resolve10, sep as sep4 } from "path";
|
|
51100
51153
|
import { lstatSync as lstatSync12, readdirSync as readdirSync6, readlinkSync as readlinkSync3, realpathSync as realpathSync5 } from "fs";
|
|
51101
51154
|
function refuse2() {
|
|
51102
51155
|
throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
|
|
@@ -51136,6 +51189,9 @@ function rootControls(root, read2) {
|
|
|
51136
51189
|
}
|
|
51137
51190
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier2(manifest.name))
|
|
51138
51191
|
refuse2();
|
|
51192
|
+
const cacheVersion = basename5(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
51193
|
+
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
51194
|
+
refuse2();
|
|
51139
51195
|
if (manifest.hooks !== undefined || manifest.mcpServers !== undefined || manifest.commands !== undefined || manifest.apps !== undefined && manifest.apps !== "./.app.json" || ["hooks", ".mcp.json"].some((path) => lstatSync12(join18(root, path), { throwIfNoEntry: false })))
|
|
51140
51196
|
refuse2();
|
|
51141
51197
|
const app = join18(root, ".app.json"), present = lstatSync12(app, { throwIfNoEntry: false });
|
|
@@ -51212,22 +51268,48 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache3, controls, read2) {
|
|
|
51212
51268
|
return false;
|
|
51213
51269
|
}
|
|
51214
51270
|
}
|
|
51215
|
-
function reviewCodexPluginSkillControls(catalog, documents, cache3, cwd2, read2) {
|
|
51271
|
+
function reviewCodexPluginSkillControls(catalog, documents, cache3, cwd2, read2, rules) {
|
|
51216
51272
|
if (catalog?.version !== "codex-cli 0.159.2" || catalog.cwd !== cwd2)
|
|
51217
51273
|
refuse2();
|
|
51218
51274
|
const skills = projectCodexNativeSkillCatalog({ data: [{ cwd: cwd2, errors: [], skills: catalog.skills }] }, cwd2);
|
|
51219
51275
|
const allowed = new Set(documents), result2 = [];
|
|
51220
|
-
|
|
51221
|
-
|
|
51276
|
+
let installedPlugins;
|
|
51277
|
+
try {
|
|
51278
|
+
installedPlugins = projectCodexInstalledPluginEntries(catalog.plugins ?? []);
|
|
51279
|
+
} catch {
|
|
51280
|
+
refuse2();
|
|
51281
|
+
}
|
|
51282
|
+
const candidates = catalog.plugins === undefined ? skills.map((skill) => skill.path).filter((path) => allowed.has(path)) : allowed;
|
|
51283
|
+
for (const document3 of candidates) {
|
|
51284
|
+
if (!document3.startsWith(cache3 + sep4))
|
|
51222
51285
|
continue;
|
|
51223
|
-
|
|
51286
|
+
const parsed = identity4(document3, cache3, read2);
|
|
51287
|
+
if (parsed.name === "skills-cli" || parsed.name.endsWith(":skills-cli"))
|
|
51288
|
+
refuse2();
|
|
51289
|
+
const cacheParts = relative4(cache3, parsed.pluginParent).split(sep4);
|
|
51290
|
+
if (cacheParts.length !== 2 || cacheParts.some((part) => !identifier2(part)))
|
|
51224
51291
|
refuse2();
|
|
51225
|
-
|
|
51292
|
+
const [marketplace, pluginName] = cacheParts;
|
|
51293
|
+
if (pluginName !== parsed.namespace)
|
|
51226
51294
|
refuse2();
|
|
51227
|
-
const
|
|
51228
|
-
|
|
51295
|
+
const expectedPluginId = `${pluginName}@${marketplace}`;
|
|
51296
|
+
const listed = skills.filter((skill) => skill.path === document3);
|
|
51297
|
+
if (listed.length > 1)
|
|
51229
51298
|
refuse2();
|
|
51230
|
-
|
|
51299
|
+
if (listed.length === 1) {
|
|
51300
|
+
if (listed[0].name !== parsed.name || listed[0].pluginId !== expectedPluginId)
|
|
51301
|
+
refuse2();
|
|
51302
|
+
} else {
|
|
51303
|
+
const installed = installedPlugins.filter((plugin) => plugin.id === expectedPluginId && plugin.name === pluginName);
|
|
51304
|
+
if (installed.length !== 1 || !installed[0].installed || !installed[0].enabled || !installed[0].localVersion)
|
|
51305
|
+
refuse2();
|
|
51306
|
+
if (installed[0].localVersion !== basename5(dirname10(dirname10(dirname10(document3)))))
|
|
51307
|
+
continue;
|
|
51308
|
+
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document3 && rule?.enabled === false);
|
|
51309
|
+
if (!exactPathDeny || !isCodexNativeSkillDisabled({ name: parsed.name, path: document3, pluginId: expectedPluginId, enabled: true }, rules))
|
|
51310
|
+
refuse2();
|
|
51311
|
+
}
|
|
51312
|
+
result2.push({ ...parsed, pluginId: expectedPluginId });
|
|
51231
51313
|
}
|
|
51232
51314
|
if (!result2.length || new Set(result2.map((item) => item.name)).size !== result2.length)
|
|
51233
51315
|
refuse2();
|
|
@@ -51261,7 +51343,7 @@ enabled = false
|
|
|
51261
51343
|
}
|
|
51262
51344
|
return text2;
|
|
51263
51345
|
}
|
|
51264
|
-
var identifier2 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v);
|
|
51346
|
+
var identifier2 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v), CODEX_DEFAULT_AGENT_PLUGIN_VERSION = "1.0.0";
|
|
51265
51347
|
var init_codex_plugin_skill_controls = __esm(() => {
|
|
51266
51348
|
init_claude_settings_witness();
|
|
51267
51349
|
init_codex_native_skill_catalog();
|
|
@@ -51776,7 +51858,7 @@ var init_agent_codex = __esm(() => {
|
|
|
51776
51858
|
// src/lib/agent-integration.ts
|
|
51777
51859
|
import { createHash as createHash11, randomUUID as randomUUID5 } from "crypto";
|
|
51778
51860
|
import { existsSync as existsSync12, lstatSync as lstatSync15, statSync as statSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync13, 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 constants8, linkSync } from "fs";
|
|
51779
|
-
import { dirname as dirname11, join as join21, resolve as resolve11, relative as
|
|
51861
|
+
import { dirname as dirname11, join as join21, resolve as resolve11, relative as relative5, isAbsolute as isAbsolute11, sep as sep5 } from "path";
|
|
51780
51862
|
import { homedir as homedir3 } from "os";
|
|
51781
51863
|
function assertSafePath(path) {
|
|
51782
51864
|
let cursor = resolve11(path);
|
|
@@ -51800,7 +51882,7 @@ function readRootAlias(home, agent) {
|
|
|
51800
51882
|
const targetStat = lstatSync15(targetPath, { throwIfNoEntry: false });
|
|
51801
51883
|
if (!targetStat?.isDirectory())
|
|
51802
51884
|
throw new Error(`Agent root alias must target an existing directory: ${alias}`);
|
|
51803
|
-
const target = realpathSync6(targetPath), inside =
|
|
51885
|
+
const target = realpathSync6(targetPath), inside = relative5(realHome, target);
|
|
51804
51886
|
if (!inside || inside === ".." || inside.startsWith(`..${sep5}`) || isAbsolute11(inside))
|
|
51805
51887
|
throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
|
|
51806
51888
|
return { agent, home: realHome, alias, target, link: link2, aliasIdentity: `${stat.dev}:${stat.ino}:${stat.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
|
|
@@ -51818,7 +51900,7 @@ function rootAliases(home, allowed = false) {
|
|
|
51818
51900
|
}
|
|
51819
51901
|
function canonicalAgentPath(path, aliases) {
|
|
51820
51902
|
const absolute = resolve11(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep5));
|
|
51821
|
-
return binding ? join21(binding.target,
|
|
51903
|
+
return binding ? join21(binding.target, relative5(binding.alias, absolute)) : absolute;
|
|
51822
51904
|
}
|
|
51823
51905
|
function disabledCodexSkillPaths(config, aliases) {
|
|
51824
51906
|
const skills = config.skills;
|
|
@@ -51889,7 +51971,7 @@ function treeHash(root) {
|
|
|
51889
51971
|
const stat = lstatSync15(path);
|
|
51890
51972
|
if (stat.isSymbolicLink())
|
|
51891
51973
|
throw new Error(`Refusing symlink in skill: ${path}`);
|
|
51892
|
-
const rel =
|
|
51974
|
+
const rel = relative5(root, path);
|
|
51893
51975
|
if (stat.isDirectory()) {
|
|
51894
51976
|
hash2.update(`d\x00${rel}\x00`);
|
|
51895
51977
|
for (const name of readdirSync8(path).sort())
|
|
@@ -51940,7 +52022,7 @@ function parseNativeMigrationTargetManifest(input) {
|
|
|
51940
52022
|
assertSafePath(projectRoot);
|
|
51941
52023
|
if (isAbsolute11(item.path) || item.path.includes("\\") || item.path.length === 0 || item.path.includes("\x00"))
|
|
51942
52024
|
throw new Error(`Native migration target path must be normalized and project-relative: ${item.path}`);
|
|
51943
|
-
const resolved = resolve11(projectRoot, item.path), normalized =
|
|
52025
|
+
const resolved = resolve11(projectRoot, item.path), normalized = relative5(projectRoot, resolved);
|
|
51944
52026
|
if (!normalized || normalized === ".." || normalized.startsWith(`..${sep5}`) || isAbsolute11(normalized) || normalized !== item.path)
|
|
51945
52027
|
throw new Error(`Native migration target path escapes or is not normalized: ${item.path}`);
|
|
51946
52028
|
if (!/^[0-9a-f]{64}$/.test(item.treeSha256))
|
|
@@ -51962,7 +52044,7 @@ function selectNativeMigrationTargets(inventory, manifest) {
|
|
|
51962
52044
|
const identities = new Set;
|
|
51963
52045
|
const selected = [];
|
|
51964
52046
|
for (const target of manifest.targets) {
|
|
51965
|
-
const projectRoot = resolve11(target.projectRoot), normalized =
|
|
52047
|
+
const projectRoot = resolve11(target.projectRoot), normalized = relative5(projectRoot, resolve11(projectRoot, target.path));
|
|
51966
52048
|
if (!isAbsolute11(target.projectRoot) || projectRoot !== target.projectRoot || !existsSync12(projectRoot) || !lstatSync15(projectRoot).isDirectory())
|
|
51967
52049
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
|
|
51968
52050
|
assertSafePath(projectRoot);
|
|
@@ -52317,7 +52399,7 @@ function planAgentIntegration(options) {
|
|
|
52317
52399
|
const bytes = readNativeBytes(path, 1024 * 1024);
|
|
52318
52400
|
observedNativeSources.push({ path, sha256: sha2(bytes) });
|
|
52319
52401
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
52320
|
-
}) : policy.bridge?.codexPluginSkills ?? [];
|
|
52402
|
+
}, codexConfig.skills?.config ?? []) : policy.bridge?.codexPluginSkills ?? [];
|
|
52321
52403
|
const changes = [];
|
|
52322
52404
|
for (const agent of [...new Set(options.agents)]) {
|
|
52323
52405
|
if (!INTEGRATION_AGENTS.includes(agent))
|
|
@@ -52395,7 +52477,7 @@ function planAgentIntegration(options) {
|
|
|
52395
52477
|
profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
|
|
52396
52478
|
disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join21(home, ".codex", "skills", ".system"), aliases) + sep5)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
|
|
52397
52479
|
rootAliases: aliases,
|
|
52398
|
-
...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(join21(home, ".codex/config.toml"), aliases))?.before === null ? null : sha2(readOptional(canonicalAgentPath(join21(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
|
|
52480
|
+
...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(join21(home, ".codex/config.toml"), aliases))?.before === null ? null : sha2(readOptional(canonicalAgentPath(join21(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
|
|
52399
52481
|
discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
|
|
52400
52482
|
} };
|
|
52401
52483
|
const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
|
|
@@ -53033,7 +53115,7 @@ import {
|
|
|
53033
53115
|
writeFileSync as writeFileSync6
|
|
53034
53116
|
} from "fs";
|
|
53035
53117
|
import { homedir as homedir4 } from "os";
|
|
53036
|
-
import { basename as
|
|
53118
|
+
import { basename as basename6, dirname as dirname12, join as join25 } from "path";
|
|
53037
53119
|
function isSkillsOwnershipMarker(marker) {
|
|
53038
53120
|
return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
|
|
53039
53121
|
}
|
|
@@ -53267,7 +53349,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
53267
53349
|
return { action, path: skillMdPath };
|
|
53268
53350
|
const parentDir = dirname12(dir);
|
|
53269
53351
|
mkdirSync7(parentDir, { recursive: true });
|
|
53270
|
-
const transactionDir = mkdtempSync(join25(parentDir, `.hasna-skills-write-${
|
|
53352
|
+
const transactionDir = mkdtempSync(join25(parentDir, `.hasna-skills-write-${basename6(dir)}-`));
|
|
53271
53353
|
const candidateDir = join25(transactionDir, "candidate");
|
|
53272
53354
|
const backupDir = join25(transactionDir, "backup");
|
|
53273
53355
|
const candidateSkillMdPath = join25(candidateDir, "SKILL.md");
|
|
@@ -54780,7 +54862,7 @@ function directoryNames(path) {
|
|
|
54780
54862
|
function snapshotPluginTree(root, options = {}) {
|
|
54781
54863
|
const chain = ancestors(root), entries = [], files = [], directories = [];
|
|
54782
54864
|
let bytes = 0, visited = 0;
|
|
54783
|
-
const visit2 = (directory,
|
|
54865
|
+
const visit2 = (directory, relative6) => {
|
|
54784
54866
|
const before2 = stat(directory);
|
|
54785
54867
|
pluginNeed(before2 && before2.isDirectory() && !before2.isSymbolicLink(), "Plugin tree must contain real directories");
|
|
54786
54868
|
const names = directoryNames(directory);
|
|
@@ -54788,18 +54870,18 @@ function snapshotPluginTree(root, options = {}) {
|
|
|
54788
54870
|
directories.push({ path: directory, stat: before2, names });
|
|
54789
54871
|
for (const name of names) {
|
|
54790
54872
|
pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
|
|
54791
|
-
const path =
|
|
54873
|
+
const path = relative6 ? `${relative6}/${name}` : name;
|
|
54792
54874
|
pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
|
|
54793
54875
|
const absolute = join29(directory, name), entryStat = stat(absolute);
|
|
54794
54876
|
pluginNeed(entryStat, "Plugin tree member disappeared");
|
|
54795
|
-
if (
|
|
54877
|
+
if (relative6 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
54796
54878
|
const bytes2 = readBytes(absolute, 32, "native-pin");
|
|
54797
54879
|
pluginNeed(/^[1-9][0-9]{12}$/.test(new TextDecoder().decode(bytes2)), "Malformed native orphan timestamp");
|
|
54798
54880
|
same3(entryStat, stat(absolute));
|
|
54799
54881
|
files.push({ path: absolute, stat: entryStat });
|
|
54800
54882
|
continue;
|
|
54801
54883
|
}
|
|
54802
|
-
if (
|
|
54884
|
+
if (relative6 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
54803
54885
|
pluginNeed(entryStat.isDirectory() && !entryStat.isSymbolicLink(), "Native plugin pins require a real directory");
|
|
54804
54886
|
owner(entryStat);
|
|
54805
54887
|
const pins = directoryNames(absolute);
|
|
@@ -55421,7 +55503,7 @@ var init_plugin_admission = __esm(() => {
|
|
|
55421
55503
|
|
|
55422
55504
|
// src/lib/plugin-discovery.ts
|
|
55423
55505
|
import { closeSync as closeSync10, constants as constants10, fstatSync as fstatSync10, lstatSync as lstatSync18, openSync as openSync10, opendirSync as opendirSync5, readSync as readSync8 } from "fs";
|
|
55424
|
-
import { basename as
|
|
55506
|
+
import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute14, join as join31, resolve as resolve14 } from "path";
|
|
55425
55507
|
function validateManagedPluginWitnesses(value) {
|
|
55426
55508
|
pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
|
|
55427
55509
|
const seen = new Set;
|
|
@@ -55504,7 +55586,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
55504
55586
|
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join31(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
55505
55587
|
const approval = (producer) => {
|
|
55506
55588
|
pluginText(producer);
|
|
55507
|
-
const digest = `sha256:${
|
|
55589
|
+
const digest = `sha256:${basename7(producer)}`;
|
|
55508
55590
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest);
|
|
55509
55591
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
55510
55592
|
if (!verified.has(producer)) {
|
|
@@ -55570,7 +55652,7 @@ var init_plugin_discovery = __esm(() => {
|
|
|
55570
55652
|
// src/lib/claude-marketplace-registry.ts
|
|
55571
55653
|
import { createHash as createHash14 } from "crypto";
|
|
55572
55654
|
import { closeSync as closeSync11, constants as constants11, fstatSync as fstatSync11, lstatSync as lstatSync19, openSync as openSync11, readSync as readSync9 } from "fs";
|
|
55573
|
-
import { basename as
|
|
55655
|
+
import { basename as basename8, dirname as dirname15, isAbsolute as isAbsolute15, resolve as resolve15 } from "path";
|
|
55574
55656
|
function need4(value, reason) {
|
|
55575
55657
|
if (!value)
|
|
55576
55658
|
throw new Error(`Claude marketplace registry ${reason}`);
|
|
@@ -55590,7 +55672,7 @@ function parents2(path) {
|
|
|
55590
55672
|
}
|
|
55591
55673
|
function readRegistry2(path, budget) {
|
|
55592
55674
|
absolutePath3(path);
|
|
55593
|
-
need4(
|
|
55675
|
+
need4(basename8(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
55594
55676
|
need4(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
|
|
55595
55677
|
const ancestors2 = parents2(path), initial2 = lstatSync19(path, { bigint: true });
|
|
55596
55678
|
need4(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
@@ -56088,7 +56170,7 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
56088
56170
|
// src/lib/agent-discovery.ts
|
|
56089
56171
|
import { createHash as createHash17 } from "crypto";
|
|
56090
56172
|
import { lstatSync as lstatSync21, readFileSync as readFileSync18, readdirSync as readdirSync11, realpathSync as realpathSync7 } from "fs";
|
|
56091
|
-
import { basename as
|
|
56173
|
+
import { basename as basename9, dirname as dirname17, isAbsolute as isAbsolute17, join as join32, resolve as resolve16, sep as sep6 } from "path";
|
|
56092
56174
|
import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
|
|
56093
56175
|
function parseConfig(text3, path, toml = false) {
|
|
56094
56176
|
try {
|
|
@@ -56198,9 +56280,9 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
56198
56280
|
safe4(root2);
|
|
56199
56281
|
}
|
|
56200
56282
|
function assertMarketplaceBinding(binding, source) {
|
|
56201
|
-
if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" ||
|
|
56283
|
+
if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" || basename9(source.path) !== "config.toml"))
|
|
56202
56284
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
56203
|
-
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" ||
|
|
56285
|
+
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"))
|
|
56204
56286
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
56205
56287
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
56206
56288
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
@@ -56483,7 +56565,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
56483
56565
|
// src/lib/authoring-path.ts
|
|
56484
56566
|
import { lstatSync as lstatSync22, realpathSync as realpathSync8 } from "fs";
|
|
56485
56567
|
import { homedir as homedir7 } from "os";
|
|
56486
|
-
import { basename as
|
|
56568
|
+
import { basename as basename10, dirname as dirname18, join as join33, resolve as resolve17, sep as sep7 } from "path";
|
|
56487
56569
|
function pathParts(path) {
|
|
56488
56570
|
return resolve17(path).split(sep7).filter(Boolean);
|
|
56489
56571
|
}
|
|
@@ -56502,7 +56584,7 @@ function physicalPath(path) {
|
|
|
56502
56584
|
let cursor = resolve17(path);
|
|
56503
56585
|
const suffix = [];
|
|
56504
56586
|
while (!lstatSync22(cursor, { throwIfNoEntry: false })) {
|
|
56505
|
-
suffix.unshift(
|
|
56587
|
+
suffix.unshift(basename10(cursor));
|
|
56506
56588
|
const parent = dirname18(cursor);
|
|
56507
56589
|
if (parent === cursor)
|
|
56508
56590
|
return resolve17(path);
|
|
@@ -56597,7 +56679,7 @@ import {
|
|
|
56597
56679
|
statSync as statSync11,
|
|
56598
56680
|
writeFileSync as writeFileSync9
|
|
56599
56681
|
} from "fs";
|
|
56600
|
-
import { basename as
|
|
56682
|
+
import { basename as basename11, dirname as dirname19, isAbsolute as isAbsolute18, join as join34, normalize as normalize3, relative as relative6, resolve as resolve18, sep as sep8 } from "path";
|
|
56601
56683
|
function getPortableSkillsRoot(options = {}) {
|
|
56602
56684
|
return resolvePortableSkillsRoot(options, true);
|
|
56603
56685
|
}
|
|
@@ -56745,7 +56827,7 @@ function physicalImportPath(path) {
|
|
|
56745
56827
|
let ancestor = resolve18(path);
|
|
56746
56828
|
const suffix = [];
|
|
56747
56829
|
while (!existsSync18(ancestor)) {
|
|
56748
|
-
suffix.unshift(
|
|
56830
|
+
suffix.unshift(basename11(ancestor));
|
|
56749
56831
|
ancestor = dirname19(ancestor);
|
|
56750
56832
|
}
|
|
56751
56833
|
return join34(realpathSync9(ancestor), ...suffix);
|
|
@@ -56754,7 +56836,7 @@ function assertDisjointImportPaths(source, destination) {
|
|
|
56754
56836
|
const sourcePath = realpathSync9(source);
|
|
56755
56837
|
const destinationPath = physicalImportPath(destination);
|
|
56756
56838
|
const contains2 = (parent, child) => {
|
|
56757
|
-
const path =
|
|
56839
|
+
const path = relative6(parent, child);
|
|
56758
56840
|
return path === "" || !isAbsolute18(path) && path !== ".." && !path.startsWith(`..${sep8}`);
|
|
56759
56841
|
};
|
|
56760
56842
|
if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
|
|
@@ -56770,8 +56852,8 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
56770
56852
|
const explicitName = options.name != null;
|
|
56771
56853
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
56772
56854
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
56773
|
-
const sourceSlug = safeNormalizeName(
|
|
56774
|
-
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${
|
|
56855
|
+
const sourceSlug = safeNormalizeName(basename11(absoluteSource));
|
|
56856
|
+
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.`;
|
|
56775
56857
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
56776
56858
|
}
|
|
56777
56859
|
const readOnlyDestination = join34(resolvePortableSkillsRoot(options, false), skillName);
|
|
@@ -58980,13 +59062,13 @@ var require_cli_spinners = __commonJS((exports, module) => {
|
|
|
58980
59062
|
|
|
58981
59063
|
// src/lib/auth-store.ts
|
|
58982
59064
|
import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync20, renameSync as renameSync7, statSync as statSync12, unlinkSync as unlinkSync5, writeFileSync as writeFileSync10 } from "fs";
|
|
58983
|
-
import { basename as
|
|
59065
|
+
import { basename as basename12, dirname as dirname20, join as join36 } from "path";
|
|
58984
59066
|
function getAuthFilePath(env3 = process.env) {
|
|
58985
59067
|
return skillsCredentialFilePath(env3);
|
|
58986
59068
|
}
|
|
58987
59069
|
function getIdentityFilePath(env3 = process.env) {
|
|
58988
59070
|
const file = skillsCredentialFilePath(env3);
|
|
58989
|
-
return join36(dirname20(file),
|
|
59071
|
+
return join36(dirname20(file), basename12(file).replace(/^credentials/, "identity") + ".json");
|
|
58990
59072
|
}
|
|
58991
59073
|
function getAuthIdentity(env3 = process.env) {
|
|
58992
59074
|
return readIdentity(env3);
|
|
@@ -81010,7 +81092,7 @@ var init_remote_auth = __esm(() => {
|
|
|
81010
81092
|
// src/lib/sign-in.ts
|
|
81011
81093
|
import { createHash as createHash20 } from "crypto";
|
|
81012
81094
|
import { chmodSync as chmodSync3, mkdirSync as mkdirSync12, readFileSync as readFileSync21, readdirSync as readdirSync14, renameSync as renameSync8, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
|
|
81013
|
-
import { basename as
|
|
81095
|
+
import { basename as basename13, dirname as dirname21, join as join37 } from "path";
|
|
81014
81096
|
function isRecord6(value) {
|
|
81015
81097
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
81016
81098
|
}
|
|
@@ -81155,7 +81237,7 @@ async function pollDeviceAuthorization(input2) {
|
|
|
81155
81237
|
}
|
|
81156
81238
|
function pendingDeviceSignInStem(env3) {
|
|
81157
81239
|
const file2 = skillsCredentialFilePath(env3);
|
|
81158
|
-
return { dir: dirname21(file2), stem:
|
|
81240
|
+
return { dir: dirname21(file2), stem: basename13(file2).replace(/^credentials/, "device-login") };
|
|
81159
81241
|
}
|
|
81160
81242
|
function pendingDeviceSignInPath(origin, env3 = process.env) {
|
|
81161
81243
|
const { dir, stem } = pendingDeviceSignInStem(env3);
|
|
@@ -82340,9 +82422,9 @@ async function buildSkillContext(input2, options = {}) {
|
|
|
82340
82422
|
if (prompt.length > 128 * 1024 || (input2.paths?.length ?? 0) > 100 || (input2.skills?.length ?? 0) > 100) {
|
|
82341
82423
|
throw new SkillSelectionError("CONTEXT_INPUT_TOO_LARGE", "The Skills context input exceeds its size limit.");
|
|
82342
82424
|
}
|
|
82343
|
-
const maxChars = options.maxChars
|
|
82425
|
+
const maxChars = options.maxChars;
|
|
82344
82426
|
const maxSkills = options.maxSkills ?? 3;
|
|
82345
|
-
if (!Number.isInteger(maxChars) || maxChars < 512 || maxChars > 64000 || !Number.isInteger(maxSkills) || maxSkills < 1 || maxSkills > 20) {
|
|
82427
|
+
if (maxChars !== undefined && (!Number.isInteger(maxChars) || maxChars < 512 || maxChars > 64000) || !Number.isInteger(maxSkills) || maxSkills < 1 || maxSkills > 20) {
|
|
82346
82428
|
throw new SkillSelectionError("INVALID_CONTEXT_BUDGET", "Context limits must be 512\u201364000 characters and 1\u201320 skills.");
|
|
82347
82429
|
}
|
|
82348
82430
|
const profileId = input2.profileId ?? "default";
|
|
@@ -82399,7 +82481,7 @@ async function buildSkillContext(input2, options = {}) {
|
|
|
82399
82481
|
const { content } = readSelectedDocument(entries);
|
|
82400
82482
|
const section = `Skill ${selection.slug}@${selection.version} (${selection.bundleDigest}; ${reason})
|
|
82401
82483
|
${content}`;
|
|
82402
|
-
if (chars + section.length + (sections.length ? 2 : 0) > maxChars) {
|
|
82484
|
+
if (maxChars !== undefined && chars + section.length + (sections.length ? 2 : 0) > maxChars) {
|
|
82403
82485
|
omitted.push({ slug: selection.slug, version: selection.version, reason: "context-budget", loadCommand });
|
|
82404
82486
|
continue;
|
|
82405
82487
|
}
|
|
@@ -82655,7 +82737,7 @@ Preserved original receipt: ${result2.archivePath}` : `Planned one session recon
|
|
|
82655
82737
|
reportContextError(error61, options.json);
|
|
82656
82738
|
}
|
|
82657
82739
|
});
|
|
82658
|
-
parent.command("context [prompt]").description("Select bounded, versioned skill context for this prompt without running skills").option("--stdin", "Read native hook JSON or a prompt from stdin", false).option("--selection-profile <id>", "Selection profile (separate from the credential --profile)").option("--cached", "Use only an explicitly selected verified cache, at most 24 hours old", false).option("--auto-reconcile-safe", "For managed hooks, archive and renew an expired session only when all loaded selections are unchanged", false).option("--session <id>", "Keep the same skill versions across this session").option("--restore", "Re-emit loaded session context after compaction or resume", false).option("--max-chars <count>", "
|
|
82740
|
+
parent.command("context [prompt]").description("Select bounded, versioned skill context for this prompt without running skills").option("--stdin", "Read native hook JSON or a prompt from stdin", false).option("--selection-profile <id>", "Selection profile (separate from the credential --profile)").option("--cached", "Use only an explicitly selected verified cache, at most 24 hours old", false).option("--auto-reconcile-safe", "For managed hooks, archive and renew an expired session only when all loaded selections are unchanged", false).option("--session <id>", "Keep the same skill versions across this session").option("--restore", "Re-emit loaded session context after compaction or resume", false).option("--max-chars <count>", "Optional maximum injected characters").option("--max-skills <count>", "Maximum loaded skills", "3").option("--json", "Return context and selection receipts as JSON", false).action(async (prompt, options) => {
|
|
82659
82741
|
try {
|
|
82660
82742
|
if (options.autoReconcileSafe && !options.cached)
|
|
82661
82743
|
throw new SkillSelectionError("INVALID_CONTEXT_INPUT", "--auto-reconcile-safe requires --cached.");
|
|
@@ -82664,7 +82746,7 @@ Preserved original receipt: ${result2.archivePath}` : `Planned one session recon
|
|
|
82664
82746
|
input2.cwd ??= process.cwd();
|
|
82665
82747
|
input2.sessionId = options.session ?? input2.sessionId;
|
|
82666
82748
|
input2.restore ||= options.restore;
|
|
82667
|
-
const resolverOptions = { ...contextResolverOptions(options), maxChars: Number(options.maxChars), maxSkills: Number(options.maxSkills) };
|
|
82749
|
+
const resolverOptions = { ...contextResolverOptions(options), ...options.maxChars === undefined ? {} : { maxChars: Number(options.maxChars) }, maxSkills: Number(options.maxSkills) };
|
|
82668
82750
|
let result2;
|
|
82669
82751
|
try {
|
|
82670
82752
|
result2 = await buildSkillContext(input2, resolverOptions);
|
|
@@ -91520,7 +91602,7 @@ var init_runs = __esm(() => {
|
|
|
91520
91602
|
// src/lib/run-state.ts
|
|
91521
91603
|
import { createHash as createHash25, randomBytes } from "crypto";
|
|
91522
91604
|
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync32, readdirSync as readdirSync18, statSync as statSync16, writeFileSync as writeFileSync16 } from "fs";
|
|
91523
|
-
import { extname, join as join46, relative as
|
|
91605
|
+
import { extname, join as join46, relative as relative7 } from "path";
|
|
91524
91606
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
91525
91607
|
const now3 = new Date;
|
|
91526
91608
|
const id2 = createRunId(now3);
|
|
@@ -91686,7 +91768,7 @@ function createRunId(now3) {
|
|
|
91686
91768
|
return `run_${now3.getTime().toString(36)}_${randomBytes(4).toString("hex")}`;
|
|
91687
91769
|
}
|
|
91688
91770
|
function toProjectRelative(targetDir, path) {
|
|
91689
|
-
const rel =
|
|
91771
|
+
const rel = relative7(targetDir, path).split(/[\\/]/).join("/");
|
|
91690
91772
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
91691
91773
|
}
|
|
91692
91774
|
function mimeForPath(path) {
|
|
@@ -98982,49 +99064,49 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
98982
99064
|
schemelessOptions.skipEscape = true;
|
|
98983
99065
|
return serialize(resolved, schemelessOptions);
|
|
98984
99066
|
}
|
|
98985
|
-
function resolveComponent(base2,
|
|
99067
|
+
function resolveComponent(base2, relative8, options, skipNormalization) {
|
|
98986
99068
|
const target = {};
|
|
98987
99069
|
if (!skipNormalization) {
|
|
98988
99070
|
base2 = parse12(serialize(base2, options), options);
|
|
98989
|
-
|
|
99071
|
+
relative8 = parse12(serialize(relative8, options), options);
|
|
98990
99072
|
}
|
|
98991
99073
|
options = options || {};
|
|
98992
|
-
if (!options.tolerant &&
|
|
98993
|
-
target.scheme =
|
|
98994
|
-
target.userinfo =
|
|
98995
|
-
target.host =
|
|
98996
|
-
target.port =
|
|
98997
|
-
target.path = removeDotSegments(
|
|
98998
|
-
target.query =
|
|
99074
|
+
if (!options.tolerant && relative8.scheme) {
|
|
99075
|
+
target.scheme = relative8.scheme;
|
|
99076
|
+
target.userinfo = relative8.userinfo;
|
|
99077
|
+
target.host = relative8.host;
|
|
99078
|
+
target.port = relative8.port;
|
|
99079
|
+
target.path = removeDotSegments(relative8.path || "");
|
|
99080
|
+
target.query = relative8.query;
|
|
98999
99081
|
} else {
|
|
99000
|
-
if (
|
|
99001
|
-
target.userinfo =
|
|
99002
|
-
target.host =
|
|
99003
|
-
target.port =
|
|
99004
|
-
target.path = removeDotSegments(
|
|
99005
|
-
target.query =
|
|
99082
|
+
if (relative8.userinfo !== undefined || relative8.host !== undefined || relative8.port !== undefined) {
|
|
99083
|
+
target.userinfo = relative8.userinfo;
|
|
99084
|
+
target.host = relative8.host;
|
|
99085
|
+
target.port = relative8.port;
|
|
99086
|
+
target.path = removeDotSegments(relative8.path || "");
|
|
99087
|
+
target.query = relative8.query;
|
|
99006
99088
|
} else {
|
|
99007
|
-
if (!
|
|
99089
|
+
if (!relative8.path) {
|
|
99008
99090
|
target.path = base2.path;
|
|
99009
|
-
if (
|
|
99010
|
-
target.query =
|
|
99091
|
+
if (relative8.query !== undefined) {
|
|
99092
|
+
target.query = relative8.query;
|
|
99011
99093
|
} else {
|
|
99012
99094
|
target.query = base2.query;
|
|
99013
99095
|
}
|
|
99014
99096
|
} else {
|
|
99015
|
-
if (
|
|
99016
|
-
target.path = removeDotSegments(
|
|
99097
|
+
if (relative8.path[0] === "/") {
|
|
99098
|
+
target.path = removeDotSegments(relative8.path);
|
|
99017
99099
|
} else {
|
|
99018
99100
|
if ((base2.userinfo !== undefined || base2.host !== undefined || base2.port !== undefined) && !base2.path) {
|
|
99019
|
-
target.path = "/" +
|
|
99101
|
+
target.path = "/" + relative8.path;
|
|
99020
99102
|
} else if (!base2.path) {
|
|
99021
|
-
target.path =
|
|
99103
|
+
target.path = relative8.path;
|
|
99022
99104
|
} else {
|
|
99023
|
-
target.path = base2.path.slice(0, base2.path.lastIndexOf("/") + 1) +
|
|
99105
|
+
target.path = base2.path.slice(0, base2.path.lastIndexOf("/") + 1) + relative8.path;
|
|
99024
99106
|
}
|
|
99025
99107
|
target.path = removeDotSegments(target.path);
|
|
99026
99108
|
}
|
|
99027
|
-
target.query =
|
|
99109
|
+
target.query = relative8.query;
|
|
99028
99110
|
}
|
|
99029
99111
|
target.userinfo = base2.userinfo;
|
|
99030
99112
|
target.host = base2.host;
|
|
@@ -99032,7 +99114,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
99032
99114
|
}
|
|
99033
99115
|
target.scheme = base2.scheme;
|
|
99034
99116
|
}
|
|
99035
|
-
target.fragment =
|
|
99117
|
+
target.fragment = relative8.fragment;
|
|
99036
99118
|
return target;
|
|
99037
99119
|
}
|
|
99038
99120
|
function equal(uriA, uriB, options) {
|
|
@@ -106912,7 +106994,7 @@ import {
|
|
|
106912
106994
|
statSync as statSync18,
|
|
106913
106995
|
writeFileSync as writeFileSync20
|
|
106914
106996
|
} from "fs";
|
|
106915
|
-
import { dirname as dirname27, join as join52, normalize as normalize4, relative as
|
|
106997
|
+
import { dirname as dirname27, join as join52, normalize as normalize4, relative as relative8, sep as sep9 } from "path";
|
|
106916
106998
|
function resolveSkillsNativeStorageConfig(env3 = process.env) {
|
|
106917
106999
|
assertNoRetiredModeEnvVars(env3, {
|
|
106918
107000
|
app: SKILLS_ENV_NAMESPACE,
|
|
@@ -106976,7 +107058,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
106976
107058
|
if (existsSync31(projectStateDir)) {
|
|
106977
107059
|
for (const filePath of walkFiles2(projectStateDir)) {
|
|
106978
107060
|
const bytes = readFileSync35(filePath);
|
|
106979
|
-
const relativePath = toPosix(
|
|
107061
|
+
const relativePath = toPosix(relative8(targetDir, filePath));
|
|
106980
107062
|
files.push({
|
|
106981
107063
|
path: relativePath,
|
|
106982
107064
|
sizeBytes: bytes.byteLength,
|
|
@@ -108179,7 +108261,7 @@ import {
|
|
|
108179
108261
|
symlinkSync,
|
|
108180
108262
|
writeFileSync as writeFileSync23
|
|
108181
108263
|
} from "fs";
|
|
108182
|
-
import { basename as
|
|
108264
|
+
import { basename as basename14, delimiter, dirname as dirname30, isAbsolute as isAbsolute24, join as join55, relative as relative9, resolve as resolve23, sep as sep10 } from "path";
|
|
108183
108265
|
function object9(value, code2) {
|
|
108184
108266
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
108185
108267
|
throw new Error(code2);
|
|
@@ -108189,7 +108271,7 @@ function hash5(bytes) {
|
|
|
108189
108271
|
return createHash27("sha256").update(bytes).digest("hex");
|
|
108190
108272
|
}
|
|
108191
108273
|
function isWithin(parent, child) {
|
|
108192
|
-
const rel =
|
|
108274
|
+
const rel = relative9(parent, child);
|
|
108193
108275
|
return rel === "" || !rel.startsWith(`..${sep10}`) && rel !== ".." && !isAbsolute24(rel);
|
|
108194
108276
|
}
|
|
108195
108277
|
function entryExists(path) {
|
|
@@ -108284,7 +108366,7 @@ function resolveRuntimeLayout(homeInput, pathInput) {
|
|
|
108284
108366
|
assertNoSymlinkAncestors(currentPackageRoot);
|
|
108285
108367
|
if (!isWithin(runtimeRoot, currentPackageRoot))
|
|
108286
108368
|
throw new Error("ACTIVE_RUNTIME_OUTSIDE_COPYFILE_ROOT");
|
|
108287
|
-
const relativePackage =
|
|
108369
|
+
const relativePackage = relative9(runtimeRoot, currentPackageRoot).split(sep10);
|
|
108288
108370
|
if (relativePackage.length !== 4 || relativePackage[1] !== "node_modules" || relativePackage[2] !== "@hasna" || relativePackage[3] !== "skills") {
|
|
108289
108371
|
throw new Error("ACTIVE_RUNTIME_LAYOUT_UNSUPPORTED");
|
|
108290
108372
|
}
|
|
@@ -108838,7 +108920,7 @@ function inspectAliasPackageChain(home, aliasPath, oldLinkTarget, oldTarget, bin
|
|
|
108838
108920
|
function validateAliasSource(home, name, actual) {
|
|
108839
108921
|
const packageRoot = dirname30(dirname30(actual));
|
|
108840
108922
|
const roots = [join55(home, ".hasna", "skills", "runtime"), join55(home, ".bun", "install"), join55(home, ".local", "lib", "node_modules")];
|
|
108841
|
-
if (
|
|
108923
|
+
if (basename14(packageRoot) !== "skills" || basename14(dirname30(packageRoot)) !== "@hasna" || !roots.some((root2) => isWithin(root2, packageRoot))) {
|
|
108842
108924
|
throw new Error("ALIAS_SOURCE_ROOT_UNSUPPORTED");
|
|
108843
108925
|
}
|
|
108844
108926
|
assertOwnedSafePath(packageRoot, home);
|
|
@@ -108916,8 +108998,8 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
108916
108998
|
for (const item of aliases) {
|
|
108917
108999
|
if (readlinkSync5(item.path) !== item.oldLinkTarget || realpathSync14(item.path) !== item.oldTarget)
|
|
108918
109000
|
throw new Error("ALIAS_CHANGED_BEFORE_SWITCH");
|
|
108919
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
108920
|
-
const source = validateAliasSource(home,
|
|
109001
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
|
|
109002
|
+
const source = validateAliasSource(home, basename14(item.path), item.oldTarget);
|
|
108921
109003
|
if (source.version !== item.oldVersion || source.binarySha256 !== item.oldBinarySha256)
|
|
108922
109004
|
throw new Error("ALIAS_SOURCE_DRIFT");
|
|
108923
109005
|
receipt.state = "switching";
|
|
@@ -108926,11 +109008,11 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
108926
109008
|
replaceLink(item.path, item.newTarget, item.backupPath, item.oldLinkTarget, item.oldTarget);
|
|
108927
109009
|
if (realpathSync14(item.path) !== item.newTarget || realpathSync14(item.backupPath) !== item.oldTarget)
|
|
108928
109010
|
throw new Error("ALIAS_SWITCH_READBACK_MISMATCH");
|
|
108929
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
109011
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
|
|
108930
109012
|
options.onAliasSwitched?.(item.path);
|
|
108931
109013
|
}
|
|
108932
109014
|
for (const item of aliases) {
|
|
108933
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
109015
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
|
|
108934
109016
|
if (readlinkSync5(item.backupPath) !== item.oldLinkTarget || realpathSync14(item.backupPath) !== item.oldTarget)
|
|
108935
109017
|
throw new Error("ALIAS_BACKUP_DRIFT");
|
|
108936
109018
|
}
|
|
@@ -108943,16 +109025,16 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
108943
109025
|
for (const item of [...aliases].reverse()) {
|
|
108944
109026
|
try {
|
|
108945
109027
|
if (!entryExists(item.backupPath)) {
|
|
108946
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
108947
|
-
const source2 = validateAliasSource(home,
|
|
109028
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
|
|
109029
|
+
const source2 = validateAliasSource(home, basename14(item.path), item.oldTarget);
|
|
108948
109030
|
if (!entryExists(item.path) || readlinkSync5(item.path) !== item.oldLinkTarget || realpathSync14(item.path) !== item.oldTarget || source2.version !== item.oldVersion || source2.binarySha256 !== item.oldBinarySha256)
|
|
108949
109031
|
failed = true;
|
|
108950
109032
|
continue;
|
|
108951
109033
|
}
|
|
108952
109034
|
if (readlinkSync5(item.backupPath) !== item.oldLinkTarget || realpathSync14(item.backupPath) !== item.oldTarget)
|
|
108953
109035
|
throw new Error("ALIAS_BACKUP_DRIFT");
|
|
108954
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
108955
|
-
const source = validateAliasSource(home,
|
|
109036
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
|
|
109037
|
+
const source = validateAliasSource(home, basename14(item.path), item.oldTarget);
|
|
108956
109038
|
if (source.version !== item.oldVersion || source.binarySha256 !== item.oldBinarySha256)
|
|
108957
109039
|
throw new Error("ALIAS_SOURCE_DRIFT");
|
|
108958
109040
|
if (realpathSync14(item.path) === item.oldTarget && readlinkSync5(item.path) === item.oldLinkTarget)
|
|
@@ -109005,7 +109087,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
|
|
|
109005
109087
|
throw new Error("ALIAS_RECEIPT_BINDING_INVALID");
|
|
109006
109088
|
const seen = new Set;
|
|
109007
109089
|
for (const item of receipt.aliases) {
|
|
109008
|
-
const name =
|
|
109090
|
+
const name = basename14(item.path), target = layout.bin[name];
|
|
109009
109091
|
if (!target || seen.has(item.path) || !aliasDirs(home).includes(dirname30(item.path)) || item.newTarget !== join55(layout.currentPackageRoot, target) || item.backupPath !== `${item.path}.skills-alias-prev-${receiptId}` || item.chain !== undefined && (!item.chain || typeof item.chain !== "object" || typeof item.chain.packageLinkPath !== "string" || typeof item.chain.packageLinkTarget !== "string")) {
|
|
109010
109092
|
throw new Error("ALIAS_RECEIPT_LAUNCHER_INVALID");
|
|
109011
109093
|
}
|
|
@@ -109054,7 +109136,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
|
|
|
109054
109136
|
restored++;
|
|
109055
109137
|
}
|
|
109056
109138
|
for (const item of receipt.aliases) {
|
|
109057
|
-
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[
|
|
109139
|
+
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename14(item.path)], item.chain, true);
|
|
109058
109140
|
}
|
|
109059
109141
|
receipt.state = "rolled-back";
|
|
109060
109142
|
persistAliasReceipt(receiptPath, receipt);
|
|
@@ -109087,7 +109169,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
|
|
|
109087
109169
|
const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
|
|
109088
109170
|
const stagePath = join55(layout.runtimeRoot, `.stage-${version2}-${id2}`);
|
|
109089
109171
|
const finalPath = join55(layout.runtimeRoot, `${version2}-copyfile`);
|
|
109090
|
-
const launchers = layout.launchers.map((item) => ({ ...item, newTarget: join55(finalPath, "node_modules", "@hasna", "skills", layout.bin[
|
|
109172
|
+
const launchers = layout.launchers.map((item) => ({ ...item, newTarget: join55(finalPath, "node_modules", "@hasna", "skills", layout.bin[basename14(item.path)]) }));
|
|
109091
109173
|
let switched = [];
|
|
109092
109174
|
let moved = false;
|
|
109093
109175
|
try {
|
|
@@ -109270,7 +109352,7 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
|
|
|
109270
109352
|
const switched = [];
|
|
109271
109353
|
const seen = new Set;
|
|
109272
109354
|
for (const item of receipt.launchers) {
|
|
109273
|
-
const bin = oldBins[
|
|
109355
|
+
const bin = oldBins[basename14(item.path)];
|
|
109274
109356
|
if (!bin || !isAbsolute24(item.path) || seen.has(item.path) || item.oldTarget !== join55(receipt.currentPackageRoot, bin) || item.newTarget !== join55(receipt.targetPackageRoot, bin) || !/^.+\.skills-prev-[0-9a-f-]{36}$/.test(item.backupPath) || !item.backupPath.startsWith(`${item.path}.skills-prev-`) || typeof item.oldLinkTarget !== "string" || resolve23(dirname30(item.path), item.oldLinkTarget) !== item.oldTarget)
|
|
109275
109357
|
throw new Error("RECEIPT_LAUNCHER_BINDING_INVALID");
|
|
109276
109358
|
assertNoSymlinkAncestors(dirname30(item.path));
|
|
@@ -109340,7 +109422,7 @@ __export(exports_runtime, {
|
|
|
109340
109422
|
});
|
|
109341
109423
|
import { createHash as createHash28, randomUUID as randomUUID10 } from "crypto";
|
|
109342
109424
|
import { lstatSync as lstatSync29, mkdirSync as mkdirSync25, readFileSync as readFileSync38, realpathSync as realpathSync15, writeFileSync as writeFileSync24 } from "fs";
|
|
109343
|
-
import { basename as
|
|
109425
|
+
import { basename as basename15, isAbsolute as isAbsolute25, join as join56 } from "path";
|
|
109344
109426
|
import { createInterface } from "readline";
|
|
109345
109427
|
function registerRuntime(parent) {
|
|
109346
109428
|
parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill; use -- to end Skills options").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--target <target>", "Execution target: local or cloud").option("--secret-bindings <path>", "Reviewed, exact-selection local execution vault bindings (JSON file)").option("--secret-bindings-template", "Print a scoped bindings template without resolving secrets or running the skill", false).option("--input <json>", "Structured cloud execution input").option("--skill-version <version>", "Exact selected skill version").option("--selection-profile <id>", "Selected Skills profile").option("--session <id>", "Pinned Skills session").option("--cached", "Use the explicit verified selected cache", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options, command) => {
|
|
@@ -109853,7 +109935,7 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
|
|
|
109853
109935
|
const info = lstatSync29(path);
|
|
109854
109936
|
if (!info.isFile() || info.size > 20 * 1024 * 1024)
|
|
109855
109937
|
throw new Error("Input must be a regular file no larger than 20 MiB");
|
|
109856
|
-
return { name:
|
|
109938
|
+
return { name: basename15(path), bytes: new Uint8Array(readFileSync38(path)) };
|
|
109857
109939
|
});
|
|
109858
109940
|
describeRemoteFiles(inputFiles);
|
|
109859
109941
|
client2 = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
|
|
@@ -111030,7 +111112,7 @@ import {
|
|
|
111030
111112
|
statSync as statSync20,
|
|
111031
111113
|
writeFileSync as writeFileSync25
|
|
111032
111114
|
} from "fs";
|
|
111033
|
-
import { dirname as dirname32, isAbsolute as isAbsolute26, relative as
|
|
111115
|
+
import { dirname as dirname32, isAbsolute as isAbsolute26, relative as relative10, resolve as resolve24, sep as sep12 } from "path";
|
|
111034
111116
|
function validateStationId(stationId) {
|
|
111035
111117
|
if (!/^[a-z0-9-]+$/.test(stationId)) {
|
|
111036
111118
|
throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
|
|
@@ -111135,7 +111217,7 @@ function writeStationSnapshot(options) {
|
|
|
111135
111217
|
const untouched = [];
|
|
111136
111218
|
for (const plan of plans) {
|
|
111137
111219
|
const destination = resolve24(repoRoot, plan.destination);
|
|
111138
|
-
const destinationRelative =
|
|
111220
|
+
const destinationRelative = relative10(repoRoot, destination);
|
|
111139
111221
|
if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep12) || isAbsolute26(destinationRelative)) {
|
|
111140
111222
|
throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
|
|
111141
111223
|
}
|
|
@@ -112194,7 +112276,9 @@ var exports_agent_integration = {};
|
|
|
112194
112276
|
__export(exports_agent_integration, {
|
|
112195
112277
|
registerAgentIntegration: () => registerAgentIntegration
|
|
112196
112278
|
});
|
|
112197
|
-
import { readFileSync as readFileSync41 } from "fs";
|
|
112279
|
+
import { existsSync as existsSync35, lstatSync as lstatSync32, readFileSync as readFileSync41, writeFileSync as writeFileSync26 } from "fs";
|
|
112280
|
+
import { createHash as createHash31 } from "crypto";
|
|
112281
|
+
import { homedir as homedir13 } from "os";
|
|
112198
112282
|
import { isAbsolute as isAbsolute29 } from "path";
|
|
112199
112283
|
function pinnedHookProfile(input3, configuredProfile) {
|
|
112200
112284
|
try {
|
|
@@ -112261,6 +112345,45 @@ function agents(value) {
|
|
|
112261
112345
|
}
|
|
112262
112346
|
function registerAgentIntegration(parent) {
|
|
112263
112347
|
const hook = parent.command("hook").description("Load selected Skills context through agent lifecycle hooks");
|
|
112348
|
+
hook.command("native-catalog").requiredOption("--cwd <path>", "Absolute project directory observed by native Codex skills/list").requiredOption("--output <file>", "New private file for the projected native catalog").option("--codex-command <path>", "Installed Codex executable used by the native client", "codex").option("--json", "Output bounded capture metadata as JSON", false).description("Capture a reviewed Codex native skill catalog for exact hook enrollment").action(async (options) => {
|
|
112349
|
+
try {
|
|
112350
|
+
if (!isAbsolute29(options.cwd) || !isAbsolute29(options.output))
|
|
112351
|
+
throw new Error("CODEX_NATIVE_SKILL_CATALOG_ABSOLUTE_PATH_REQUIRED");
|
|
112352
|
+
if (existsSync35(options.output))
|
|
112353
|
+
throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
|
|
112354
|
+
const catalog = await captureCodexNativeSkillCatalog({
|
|
112355
|
+
command: options.codexCommand,
|
|
112356
|
+
home: homedir13(),
|
|
112357
|
+
...process.env.CODEX_HOME === undefined ? {} : { codexHome: process.env.CODEX_HOME },
|
|
112358
|
+
cwd: options.cwd
|
|
112359
|
+
});
|
|
112360
|
+
const bytes = JSON.stringify(catalog, null, 2) + `
|
|
112361
|
+
`;
|
|
112362
|
+
try {
|
|
112363
|
+
writeFileSync26(options.output, bytes, { flag: "wx", mode: 384 });
|
|
112364
|
+
} catch (error61) {
|
|
112365
|
+
if (error61 && typeof error61 === "object" && "code" in error61 && error61.code === "EEXIST")
|
|
112366
|
+
throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
|
|
112367
|
+
throw error61;
|
|
112368
|
+
}
|
|
112369
|
+
const written = lstatSync32(options.output);
|
|
112370
|
+
if (!written.isFile() || written.isSymbolicLink() || (written.mode & 63) !== 0 || readFileSync41(options.output, "utf8") !== bytes)
|
|
112371
|
+
throw new Error("CODEX_NATIVE_SKILL_CATALOG_READBACK_FAILED");
|
|
112372
|
+
const receipt = {
|
|
112373
|
+
version: catalog.version,
|
|
112374
|
+
cwd: catalog.cwd,
|
|
112375
|
+
skillCount: catalog.skills.length,
|
|
112376
|
+
output: options.output,
|
|
112377
|
+
bytes: Buffer.byteLength(bytes),
|
|
112378
|
+
sha256: createHash31("sha256").update(bytes).digest("hex")
|
|
112379
|
+
};
|
|
112380
|
+
await writeCliOutput(options.json ? JSON.stringify(receipt) : `Captured ${receipt.skillCount} native Codex skill(s) in ${receipt.output}.`);
|
|
112381
|
+
} catch (error61) {
|
|
112382
|
+
const message = error61 instanceof Error && /^[A-Z][A-Z0-9_]{2,120}$/.test(error61.message) ? error61.message : "CODEX_NATIVE_SKILL_CATALOG_CAPTURE_FAILED";
|
|
112383
|
+
console.error(message);
|
|
112384
|
+
process.exitCode = 1;
|
|
112385
|
+
}
|
|
112386
|
+
});
|
|
112264
112387
|
hook.command("witness").requiredOption("--kind <kind>", "claude-settings-v3, claude-settings-v2, codex-settings-v1 or claude-marketplace-registry-v2").requiredOption("--path <path>", "Canonical absolute path to the reviewed settings or registry file").option("--json", "Output the discovery witness as JSON", false).description("Capture an explicit versioned review witness without installing it").action(async (options) => {
|
|
112265
112388
|
const capture2 = options.kind === "codex-settings-v1" ? captureCodexSettings : options.kind === "claude-settings-v3" ? captureClaudeSettingsV3 : options.kind === "claude-settings-v2" ? captureClaudeSettingsV2 : options.kind === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : null;
|
|
112266
112389
|
if (!capture2)
|
|
@@ -112283,7 +112406,7 @@ function registerAgentIntegration(parent) {
|
|
|
112283
112406
|
hook.command("agents").option("--json", "Output the adapter capability inventory", false).description("Show maintained native adapters and explicit coverage limits").action(async () => {
|
|
112284
112407
|
await writeCliOutput(JSON.stringify({ agents: INTEGRATION_AGENTS.map((agent) => ({ agent, bridge: true, ...AGENT_ADAPTERS[agent] })), inventoryOnly: ["codewith", "windsurf", "pi", "amp", "cline", "roo", "copilot"], limitations: ["Cursor prompt hooks gate submission; selected context is injected at session start only.", "Native discovery checks cover known home roots and current project ancestors. External plugin hook injection and arbitrary added directories require separate review.", "Hermes injects selected prompt context, but native pre_llm_call fails open. Exact native hook trust, bundled reseeding opt-out, native payload retirement and a supervised pre-tool guard are required. Child failures block explicitly; native host/supervisor death is not a universal fail-closed guarantee.", "Restart agents and use their normal hook trust controls after installation."] }, null, 2));
|
|
112285
112408
|
});
|
|
112286
|
-
hook.command("install").option("--agent <agent>", `Agent to configure: ${INTEGRATION_AGENTS.join(", ")}, all`, "all").option("--command <path>", "Skills executable used by the hook (preserves existing binding; new agents use skills)").option("--selection-profile <id>", "Selection profile (preserves existing binding; new agents use default)").option("--include-vendor", "Retained for compatibility; vendor system skills are always inventoried and disabled", false).option("--discovery-inputs <file>", "Advanced reviewed active plugin roots and source hashes for unsupported registrations").option("--codex-native-catalog <file>", "Reviewed
|
|
112409
|
+
hook.command("install").option("--agent <agent>", `Agent to configure: ${INTEGRATION_AGENTS.join(", ")}, all`, "all").option("--command <path>", "Skills executable used by the hook (preserves existing binding; new agents use skills)").option("--selection-profile <id>", "Selection profile (preserves existing binding; new agents use default)").option("--include-vendor", "Retained for compatibility; vendor system skills are always inventoried and disabled", false).option("--discovery-inputs <file>", "Advanced reviewed active plugin roots and source hashes for unsupported registrations").option("--codex-native-catalog <file>", "Reviewed Codex 0.159.2 skill and installed-plugin receipt for exact qualified-name disables").option("--reviewed-cache-alias <path>", "Exact skill-containing vendor cache alias reviewed for this hook plan").option("--allow-root-aliases", "Allow home .claude/.codex aliases to existing directories within this home", false).option("--apply", "Apply the plan, preserving prior configuration in private backups", false).option("--json", "Output a receipt as JSON", false).description("Plan or install one Skills CLI bridge plus native prompt hooks").action(async (options) => {
|
|
112287
112410
|
try {
|
|
112288
112411
|
const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync41(options.discoveryInputs, "utf8")) : undefined;
|
|
112289
112412
|
const plan = planAgentIntegration({ projectDir: process.cwd(), agents: agents(options.agent), command: options.command, profileId: options.selectionProfile, includeVendor: options.includeVendor, discoveryInputs, allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, codexNativeCatalog: options.codexNativeCatalog ? JSON.parse(readFileSync41(options.codexNativeCatalog, "utf8")) : undefined });
|
|
@@ -112492,6 +112615,7 @@ var init_agent_integration2 = __esm(() => {
|
|
|
112492
112615
|
init_claude_settings_witness();
|
|
112493
112616
|
init_codex_settings_witness();
|
|
112494
112617
|
init_claude_marketplace_registry();
|
|
112618
|
+
init_codex_native_skill_catalog();
|
|
112495
112619
|
RECOVERABLE_CONTEXT_CACHE_ERRORS = new Set(["CACHED_PROFILE_EXPIRED", "CACHED_PROFILE_MISSING", "CACHED_BUNDLE_MISSING"]);
|
|
112496
112620
|
});
|
|
112497
112621
|
|
|
@@ -112630,7 +112754,7 @@ var exports_profiles = {};
|
|
|
112630
112754
|
__export(exports_profiles, {
|
|
112631
112755
|
registerProfiles: () => registerProfiles
|
|
112632
112756
|
});
|
|
112633
|
-
import { closeSync as closeSync21, constants as constants20, fstatSync as fstatSync21, openSync as openSync21, readSync as readSync17, writeFileSync as
|
|
112757
|
+
import { closeSync as closeSync21, constants as constants20, fstatSync as fstatSync21, openSync as openSync21, readSync as readSync17, writeFileSync as writeFileSync27 } from "fs";
|
|
112634
112758
|
function readProfileInput(path) {
|
|
112635
112759
|
const fd = openSync21(path, constants20.O_RDONLY | constants20.O_NONBLOCK);
|
|
112636
112760
|
try {
|
|
@@ -112658,7 +112782,7 @@ function registerProfiles(parent) {
|
|
|
112658
112782
|
try {
|
|
112659
112783
|
const profile = await readSkillProfile(id3), text4 = JSON.stringify(profile, null, 2);
|
|
112660
112784
|
if (options.save)
|
|
112661
|
-
|
|
112785
|
+
writeFileSync27(options.save, JSON.stringify(profile), { mode: 384, flag: "wx" });
|
|
112662
112786
|
await writeCliOutput(options.json ? text4 : `${profile.id} at ${profile.revision}: ${profile.selections.map((skill) => `${skill.slug}@${skill.version}`).join(", ")}`);
|
|
112663
112787
|
} catch (error61) {
|
|
112664
112788
|
console.error(error61.message);
|
|
@@ -112705,7 +112829,7 @@ import {
|
|
|
112705
112829
|
fstatSync as fstatSync23,
|
|
112706
112830
|
openSync as openSync23,
|
|
112707
112831
|
readSync as readSync18,
|
|
112708
|
-
writeFileSync as
|
|
112832
|
+
writeFileSync as writeFileSync28
|
|
112709
112833
|
} from "fs";
|
|
112710
112834
|
function readInput(path) {
|
|
112711
112835
|
const fd = openSync23(path, constants21.O_RDONLY | constants21.O_NONBLOCK);
|
|
@@ -112738,7 +112862,7 @@ function registerGrants(parent) {
|
|
|
112738
112862
|
try {
|
|
112739
112863
|
const policy = await readExecutionGrantPolicy(profile, options.revision);
|
|
112740
112864
|
if (options.save)
|
|
112741
|
-
|
|
112865
|
+
writeFileSync28(options.save, JSON.stringify(policy, null, 2), {
|
|
112742
112866
|
mode: 384,
|
|
112743
112867
|
flag: "wx"
|
|
112744
112868
|
});
|
|
@@ -112765,14 +112889,14 @@ var init_grants = __esm(() => {
|
|
|
112765
112889
|
});
|
|
112766
112890
|
|
|
112767
112891
|
// src/lib/station-hydrate.ts
|
|
112768
|
-
import { createHash as
|
|
112892
|
+
import { createHash as createHash32 } from "crypto";
|
|
112769
112893
|
import {
|
|
112770
112894
|
copyFileSync as copyFileSync3,
|
|
112771
112895
|
mkdirSync as mkdirSync28,
|
|
112772
112896
|
readdirSync as readdirSync24,
|
|
112773
112897
|
readFileSync as readFileSync42,
|
|
112774
112898
|
statSync as statSync22,
|
|
112775
|
-
writeFileSync as
|
|
112899
|
+
writeFileSync as writeFileSync29
|
|
112776
112900
|
} from "fs";
|
|
112777
112901
|
import { dirname as dirname35, join as join61, resolve as resolve26, sep as sep13 } from "path";
|
|
112778
112902
|
function fail5(code2, message, detail = []) {
|
|
@@ -112968,7 +113092,7 @@ function skillSha256(skill) {
|
|
|
112968
113092
|
return sha256File(skill.files[0].winner.fullPath);
|
|
112969
113093
|
}
|
|
112970
113094
|
const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
|
|
112971
|
-
return
|
|
113095
|
+
return createHash32("sha256").update(joined.sort().join(`
|
|
112972
113096
|
`)).digest("hex");
|
|
112973
113097
|
}
|
|
112974
113098
|
function writeStationHydration(options) {
|
|
@@ -113050,7 +113174,7 @@ function writeStationHydration(options) {
|
|
|
113050
113174
|
};
|
|
113051
113175
|
const hydrationManifestPath = join61(dirname35(cacheRoot), `hydration-${options.stationId}.json`);
|
|
113052
113176
|
mkdirSync28(dirname35(hydrationManifestPath), { recursive: true });
|
|
113053
|
-
|
|
113177
|
+
writeFileSync29(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
|
|
113054
113178
|
`);
|
|
113055
113179
|
return {
|
|
113056
113180
|
...base3,
|
|
@@ -113125,10 +113249,10 @@ var init_hydrate = __esm(() => {
|
|
|
113125
113249
|
});
|
|
113126
113250
|
|
|
113127
113251
|
// src/lib/prepare-skill.ts
|
|
113128
|
-
import { createHash as
|
|
113129
|
-
import { chmodSync as chmodSync5, existsSync as
|
|
113252
|
+
import { createHash as createHash33, randomUUID as randomUUID12 } from "crypto";
|
|
113253
|
+
import { chmodSync as chmodSync5, existsSync as existsSync36, lstatSync as lstatSync33, mkdirSync as mkdirSync29, mkdtempSync as mkdtempSync6, readFileSync as readFileSync43, readdirSync as readdirSync25, renameSync as renameSync14, rmSync as rmSync9, writeFileSync as writeFileSync30 } from "fs";
|
|
113130
113254
|
import { tmpdir as tmpdir2 } from "os";
|
|
113131
|
-
import { dirname as dirname36, isAbsolute as isAbsolute30, join as join62, relative as
|
|
113255
|
+
import { dirname as dirname36, isAbsolute as isAbsolute30, join as join62, relative as relative11, resolve as resolve27, sep as sep14 } from "path";
|
|
113132
113256
|
function prepareSkill(name, options) {
|
|
113133
113257
|
const normalized = normalizePortableSkillName(name);
|
|
113134
113258
|
if (!new RegExp(SEMVER_PATTERN).test(options.version))
|
|
@@ -113175,10 +113299,10 @@ function prepareSkill(name, options) {
|
|
|
113175
113299
|
for (const file2 of before2.files) {
|
|
113176
113300
|
const destination = join62(staging, file2.path);
|
|
113177
113301
|
mkdirSync29(dirname36(destination), { recursive: true });
|
|
113178
|
-
|
|
113302
|
+
writeFileSync30(destination, file2.bytes, { mode: file2.mode });
|
|
113179
113303
|
}
|
|
113180
113304
|
const stagedManifest = join62(staging, "skill.json");
|
|
113181
|
-
|
|
113305
|
+
writeFileSync30(stagedManifest, `${JSON.stringify(candidate2, null, 2)}
|
|
113182
113306
|
`);
|
|
113183
113307
|
const contentHash = computeContentHash(staging);
|
|
113184
113308
|
const changed3 = options.version !== previousVersion || kind !== manifest.kind || contentHash !== provenance?.content_hash;
|
|
@@ -113188,7 +113312,7 @@ function prepareSkill(name, options) {
|
|
|
113188
113312
|
candidate2.provenance.content_hash = contentHash;
|
|
113189
113313
|
const candidateBytes = `${JSON.stringify(candidate2, null, 2)}
|
|
113190
113314
|
`;
|
|
113191
|
-
|
|
113315
|
+
writeFileSync30(stagedManifest, candidateBytes);
|
|
113192
113316
|
validateRawCandidate(candidate2);
|
|
113193
113317
|
validateRuntimeEntrypoint(candidate2, staging);
|
|
113194
113318
|
const validation = validatePortableSkillDirectory(normalized, staging);
|
|
@@ -113202,7 +113326,7 @@ ${validation.issues.map((issue2) => `${issue2.code}: ${issue2.message}`).join(`
|
|
|
113202
113326
|
if (changed3 && !options.dryRun) {
|
|
113203
113327
|
const temporary = join62(path, `.skill-prepare-${randomUUID12()}.tmp`);
|
|
113204
113328
|
try {
|
|
113205
|
-
|
|
113329
|
+
writeFileSync30(temporary, candidateBytes, { flag: "wx", mode: manifestFile.mode });
|
|
113206
113330
|
chmodSync5(temporary, manifestFile.mode);
|
|
113207
113331
|
renameSync14(temporary, join62(path, "skill.json"));
|
|
113208
113332
|
} finally {
|
|
@@ -113234,8 +113358,8 @@ function validateRuntimeEntrypoint(candidate2, root2) {
|
|
|
113234
113358
|
const entry = candidate2.runtime.entrypoint;
|
|
113235
113359
|
if (typeof entry !== "string")
|
|
113236
113360
|
return;
|
|
113237
|
-
const target = resolve27(root2, entry), rel =
|
|
113238
|
-
if (isAbsolute30(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep14}`) || isAbsolute30(rel) || !
|
|
113361
|
+
const target = resolve27(root2, entry), rel = relative11(root2, target);
|
|
113362
|
+
if (isAbsolute30(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep14}`) || isAbsolute30(rel) || !existsSync36(target) || !lstatSync33(target).isFile()) {
|
|
113239
113363
|
throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
|
|
113240
113364
|
}
|
|
113241
113365
|
}
|
|
@@ -113320,20 +113444,20 @@ function compareVersions(left, right) {
|
|
|
113320
113444
|
return 0;
|
|
113321
113445
|
}
|
|
113322
113446
|
function snapshot2(root2) {
|
|
113323
|
-
const rootStat =
|
|
113447
|
+
const rootStat = lstatSync33(root2);
|
|
113324
113448
|
if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
|
|
113325
113449
|
throw new Error("Skill root must be a real directory, not a symlink.");
|
|
113326
113450
|
const files = [], directories = [];
|
|
113327
|
-
const hash6 =
|
|
113451
|
+
const hash6 = createHash33("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
|
|
113328
113452
|
let count = 0, bytes = 0;
|
|
113329
|
-
const walk2 = (
|
|
113330
|
-
for (const name of readdirSync25(join62(root2,
|
|
113331
|
-
if (IGNORED.has(name.toLowerCase()) || !
|
|
113453
|
+
const walk2 = (relative12) => {
|
|
113454
|
+
for (const name of readdirSync25(join62(root2, relative12)).sort()) {
|
|
113455
|
+
if (IGNORED.has(name.toLowerCase()) || !relative12 && ROOT_IGNORED.has(name.toLowerCase()))
|
|
113332
113456
|
continue;
|
|
113333
|
-
const path =
|
|
113457
|
+
const path = relative12 ? `${relative12}/${name}` : name;
|
|
113334
113458
|
if (++count > 20000)
|
|
113335
113459
|
throw new Error("Skill exceeds the preparation entry limit (20000).");
|
|
113336
|
-
const absolute = join62(root2, path), stat3 =
|
|
113460
|
+
const absolute = join62(root2, path), stat3 = lstatSync33(absolute);
|
|
113337
113461
|
if (stat3.isSymbolicLink())
|
|
113338
113462
|
throw new Error(`Skill contains a symlink: ${path}. No files were changed.`);
|
|
113339
113463
|
if (stat3.isDirectory() && name === "node_modules")
|
|
@@ -113748,8 +113872,8 @@ var init_schedule = __esm(() => {
|
|
|
113748
113872
|
});
|
|
113749
113873
|
|
|
113750
113874
|
// src/lib/registry-sync.ts
|
|
113751
|
-
import { mkdirSync as mkdirSync30, writeFileSync as
|
|
113752
|
-
import { dirname as dirname37, relative as
|
|
113875
|
+
import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync31 } from "fs";
|
|
113876
|
+
import { dirname as dirname37, relative as relative12 } from "path";
|
|
113753
113877
|
function createRegistrySyncArtifact(options = {}) {
|
|
113754
113878
|
const profile = options.profile ?? "all";
|
|
113755
113879
|
const includeDocs = options.includeDocs ?? true;
|
|
@@ -113761,7 +113885,7 @@ function createRegistrySyncArtifact(options = {}) {
|
|
|
113761
113885
|
const registry2 = [...loadRegistryProfile(profile)].sort((a, b) => a.name.localeCompare(b.name));
|
|
113762
113886
|
const skills = registry2.map((skill) => {
|
|
113763
113887
|
const skillPath = getSkillPath(skill.name);
|
|
113764
|
-
const directory2 =
|
|
113888
|
+
const directory2 = relative12(process.cwd(), skillPath) || skillPath;
|
|
113765
113889
|
const validation = includeValidation ? validateSkillDirectory(skill.name, skillPath, skill) : undefined;
|
|
113766
113890
|
const docs = includeDocs ? buildDocs(skill.name) : undefined;
|
|
113767
113891
|
return {
|
|
@@ -113807,7 +113931,7 @@ function createRegistrySyncArtifact(options = {}) {
|
|
|
113807
113931
|
}
|
|
113808
113932
|
function writeRegistrySyncArtifact(path, artifact) {
|
|
113809
113933
|
mkdirSync30(dirname37(path), { recursive: true });
|
|
113810
|
-
|
|
113934
|
+
writeFileSync31(path, `${JSON.stringify(artifact, null, 2)}
|
|
113811
113935
|
`);
|
|
113812
113936
|
}
|
|
113813
113937
|
function buildDocs(name) {
|
|
@@ -113826,8 +113950,8 @@ var init_registry_sync = __esm(() => {
|
|
|
113826
113950
|
});
|
|
113827
113951
|
|
|
113828
113952
|
// src/lib/review-export.ts
|
|
113829
|
-
import { constants as constants22, closeSync as closeSync25, existsSync as
|
|
113830
|
-
import { basename as
|
|
113953
|
+
import { constants as constants22, closeSync as closeSync25, existsSync as existsSync37, fstatSync as fstatSync25, fsyncSync as fsyncSync7, lstatSync as lstatSync34, openSync as openSync25, realpathSync as realpathSync18, statSync as statSync23, writeFileSync as writeFileSync32 } from "fs";
|
|
113954
|
+
import { basename as basename16, dirname as dirname38, isAbsolute as isAbsolute31, join as join63, parse as parse12, resolve as resolve28, sep as sep15 } from "path";
|
|
113831
113955
|
function exactVersion(spec) {
|
|
113832
113956
|
const at2 = spec.indexOf("@");
|
|
113833
113957
|
const slug2 = spec.slice(0, at2);
|
|
@@ -113838,11 +113962,11 @@ function exactVersion(spec) {
|
|
|
113838
113962
|
return { slug: slug2, version: version2 };
|
|
113839
113963
|
}
|
|
113840
113964
|
function assertPrivateDestination(output2) {
|
|
113841
|
-
if (!isAbsolute31(output2) || resolve28(output2) !== output2 || !
|
|
113965
|
+
if (!isAbsolute31(output2) || resolve28(output2) !== output2 || !basename16(output2).endsWith(".tar.gz")) {
|
|
113842
113966
|
throw new Error("Review output must be an absolute, normalized .tar.gz path.");
|
|
113843
113967
|
}
|
|
113844
113968
|
const parent = dirname38(output2);
|
|
113845
|
-
if (realpathSync18(parent) !== parent ||
|
|
113969
|
+
if (realpathSync18(parent) !== parent || lstatSync34(parent).isSymbolicLink()) {
|
|
113846
113970
|
throw new Error("Review output parent must be a real directory, not a symlink.");
|
|
113847
113971
|
}
|
|
113848
113972
|
const parentStat = statSync23(parent);
|
|
@@ -113854,7 +113978,7 @@ function assertPrivateDestination(output2) {
|
|
|
113854
113978
|
throw new Error("Review output cannot be placed in agent-native discovery or Skills installation paths.");
|
|
113855
113979
|
}
|
|
113856
113980
|
for (let current = parent;; current = dirname38(current)) {
|
|
113857
|
-
if (
|
|
113981
|
+
if (existsSync37(join63(current, ".git"))) {
|
|
113858
113982
|
throw new Error("Review output cannot be placed inside a Git worktree.");
|
|
113859
113983
|
}
|
|
113860
113984
|
if (current === parse12(current).root)
|
|
@@ -113865,7 +113989,7 @@ function assertPrivateDestination(output2) {
|
|
|
113865
113989
|
async function exportSkillVersionForReview(spec, output2, client2) {
|
|
113866
113990
|
const { slug: slug2, version: version2 } = exactVersion(spec);
|
|
113867
113991
|
const target = assertPrivateDestination(output2);
|
|
113868
|
-
if (
|
|
113992
|
+
if (existsSync37(target))
|
|
113869
113993
|
throw new Error("Review output already exists; choose a new filename.");
|
|
113870
113994
|
const metadata = await client2.getSkillVersion(slug2, version2);
|
|
113871
113995
|
if (!metadata)
|
|
@@ -113892,7 +114016,7 @@ async function exportSkillVersionForReview(spec, output2, client2) {
|
|
|
113892
114016
|
}
|
|
113893
114017
|
const fd = openSync25(target, constants22.O_WRONLY | constants22.O_CREAT | constants22.O_EXCL | constants22.O_NOFOLLOW, 384);
|
|
113894
114018
|
try {
|
|
113895
|
-
|
|
114019
|
+
writeFileSync32(fd, bytes);
|
|
113896
114020
|
fsyncSync7(fd);
|
|
113897
114021
|
if (fstatSync25(fd).size !== bytes.byteLength)
|
|
113898
114022
|
throw new Error("Incomplete review output write.");
|
|
@@ -114139,7 +114263,7 @@ __export(exports_publish, {
|
|
|
114139
114263
|
PushSkillError: () => PushSkillError
|
|
114140
114264
|
});
|
|
114141
114265
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
114142
|
-
import { existsSync as
|
|
114266
|
+
import { existsSync as existsSync38, readFileSync as readFileSync44 } from "fs";
|
|
114143
114267
|
import { hostname as hostname5 } from "os";
|
|
114144
114268
|
import { join as join64 } from "path";
|
|
114145
114269
|
function registerPublish(parent) {
|
|
@@ -114194,7 +114318,7 @@ async function pushSkill(name, options = {}) {
|
|
|
114194
114318
|
await verifyPackedCanonicalHash(skill.name, packed);
|
|
114195
114319
|
const versionManifest = buildVersionManifest(skill.path, packed);
|
|
114196
114320
|
const skillMdPath = join64(skill.path, "SKILL.md");
|
|
114197
|
-
const skillMd =
|
|
114321
|
+
const skillMd = existsSync38(skillMdPath) ? readFileSync44(skillMdPath, "utf-8") : undefined;
|
|
114198
114322
|
const base3 = {
|
|
114199
114323
|
slug: skill.name,
|
|
114200
114324
|
path: skill.path,
|
|
@@ -115913,7 +116037,7 @@ var init_storage2 = __esm(() => {
|
|
|
115913
116037
|
});
|
|
115914
116038
|
|
|
115915
116039
|
// src/lib/registry-reconcile.ts
|
|
115916
|
-
import { existsSync as
|
|
116040
|
+
import { existsSync as existsSync39, readFileSync as readFileSync45, statSync as statSync24, writeFileSync as writeFileSync33 } from "fs";
|
|
115917
116041
|
import { join as join65 } from "path";
|
|
115918
116042
|
function isDirectory2(path) {
|
|
115919
116043
|
try {
|
|
@@ -115930,7 +116054,7 @@ function migrationNeeded(options) {
|
|
|
115930
116054
|
}
|
|
115931
116055
|
function readBaseline(skillDir) {
|
|
115932
116056
|
const markerPath = join65(skillDir, PULL_MARKER_FILE);
|
|
115933
|
-
if (!
|
|
116057
|
+
if (!existsSync39(markerPath))
|
|
115934
116058
|
return;
|
|
115935
116059
|
try {
|
|
115936
116060
|
const marker = JSON.parse(readFileSync45(markerPath, "utf-8"));
|
|
@@ -115946,7 +116070,7 @@ function readBaseline(skillDir) {
|
|
|
115946
116070
|
}
|
|
115947
116071
|
function readCursor(root2) {
|
|
115948
116072
|
const path = join65(root2, SYNC_CURSOR_FILE);
|
|
115949
|
-
if (!
|
|
116073
|
+
if (!existsSync39(path))
|
|
115950
116074
|
return { runCount: 0 };
|
|
115951
116075
|
try {
|
|
115952
116076
|
const cursor2 = JSON.parse(readFileSync45(path, "utf-8"));
|
|
@@ -115977,7 +116101,7 @@ function remoteRowToSkill(record11) {
|
|
|
115977
116101
|
}
|
|
115978
116102
|
function recheckLocalSide(plannedLocal, localDir, ops = {
|
|
115979
116103
|
pack: (dir) => packSkillBundle(dir).sha256,
|
|
115980
|
-
exists:
|
|
116104
|
+
exists: existsSync39
|
|
115981
116105
|
}) {
|
|
115982
116106
|
let localNow;
|
|
115983
116107
|
try {
|
|
@@ -116228,7 +116352,7 @@ async function reconcileRegistry(options = {}) {
|
|
|
116228
116352
|
runCount: readCursor(root2).runCount + 1,
|
|
116229
116353
|
summary
|
|
116230
116354
|
};
|
|
116231
|
-
|
|
116355
|
+
writeFileSync33(join65(root2, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
|
|
116232
116356
|
`);
|
|
116233
116357
|
return {
|
|
116234
116358
|
corpusRoot: root2,
|