@hasna/skills 0.10.74 → 0.10.76
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 +18 -1
- package/bin/index.js +701 -341
- package/bin/mcp.js +142 -93
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/cli/stray-arguments.d.ts +29 -0
- package/dist/index.js +572 -243
- package/dist/lib/agent-codex-trust.d.ts +4 -0
- package/dist/lib/agent-integration.d.ts +3 -3
- package/dist/lib/agent-sync.d.ts +6 -4
- package/dist/lib/codex-corpus-write.d.ts +47 -6
- package/dist/lib/codex-hook-rpc.d.ts +3 -0
- package/dist/lib/home-adoption.d.ts +5 -5
- package/dist/lib/installer.d.ts +5 -3
- package/dist/lib/search.d.ts +18 -0
- package/dist/runtime-prerequisites.js +1 -1
- package/dist/sdk/index.js +630 -301
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6988,7 +6988,7 @@ var require_public_api = __commonJS((exports) => {
|
|
|
6988
6988
|
});
|
|
6989
6989
|
|
|
6990
6990
|
// src/lib/registry.ts
|
|
6991
|
-
import { existsSync as existsSync15, readFileSync as readFileSync27, readdirSync as
|
|
6991
|
+
import { existsSync as existsSync15, readFileSync as readFileSync27, readdirSync as readdirSync15 } from "fs";
|
|
6992
6992
|
import { join as join41 } from "path";
|
|
6993
6993
|
|
|
6994
6994
|
// src/lib/config.ts
|
|
@@ -7257,12 +7257,12 @@ function unsetConfig(key, scope = "project") {
|
|
|
7257
7257
|
// src/lib/portable-skills.ts
|
|
7258
7258
|
import {
|
|
7259
7259
|
existsSync as existsSync14,
|
|
7260
|
-
mkdirSync as
|
|
7261
|
-
mkdtempSync as
|
|
7262
|
-
readdirSync as
|
|
7260
|
+
mkdirSync as mkdirSync12,
|
|
7261
|
+
mkdtempSync as mkdtempSync3,
|
|
7262
|
+
readdirSync as readdirSync14,
|
|
7263
7263
|
realpathSync as realpathSync15,
|
|
7264
7264
|
renameSync as renameSync6,
|
|
7265
|
-
rmSync as
|
|
7265
|
+
rmSync as rmSync5,
|
|
7266
7266
|
statSync as statSync13,
|
|
7267
7267
|
writeFileSync as writeFileSync9
|
|
7268
7268
|
} from "fs";
|
|
@@ -9973,7 +9973,7 @@ function assertAgentPolicyCollections(policy) {
|
|
|
9973
9973
|
|
|
9974
9974
|
// src/lib/agent-discovery.ts
|
|
9975
9975
|
import { createHash as createHash30 } from "crypto";
|
|
9976
|
-
import { lstatSync as lstatSync32, readFileSync as readFileSync26, readdirSync as
|
|
9976
|
+
import { lstatSync as lstatSync32, readFileSync as readFileSync26, readdirSync as readdirSync13, realpathSync as realpathSync13 } from "fs";
|
|
9977
9977
|
import { basename as basename15, dirname as dirname26, isAbsolute as isAbsolute28, join as join38, relative as relative10, resolve as resolve27, sep as sep15 } from "path";
|
|
9978
9978
|
import { isDeepStrictEqual as isDeepStrictEqual9 } from "util";
|
|
9979
9979
|
|
|
@@ -13491,14 +13491,14 @@ function hashDiscoveryPathFile(path, budget2, changes) {
|
|
|
13491
13491
|
}
|
|
13492
13492
|
|
|
13493
13493
|
// src/lib/codex-vendor-refresh.ts
|
|
13494
|
-
import { lstatSync as lstatSync15, readdirSync as
|
|
13494
|
+
import { lstatSync as lstatSync15, readdirSync as readdirSync7, readFileSync as readFileSync12 } from "fs";
|
|
13495
13495
|
import { isAbsolute as isAbsolute16, join as join19, relative as relative6, resolve as resolve16, sep as sep9 } from "path";
|
|
13496
13496
|
import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
|
|
13497
13497
|
|
|
13498
13498
|
// src/lib/codex-plugin-skill-controls.ts
|
|
13499
13499
|
import { createHash as createHash18 } from "crypto";
|
|
13500
13500
|
import { basename as basename8, dirname as dirname15, join as join18, relative as relative5, resolve as resolve15, sep as sep8 } from "path";
|
|
13501
|
-
import { lstatSync as lstatSync14, readdirSync as
|
|
13501
|
+
import { lstatSync as lstatSync14, readdirSync as readdirSync6, readFileSync as readFileSync11, readlinkSync as readlinkSync3, realpathSync as realpathSync6 } from "fs";
|
|
13502
13502
|
|
|
13503
13503
|
// src/lib/codex-native-skill-catalog.ts
|
|
13504
13504
|
import { realpathSync as realpathSync5 } from "fs";
|
|
@@ -13836,14 +13836,35 @@ class KernelLock {
|
|
|
13836
13836
|
}
|
|
13837
13837
|
|
|
13838
13838
|
// src/lib/codex-corpus-write.ts
|
|
13839
|
-
import {
|
|
13839
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
13840
|
+
import { execFileSync, spawnSync as spawnSync3 } from "child_process";
|
|
13840
13841
|
import { createHash as createHash17 } from "crypto";
|
|
13841
|
-
import { accessSync, constants as constants8, lstatSync as lstatSync13, readFileSync as readFileSync10, realpathSync as realpathSync3, statSync as statSync7 } from "fs";
|
|
13842
|
+
import { accessSync, constants as constants8, lstatSync as lstatSync13, mkdirSync as mkdirSync5, mkdtempSync, readdirSync as readdirSync5, readFileSync as readFileSync10, realpathSync as realpathSync3, rmSync as rmSync2, statSync as statSync7 } from "fs";
|
|
13842
13843
|
import { basename as basename7, delimiter, dirname as dirname14, isAbsolute as isAbsolute13, join as join16, relative as relative4, resolve as resolve14, sep as sep7 } from "path";
|
|
13843
13844
|
var KEY = ".native-corpus-admission";
|
|
13844
|
-
var fail = () => {
|
|
13845
|
-
throw new Error(
|
|
13845
|
+
var fail = (reason2) => {
|
|
13846
|
+
throw new Error(`CODEX_CORPUS_ADMISSION_REQUIRED: verified native admission and its existing shared lock are required${reason2 ? ` (${reason2})` : ""}`);
|
|
13846
13847
|
};
|
|
13848
|
+
function codexAdmissionRecord(options) {
|
|
13849
|
+
const record4 = options.onCodexAdmission;
|
|
13850
|
+
const invalid = () => {
|
|
13851
|
+
throw new Error("CODEX_CORPUS_ADMISSION_RECORD_INVALID: onCodexAdmission must be a synchronous function");
|
|
13852
|
+
};
|
|
13853
|
+
if (record4 !== undefined && typeof record4 !== "function")
|
|
13854
|
+
invalid();
|
|
13855
|
+
return { policy: { fallback: typeof record4 === "function" }, deliver(admission) {
|
|
13856
|
+
if (!admission || typeof record4 !== "function")
|
|
13857
|
+
return;
|
|
13858
|
+
const result = record4(admission);
|
|
13859
|
+
if (result !== null && (typeof result === "object" || typeof result === "function") && typeof result.then === "function") {
|
|
13860
|
+
Promise.resolve(result).catch(() => {});
|
|
13861
|
+
invalid();
|
|
13862
|
+
}
|
|
13863
|
+
} };
|
|
13864
|
+
}
|
|
13865
|
+
function codexAdmissionReceipt(admission) {
|
|
13866
|
+
return admission?.nativeAdmission === "unavailable" && admission.probe ? { nativeAdmission: "unavailable", nativeAdmissionProbe: { ...admission.probe } } : {};
|
|
13867
|
+
}
|
|
13847
13868
|
function physicalTarget(path) {
|
|
13848
13869
|
const suffix = [];
|
|
13849
13870
|
for (let cursor = path;; cursor = dirname14(cursor)) {
|
|
@@ -13925,13 +13946,246 @@ function executable(options) {
|
|
|
13925
13946
|
const digest = hash2();
|
|
13926
13947
|
if (options.codexSha256 && digest !== options.codexSha256)
|
|
13927
13948
|
return fail();
|
|
13928
|
-
return { path, assertCurrent() {
|
|
13949
|
+
return { path, sha256: digest, size: Number(initial.size), assertCurrent() {
|
|
13929
13950
|
const current = statSync7(path, { bigint: true });
|
|
13930
13951
|
if (realpathSync3(found) !== path || ["dev", "ino", "size", "mtimeNs", "ctimeNs", "mode"].some((key2) => initial[key2] !== current[key2]) || hash2() !== digest)
|
|
13931
13952
|
fail();
|
|
13932
13953
|
} };
|
|
13933
13954
|
}
|
|
13934
|
-
|
|
13955
|
+
var PROBE = { timeout: 5000, maxBuffer: 4096, killSignal: "SIGKILL", encoding: "utf8" };
|
|
13956
|
+
var UNRECOGNIZED = /^error: unrecognized subcommand 'corpus-admission-inspect'(?:\r?\n|$)/;
|
|
13957
|
+
var VERSION = /^codex-cli (?:0|[1-9][0-9]{0,5})\.(?:0|[1-9][0-9]{0,5})\.(?:0|[1-9][0-9]{0,5})(?:-[0-9A-Za-z-]{1,32}(?:\.[0-9A-Za-z-]{1,32}){0,7})?$/;
|
|
13958
|
+
var LOCK_DIRECTORY = "codex-corpus-locks";
|
|
13959
|
+
var PROBE_PARENT = "codex-probe-homes";
|
|
13960
|
+
var retain = (hold) => {
|
|
13961
|
+
hold.refs++;
|
|
13962
|
+
return { hold, released: false };
|
|
13963
|
+
};
|
|
13964
|
+
var release = (ref) => {
|
|
13965
|
+
if (ref.released)
|
|
13966
|
+
return;
|
|
13967
|
+
ref.released = true;
|
|
13968
|
+
if (--ref.hold.refs === 0)
|
|
13969
|
+
ref.hold.lock.close();
|
|
13970
|
+
};
|
|
13971
|
+
var enclosing = new AsyncLocalStorage;
|
|
13972
|
+
var leaseHolds = new WeakMap;
|
|
13973
|
+
var contains = (base, path) => {
|
|
13974
|
+
const distance = relative4(base, path);
|
|
13975
|
+
return distance === "" || !distance.startsWith(`..${sep7}`) && distance !== ".." && !isAbsolute13(distance);
|
|
13976
|
+
};
|
|
13977
|
+
function nativeLockAbsent(root) {
|
|
13978
|
+
for (const name of [`${KEY}.flock-v1`, `${KEY}.lock`]) {
|
|
13979
|
+
try {
|
|
13980
|
+
lstatSync13(join16(root, name));
|
|
13981
|
+
return false;
|
|
13982
|
+
} catch (error) {
|
|
13983
|
+
if (error.code !== "ENOENT")
|
|
13984
|
+
throw error;
|
|
13985
|
+
}
|
|
13986
|
+
}
|
|
13987
|
+
return true;
|
|
13988
|
+
}
|
|
13989
|
+
function skillsState(root, leaf, roots) {
|
|
13990
|
+
const chain = [realpathSync3(dirname14(root))];
|
|
13991
|
+
for (const part of [".hasna", "skills", leaf])
|
|
13992
|
+
chain.push(join16(chain.at(-1), part));
|
|
13993
|
+
const path = chain.at(-1);
|
|
13994
|
+
const uid2 = process.getuid();
|
|
13995
|
+
const verify = () => {
|
|
13996
|
+
if (roots.some((item) => contains(item, path)) || codexCorpusRootForPath(path) !== undefined)
|
|
13997
|
+
fail();
|
|
13998
|
+
for (let ancestor = dirname14(chain[0]);; ancestor = dirname14(ancestor)) {
|
|
13999
|
+
const stat2 = lstatSync13(ancestor), sticky = stat2.uid === 0 && (stat2.mode & 512) !== 0;
|
|
14000
|
+
if (!stat2.isDirectory() || stat2.uid !== uid2 && stat2.uid !== 0 || (stat2.mode & 18) !== 0 && !sticky)
|
|
14001
|
+
fail();
|
|
14002
|
+
if (dirname14(ancestor) === ancestor)
|
|
14003
|
+
break;
|
|
14004
|
+
}
|
|
14005
|
+
for (const component of chain) {
|
|
14006
|
+
const stat2 = lstatSync13(component, { throwIfNoEntry: false });
|
|
14007
|
+
if (!stat2)
|
|
14008
|
+
return;
|
|
14009
|
+
if (!stat2.isDirectory() || stat2.uid !== uid2 && stat2.uid !== 0 || (stat2.mode & 18) !== 0 || component === path && stat2.uid !== uid2)
|
|
14010
|
+
fail();
|
|
14011
|
+
}
|
|
14012
|
+
};
|
|
14013
|
+
verify();
|
|
14014
|
+
return { path, ensure() {
|
|
14015
|
+
verify();
|
|
14016
|
+
for (const component of chain.slice(1)) {
|
|
14017
|
+
try {
|
|
14018
|
+
mkdirSync5(component, { mode: 448 });
|
|
14019
|
+
} catch (error) {
|
|
14020
|
+
if (error.code !== "EEXIST")
|
|
14021
|
+
throw error;
|
|
14022
|
+
}
|
|
14023
|
+
}
|
|
14024
|
+
verify();
|
|
14025
|
+
if (realpathSync3(path) !== path)
|
|
14026
|
+
fail();
|
|
14027
|
+
return path;
|
|
14028
|
+
} };
|
|
14029
|
+
}
|
|
14030
|
+
function probeParent(roots) {
|
|
14031
|
+
const dataRoot = resolve14(getDataDirReadOnly()), path = join16(dataRoot, PROBE_PARENT), uid2 = process.getuid();
|
|
14032
|
+
const chain = [];
|
|
14033
|
+
for (let component = path;; component = dirname14(component)) {
|
|
14034
|
+
chain.unshift(component);
|
|
14035
|
+
if (dirname14(component) === component)
|
|
14036
|
+
break;
|
|
14037
|
+
}
|
|
14038
|
+
const verify = () => {
|
|
14039
|
+
if (roots.some((item) => contains(item, path)) || codexCorpusRootForPath(path) !== undefined)
|
|
14040
|
+
fail();
|
|
14041
|
+
for (const component of chain) {
|
|
14042
|
+
const stat2 = lstatSync13(component, { throwIfNoEntry: false });
|
|
14043
|
+
if (!stat2)
|
|
14044
|
+
return;
|
|
14045
|
+
const skills = contains(dataRoot, component), sticky = !skills && stat2.uid === 0 && (stat2.mode & 512) !== 0;
|
|
14046
|
+
if (!stat2.isDirectory() || stat2.uid !== uid2 && (skills || stat2.uid !== 0) || (stat2.mode & 18) !== 0 && !sticky)
|
|
14047
|
+
fail();
|
|
14048
|
+
}
|
|
14049
|
+
};
|
|
14050
|
+
verify();
|
|
14051
|
+
for (const component of chain) {
|
|
14052
|
+
if (lstatSync13(component, { throwIfNoEntry: false }))
|
|
14053
|
+
continue;
|
|
14054
|
+
try {
|
|
14055
|
+
mkdirSync5(component, { mode: 448 });
|
|
14056
|
+
} catch (error) {
|
|
14057
|
+
if (error.code !== "EEXIST")
|
|
14058
|
+
throw error;
|
|
14059
|
+
}
|
|
14060
|
+
}
|
|
14061
|
+
verify();
|
|
14062
|
+
if (realpathSync3(path) !== path)
|
|
14063
|
+
fail();
|
|
14064
|
+
return path;
|
|
14065
|
+
}
|
|
14066
|
+
function probeHomeIntact(home, empty) {
|
|
14067
|
+
const stat2 = lstatSync13(home.path, { bigint: true, throwIfNoEntry: false });
|
|
14068
|
+
return !!stat2 && stat2.isDirectory() && stat2.dev === home.dev && stat2.ino === home.ino && stat2.uid === BigInt(process.getuid()) && (stat2.mode & 0o777n) === 0o700n && realpathSync3(home.path) === home.path && (!empty || readdirSync5(home.path).length === 0);
|
|
14069
|
+
}
|
|
14070
|
+
function removeProbeHome(home) {
|
|
14071
|
+
try {
|
|
14072
|
+
const stat2 = lstatSync13(home.path, { bigint: true });
|
|
14073
|
+
if (stat2.isDirectory() && stat2.dev === home.dev && stat2.ino === home.ino)
|
|
14074
|
+
rmSync2(home.path, { recursive: true, force: true });
|
|
14075
|
+
} catch {}
|
|
14076
|
+
}
|
|
14077
|
+
function probe(path, args, parent, stdio) {
|
|
14078
|
+
const created = mkdtempSync(join16(parent, "probe-")), stat2 = lstatSync13(created, { bigint: true });
|
|
14079
|
+
const home = { path: created, dev: stat2.dev, ino: stat2.ino };
|
|
14080
|
+
try {
|
|
14081
|
+
if (!probeHomeIntact(home, true))
|
|
14082
|
+
return;
|
|
14083
|
+
const env = { CODEX_HOME: home.path };
|
|
14084
|
+
for (const key2 of ["PATH", "HOME"])
|
|
14085
|
+
if (process.env[key2] !== undefined)
|
|
14086
|
+
env[key2] = process.env[key2];
|
|
14087
|
+
const result = spawnSync3(path, args, { ...PROBE, cwd: home.path, env, stdio: ["ignore", stdio, stdio] });
|
|
14088
|
+
return probeHomeIntact(home, false) ? result : undefined;
|
|
14089
|
+
} finally {
|
|
14090
|
+
removeProbeHome(home);
|
|
14091
|
+
}
|
|
14092
|
+
}
|
|
14093
|
+
function probeAdmissionCommand(path, parent) {
|
|
14094
|
+
const help = probe(path, ["help", "corpus-admission-inspect"], parent, "pipe");
|
|
14095
|
+
if (!help || help.error || help.signal !== null)
|
|
14096
|
+
return "inconclusive";
|
|
14097
|
+
if (help.status === 0)
|
|
14098
|
+
return "present";
|
|
14099
|
+
if (help.status !== 2 || help.stdout !== "" || typeof help.stderr !== "string" || !UNRECOGNIZED.test(help.stderr))
|
|
14100
|
+
return "inconclusive";
|
|
14101
|
+
const control = probe(path, ["help", "exec"], parent, "ignore");
|
|
14102
|
+
return control && !control.error && control.signal === null && control.status === 0 ? "absent" : "inconclusive";
|
|
14103
|
+
}
|
|
14104
|
+
function strictVersion(path, parent) {
|
|
14105
|
+
const result = probe(path, ["--version"], parent, "pipe");
|
|
14106
|
+
if (!result || result.error || result.signal !== null || result.status !== 0 || typeof result.stdout !== "string")
|
|
14107
|
+
return;
|
|
14108
|
+
const line = result.stdout.replace(/\r?\n$/, "");
|
|
14109
|
+
return VERSION.test(line) ? line : undefined;
|
|
14110
|
+
}
|
|
14111
|
+
function rootLockKey(root, id) {
|
|
14112
|
+
return `codex-corpus-${createHash17("sha256").update(`${root}\x00${id.device}\x00${id.inode}`).digest("hex")}`;
|
|
14113
|
+
}
|
|
14114
|
+
function acquireFallback(inputs, options) {
|
|
14115
|
+
let reason2 = "executable-unverified";
|
|
14116
|
+
const refs = new Map, held = [];
|
|
14117
|
+
const close = () => {
|
|
14118
|
+
for (const ref of [...refs.values()].reverse())
|
|
14119
|
+
release(ref);
|
|
14120
|
+
};
|
|
14121
|
+
try {
|
|
14122
|
+
const native = executable(options);
|
|
14123
|
+
reason2 = "skills-lock-unavailable";
|
|
14124
|
+
const roots = inputs.map((item) => item.root);
|
|
14125
|
+
const locks = new Map(roots.map((root) => [root, skillsState(root, LOCK_DIRECTORY, roots)]));
|
|
14126
|
+
const parent = probeParent(roots);
|
|
14127
|
+
reason2 = "probe-inconclusive";
|
|
14128
|
+
const state = probeAdmissionCommand(native.path, parent);
|
|
14129
|
+
if (state === "present")
|
|
14130
|
+
reason2 = "command-present";
|
|
14131
|
+
if (state !== "absent")
|
|
14132
|
+
fail();
|
|
14133
|
+
const version = strictVersion(native.path, parent);
|
|
14134
|
+
if (version === undefined)
|
|
14135
|
+
fail();
|
|
14136
|
+
reason2 = "executable-unverified";
|
|
14137
|
+
native.assertCurrent();
|
|
14138
|
+
reason2 = "skills-lock-unavailable";
|
|
14139
|
+
for (const { input, root } of inputs) {
|
|
14140
|
+
const id = identity3(root), key2 = rootLockKey(root, id);
|
|
14141
|
+
if (!refs.has(key2)) {
|
|
14142
|
+
const owner2 = enclosing.getStore()?.get(key2);
|
|
14143
|
+
if (owner2 && !owner2.released)
|
|
14144
|
+
refs.set(key2, retain(owner2.hold));
|
|
14145
|
+
else {
|
|
14146
|
+
const lock = new KernelLock(locks.get(root).ensure(), key2, { mode: "exclusive" });
|
|
14147
|
+
refs.set(key2, retain({ lock, refs: 0 }));
|
|
14148
|
+
if (!lock.trySync(1000)) {
|
|
14149
|
+
reason2 = "writer-busy";
|
|
14150
|
+
fail();
|
|
14151
|
+
}
|
|
14152
|
+
}
|
|
14153
|
+
}
|
|
14154
|
+
held.push({ input, root, id, ref: refs.get(key2) });
|
|
14155
|
+
}
|
|
14156
|
+
const assertCurrent = () => {
|
|
14157
|
+
try {
|
|
14158
|
+
for (const item of held) {
|
|
14159
|
+
if (item.ref.released)
|
|
14160
|
+
fail();
|
|
14161
|
+
item.ref.hold.lock.assertUnchanged();
|
|
14162
|
+
if (realpathSync3(item.input) !== item.root || !sameIdentity(identity3(item.root), item.id) || !nativeLockAbsent(item.root))
|
|
14163
|
+
fail();
|
|
14164
|
+
}
|
|
14165
|
+
native.assertCurrent();
|
|
14166
|
+
} catch {
|
|
14167
|
+
fail("lease-changed");
|
|
14168
|
+
}
|
|
14169
|
+
};
|
|
14170
|
+
reason2 = "lease-changed";
|
|
14171
|
+
assertCurrent();
|
|
14172
|
+
const lease = { assertCurrent, close, admission: { nativeAdmission: "unavailable", probe: {
|
|
14173
|
+
kind: "help-unrecognized-subcommand",
|
|
14174
|
+
executable: native.path,
|
|
14175
|
+
sha256: native.sha256,
|
|
14176
|
+
size: native.size,
|
|
14177
|
+
version,
|
|
14178
|
+
probeExitCode: 2,
|
|
14179
|
+
controlExitCode: 0
|
|
14180
|
+
} } };
|
|
14181
|
+
leaseHolds.set(lease, refs);
|
|
14182
|
+
return lease;
|
|
14183
|
+
} catch {
|
|
14184
|
+
close();
|
|
14185
|
+
return fail(reason2);
|
|
14186
|
+
}
|
|
14187
|
+
}
|
|
14188
|
+
function acquireCodexCorpusWrite(roots, options, policy = {}) {
|
|
13935
14189
|
const held = [];
|
|
13936
14190
|
const close = () => {
|
|
13937
14191
|
for (const item of held.reverse())
|
|
@@ -13944,10 +14198,20 @@ function acquireCodexCorpusWrite(roots, options) {
|
|
|
13944
14198
|
fail();
|
|
13945
14199
|
}
|
|
13946
14200
|
};
|
|
14201
|
+
let fallback = false, refusal;
|
|
13947
14202
|
try {
|
|
13948
14203
|
if (roots.some((root) => typeof root !== "string" || !isAbsolute13(root) || root.includes("\x00")))
|
|
13949
14204
|
fail();
|
|
13950
14205
|
const inputs = [...new Set(roots)].map((input) => ({ input, root: realpathSync3(input) })).sort((a, b) => a.root.localeCompare(b.root));
|
|
14206
|
+
const absent = inputs.filter(({ root }) => nativeLockAbsent(root));
|
|
14207
|
+
if (absent.length && absent.length !== inputs.length) {
|
|
14208
|
+
refusal = "native-lock-present";
|
|
14209
|
+
fail();
|
|
14210
|
+
}
|
|
14211
|
+
if (absent.length && policy.fallback !== false) {
|
|
14212
|
+
fallback = true;
|
|
14213
|
+
return acquireFallback(inputs, options);
|
|
14214
|
+
}
|
|
13951
14215
|
for (const { input, root } of inputs) {
|
|
13952
14216
|
const lock = new KernelLock(root, KEY, { mode: "shared", existingOnly: true });
|
|
13953
14217
|
held.push({ input, root, lock });
|
|
@@ -13975,19 +14239,25 @@ function acquireCodexCorpusWrite(roots, options) {
|
|
|
13975
14239
|
if (Object.keys(row).sort().join(",") !== "lock,root,schema,state" || row.schema !== "codex-corpus-admission-status/v1" || row.state !== "committed-v1" && row.state !== "committed-v2" || !sameIdentity(row.root, rootIdentity) || !sameIdentity(row.lock, lockIdentity))
|
|
13976
14240
|
fail();
|
|
13977
14241
|
}
|
|
13978
|
-
return { assertCurrent, close };
|
|
13979
|
-
} catch {
|
|
14242
|
+
return { assertCurrent, close, admission: { nativeAdmission: "verified" } };
|
|
14243
|
+
} catch (error) {
|
|
14244
|
+
if (fallback)
|
|
14245
|
+
throw error;
|
|
13980
14246
|
close();
|
|
13981
|
-
return fail();
|
|
14247
|
+
return fail(refusal);
|
|
13982
14248
|
}
|
|
13983
14249
|
}
|
|
13984
|
-
function
|
|
14250
|
+
function scoped(lease, run) {
|
|
14251
|
+
const holds = leaseHolds.get(lease);
|
|
14252
|
+
return holds?.size ? enclosing.run(new Map([...enclosing.getStore() ?? [], ...holds]), run) : run();
|
|
14253
|
+
}
|
|
14254
|
+
function withCodexCorpusWrite(roots, run, options = {}, policy = {}) {
|
|
13985
14255
|
if (!roots.length)
|
|
13986
14256
|
return run(() => {});
|
|
13987
|
-
const lease = acquireCodexCorpusWrite(roots, options);
|
|
14257
|
+
const lease = acquireCodexCorpusWrite(roots, options, policy);
|
|
13988
14258
|
try {
|
|
13989
14259
|
lease.assertCurrent();
|
|
13990
|
-
const result = run(lease.assertCurrent);
|
|
14260
|
+
const result = scoped(lease, () => run(lease.assertCurrent, lease.admission));
|
|
13991
14261
|
lease.assertCurrent();
|
|
13992
14262
|
return result;
|
|
13993
14263
|
} finally {
|
|
@@ -14108,6 +14378,7 @@ async function connectCodexHookRpc(options) {
|
|
|
14108
14378
|
const rpc = {
|
|
14109
14379
|
version,
|
|
14110
14380
|
processId: child2.pid,
|
|
14381
|
+
admission: corpusLease.admission,
|
|
14111
14382
|
request(method, params) {
|
|
14112
14383
|
if (stopped)
|
|
14113
14384
|
return Promise.reject(new Error(configInvalid ? CODEX_CONFIG_INVALID : "CODEX_HOOK_TRUST_NATIVE_RPC_CLOSED"));
|
|
@@ -14561,7 +14832,7 @@ function reviewedRetiredCodexRoot(cache, root, controls, rules, read2, allowAbse
|
|
|
14561
14832
|
if (!enrolled.some((control) => control.namespace === parsed.namespace && control.manifestSha256 === parsed.manifestSha256 && !parsed.appSha256 && !parsed.mcpSha256))
|
|
14562
14833
|
return false;
|
|
14563
14834
|
let entries = 0;
|
|
14564
|
-
const emptySkills = (directory, depth) => depth <= 64 &&
|
|
14835
|
+
const emptySkills = (directory, depth) => depth <= 64 && readdirSync6(directory).every((name) => {
|
|
14565
14836
|
if (++entries > 4096 || name === "SKILL.md")
|
|
14566
14837
|
return false;
|
|
14567
14838
|
const path = join18(directory, name), stat2 = lstatSync14(path);
|
|
@@ -14586,7 +14857,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read2, rules)
|
|
|
14586
14857
|
if (control.remotePluginId !== undefined && !remoteInstallationMatches(parent, control.remotePluginId, read2))
|
|
14587
14858
|
return false;
|
|
14588
14859
|
}
|
|
14589
|
-
const names =
|
|
14860
|
+
const names = readdirSync6(parent);
|
|
14590
14861
|
entries += names.length;
|
|
14591
14862
|
if (entries > 4096)
|
|
14592
14863
|
return false;
|
|
@@ -14803,11 +15074,11 @@ var MAX_SUBTREE_DEPTH = 32;
|
|
|
14803
15074
|
var hiddenName = (name) => name.startsWith(".") || name === "node_modules";
|
|
14804
15075
|
var isSkillDocument = (name) => name.toLowerCase() === "skill.md";
|
|
14805
15076
|
var present = (path) => lstatSync15(path, { throwIfNoEntry: false }) !== undefined;
|
|
14806
|
-
var holdsOtherControl = (path) =>
|
|
15077
|
+
var holdsOtherControl = (path) => readdirSync7(path).some((name) => OTHER_PLUGIN_CONTROLS.includes(name.toLowerCase()));
|
|
14807
15078
|
function pluginTreeVisible(path, hidden, insideSkill, depth, budget2) {
|
|
14808
15079
|
if (depth > MAX_SUBTREE_DEPTH)
|
|
14809
15080
|
return false;
|
|
14810
|
-
const names =
|
|
15081
|
+
const names = readdirSync7(path);
|
|
14811
15082
|
const skill = names.some(isSkillDocument);
|
|
14812
15083
|
if (skill && (hidden || insideSkill))
|
|
14813
15084
|
return false;
|
|
@@ -14831,7 +15102,7 @@ function codexVendorPluginRootRefreshSafe(root, budget2 = { remaining: MAX_SUBTR
|
|
|
14831
15102
|
return false;
|
|
14832
15103
|
if (!directory(join19(root, ".codex-plugin")))
|
|
14833
15104
|
return false;
|
|
14834
|
-
const controls =
|
|
15105
|
+
const controls = readdirSync7(join19(root, ".codex-plugin"));
|
|
14835
15106
|
if (controls.length !== 1 || controls[0] !== "plugin.json")
|
|
14836
15107
|
return false;
|
|
14837
15108
|
const manifest = join19(root, ".codex-plugin", "plugin.json"), stat2 = lstatSync15(manifest, { throwIfNoEntry: false });
|
|
@@ -14854,7 +15125,7 @@ function codexVendorPluginRootRefreshSafe(root, budget2 = { remaining: MAX_SUBTR
|
|
|
14854
15125
|
}
|
|
14855
15126
|
function vendorMembers(path, budget2) {
|
|
14856
15127
|
const directories = [];
|
|
14857
|
-
for (const name of
|
|
15128
|
+
for (const name of readdirSync7(path)) {
|
|
14858
15129
|
if (--budget2.remaining < 0)
|
|
14859
15130
|
return null;
|
|
14860
15131
|
const stat2 = lstatSync15(join19(path, name));
|
|
@@ -15144,7 +15415,7 @@ import { basename as basename13, dirname as dirname24, isAbsolute as isAbsolute2
|
|
|
15144
15415
|
import { homedir as homedir5 } from "os";
|
|
15145
15416
|
import { isAbsolute as isAbsolute25, join as join36, resolve as resolve24 } from "path";
|
|
15146
15417
|
// package.json
|
|
15147
|
-
var version = "0.10.
|
|
15418
|
+
var version = "0.10.76";
|
|
15148
15419
|
var package_default = {
|
|
15149
15420
|
name: "@hasna/skills",
|
|
15150
15421
|
version,
|
|
@@ -15287,7 +15558,7 @@ var package_default = {
|
|
|
15287
15558
|
|
|
15288
15559
|
// node_modules/@hasna/contracts/dist/client/transport.js
|
|
15289
15560
|
import { isIP } from "net";
|
|
15290
|
-
import { spawnSync as
|
|
15561
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
15291
15562
|
import { closeSync as closeSync22, fstatSync as fstatSync22, openSync as openSync22, readFileSync as readFileSync22 } from "fs";
|
|
15292
15563
|
import { O_NOFOLLOW as O_NOFOLLOW2, O_NONBLOCK as O_NONBLOCK2, O_RDONLY as O_RDONLY2 } from "constants";
|
|
15293
15564
|
import { hostname as osHostname } from "os";
|
|
@@ -15687,7 +15958,7 @@ function isAmbientEnvironment(env) {
|
|
|
15687
15958
|
return env === process.env || env[AMBIENT_ENVIRONMENT] === true;
|
|
15688
15959
|
}
|
|
15689
15960
|
function defaultKeychainRunner(argv) {
|
|
15690
|
-
const result =
|
|
15961
|
+
const result = spawnSync4(KEYCHAIN_SECURITY_BIN, [...argv], {
|
|
15691
15962
|
encoding: "utf8",
|
|
15692
15963
|
stdio: ["ignore", "pipe", "pipe"],
|
|
15693
15964
|
timeout: KEYCHAIN_SPAWN_TIMEOUT_MS
|
|
@@ -16782,7 +17053,7 @@ async function createProfileClient(signal) {
|
|
|
16782
17053
|
}
|
|
16783
17054
|
|
|
16784
17055
|
// src/lib/dependency-preparation.ts
|
|
16785
|
-
import { constants as constants10, closeSync as closeSync10, fstatSync as fstatSync10, lstatSync as lstatSync18, mkdirSync as
|
|
17056
|
+
import { constants as constants10, closeSync as closeSync10, fstatSync as fstatSync10, lstatSync as lstatSync18, mkdirSync as mkdirSync6, openSync as openSync10, readFileSync as readFileSync14, readdirSync as readdirSync8, rmdirSync as rmdirSync2, unlinkSync as unlinkSync3, ftruncateSync, writeSync as writeSync2 } from "fs";
|
|
16786
17057
|
import { join as join21 } from "path";
|
|
16787
17058
|
|
|
16788
17059
|
// src/lib/preparation-process.ts
|
|
@@ -16841,7 +17112,7 @@ function claimPreparation(skillPath) {
|
|
|
16841
17112
|
const state = join21(marker, "state.json"), active = join21(marker, "active");
|
|
16842
17113
|
let created = false;
|
|
16843
17114
|
try {
|
|
16844
|
-
|
|
17115
|
+
mkdirSync6(marker, { mode: 448 });
|
|
16845
17116
|
created = true;
|
|
16846
17117
|
} catch (error) {
|
|
16847
17118
|
if (error.code !== "EEXIST")
|
|
@@ -16852,7 +17123,7 @@ function claimPreparation(skillPath) {
|
|
|
16852
17123
|
if (!lstatSync18(marker).isDirectory() || lstatSync18(marker).isSymbolicLink())
|
|
16853
17124
|
return;
|
|
16854
17125
|
if (!created) {
|
|
16855
|
-
if (
|
|
17126
|
+
if (readdirSync8(marker).some((name) => name !== "state.json"))
|
|
16856
17127
|
return;
|
|
16857
17128
|
if (!lstatSync18(state).isFile() || lstatSync18(state).isSymbolicLink() || lstatSync18(state).size > 1024)
|
|
16858
17129
|
return;
|
|
@@ -16860,7 +17131,7 @@ function claimPreparation(skillPath) {
|
|
|
16860
17131
|
if (previous.version !== 1 || previous.status !== "failed" || Object.keys(previous).length !== 2)
|
|
16861
17132
|
return;
|
|
16862
17133
|
}
|
|
16863
|
-
|
|
17134
|
+
mkdirSync6(active, { mode: 448 });
|
|
16864
17135
|
fd = openSync10(state, constants10.O_RDWR | constants10.O_NOFOLLOW | (created ? constants10.O_CREAT | constants10.O_EXCL : 0), 384);
|
|
16865
17136
|
if (!fstatSync10(fd).isFile()) {
|
|
16866
17137
|
closeSync10(fd);
|
|
@@ -16993,7 +17264,7 @@ import { existsSync as existsSync13, readFileSync as readFileSync25 } from "fs";
|
|
|
16993
17264
|
import { join as join35 } from "path";
|
|
16994
17265
|
|
|
16995
17266
|
// src/lib/installer.ts
|
|
16996
|
-
import { existsSync as existsSync12, readFileSync as readFileSync23, rmSync as
|
|
17267
|
+
import { existsSync as existsSync12, readFileSync as readFileSync23, rmSync as rmSync4 } from "fs";
|
|
16997
17268
|
import { join as join34 } from "path";
|
|
16998
17269
|
import { homedir as homedir4 } from "os";
|
|
16999
17270
|
|
|
@@ -17002,12 +17273,12 @@ import {
|
|
|
17002
17273
|
cpSync as cpSync2,
|
|
17003
17274
|
existsSync as existsSync10,
|
|
17004
17275
|
lstatSync as lstatSync29,
|
|
17005
|
-
mkdirSync as
|
|
17006
|
-
mkdtempSync,
|
|
17276
|
+
mkdirSync as mkdirSync10,
|
|
17277
|
+
mkdtempSync as mkdtempSync2,
|
|
17007
17278
|
readFileSync as readFileSync20,
|
|
17008
|
-
readdirSync as
|
|
17279
|
+
readdirSync as readdirSync12,
|
|
17009
17280
|
renameSync as renameSync5,
|
|
17010
|
-
rmSync as
|
|
17281
|
+
rmSync as rmSync3,
|
|
17011
17282
|
statSync as statSync12,
|
|
17012
17283
|
writeFileSync as writeFileSync7
|
|
17013
17284
|
} from "fs";
|
|
@@ -17016,7 +17287,7 @@ import { basename as basename12, dirname as dirname23, join as join32 } from "pa
|
|
|
17016
17287
|
|
|
17017
17288
|
// src/lib/codex-native-skill-policy.ts
|
|
17018
17289
|
import { createHash as createHash21, randomUUID as randomUUID3 } from "crypto";
|
|
17019
|
-
import { closeSync as closeSync11, constants as constants11, fstatSync as fstatSync11, fsyncSync as fsyncSync3, lstatSync as lstatSync19, mkdirSync as
|
|
17290
|
+
import { closeSync as closeSync11, constants as constants11, fstatSync as fstatSync11, fsyncSync as fsyncSync3, lstatSync as lstatSync19, mkdirSync as mkdirSync7, openSync as openSync11, readFileSync as readFileSync15, readSync as readSync7, readlinkSync as readlinkSync4, realpathSync as realpathSync8, renameSync as renameSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
17020
17291
|
import { dirname as dirname17, isAbsolute as isAbsolute18, join as join23, resolve as resolve17 } from "path";
|
|
17021
17292
|
import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
|
|
17022
17293
|
var CODEX_NATIVE_POLICY_CAPABILITY = "host-path-allowlist-v1";
|
|
@@ -17285,7 +17556,7 @@ function writeExecutableCache(dataDir2, entries) {
|
|
|
17285
17556
|
return;
|
|
17286
17557
|
const existing = lstatSync19(directory2, { throwIfNoEntry: false });
|
|
17287
17558
|
if (!existing)
|
|
17288
|
-
|
|
17559
|
+
mkdirSync7(directory2, { mode: 448 });
|
|
17289
17560
|
else if (existing.isSymbolicLink() || !existing.isDirectory())
|
|
17290
17561
|
return;
|
|
17291
17562
|
const holder = lstatSync19(directory2, { throwIfNoEntry: false, bigint: true });
|
|
@@ -17580,7 +17851,7 @@ function recordCodexNativePolicyAcceptance(dataDir2, verification, accepted) {
|
|
|
17580
17851
|
...verification.attestation ? { attestation: { schema: verification.attestation.schema, peerProcessId: verification.attestation.peerProcessId } } : {}
|
|
17581
17852
|
};
|
|
17582
17853
|
try {
|
|
17583
|
-
|
|
17854
|
+
mkdirSync7(directory2, { recursive: true, mode: 448 });
|
|
17584
17855
|
const stat2 = lstatSync19(directory2);
|
|
17585
17856
|
if (stat2.isSymbolicLink() || !stat2.isDirectory())
|
|
17586
17857
|
throw new Error(`the receipt directory is not a real directory: ${directory2}`);
|
|
@@ -17612,7 +17883,7 @@ function recordCodexNativePolicyAcceptance(dataDir2, verification, accepted) {
|
|
|
17612
17883
|
|
|
17613
17884
|
// src/lib/codex-semantic-cache-witness.ts
|
|
17614
17885
|
import { createHash as createHash22 } from "crypto";
|
|
17615
|
-
import { constants as constants12, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as lstatSync20, openSync as openSync12, readSync as readSync8, readdirSync as
|
|
17886
|
+
import { constants as constants12, closeSync as closeSync12, fstatSync as fstatSync12, lstatSync as lstatSync20, openSync as openSync12, readSync as readSync8, readdirSync as readdirSync9, realpathSync as realpathSync9 } from "fs";
|
|
17616
17887
|
import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute19, join as join25, relative as relative8, resolve as resolve18, sep as sep11 } from "path";
|
|
17617
17888
|
var CODEX_SEMANTIC_CACHE_WITNESS_SCHEMA = "hasna.codex-semantic-cache-witness.v1";
|
|
17618
17889
|
var identifier5 = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(value);
|
|
@@ -17777,7 +18048,7 @@ function assertCanonicalDirectory(path) {
|
|
|
17777
18048
|
function walkSafeTree(path, state, depth = 0, root = path) {
|
|
17778
18049
|
if (depth > 64 || ++state.entries > 16384)
|
|
17779
18050
|
refuse4();
|
|
17780
|
-
const names =
|
|
18051
|
+
const names = readdirSync9(path).sort();
|
|
17781
18052
|
const files = [];
|
|
17782
18053
|
for (const name of names) {
|
|
17783
18054
|
if (!name || name === "." || name === ".." || name.includes(sep11) || ++state.entries > 16384)
|
|
@@ -17923,7 +18194,7 @@ function appOnlyParentProjection(cacheRoot, parents2, read2) {
|
|
|
17923
18194
|
} catch {
|
|
17924
18195
|
refuse4();
|
|
17925
18196
|
}
|
|
17926
|
-
const versions =
|
|
18197
|
+
const versions = readdirSync9(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json");
|
|
17927
18198
|
if (!versions.length || versions.length > 4096)
|
|
17928
18199
|
refuse4();
|
|
17929
18200
|
const materializations = versions.map((version2) => {
|
|
@@ -18068,7 +18339,7 @@ function reviewedHookParentProjection(cacheRoot, parents2, read2) {
|
|
|
18068
18339
|
if (createHash22("sha256").update(marketplaceText).digest("hex") !== parent.marketplaceSha256 || !codexLocalMarketplaceMapsPlugin(marketplaceText, parts[0], parent.namespace))
|
|
18069
18340
|
refuse4();
|
|
18070
18341
|
}
|
|
18071
|
-
const materializations =
|
|
18342
|
+
const materializations = readdirSync9(parent.pluginParent).filter((name) => name !== ".codex-remote-plugin-install.json").map((version2) => {
|
|
18072
18343
|
if (!/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(version2))
|
|
18073
18344
|
refuse4();
|
|
18074
18345
|
const root = join25(parent.pluginParent, version2), stat2 = lstatSync20(root, { throwIfNoEntry: false });
|
|
@@ -18102,14 +18373,14 @@ function assertParents(cacheRoot, controls, appOnlyParents, hookParents, files,
|
|
|
18102
18373
|
refuse4();
|
|
18103
18374
|
actual.add(join25(cacheRoot, parts[0], parts[1]));
|
|
18104
18375
|
}
|
|
18105
|
-
const actualMarkets =
|
|
18376
|
+
const actualMarkets = readdirSync9(cacheRoot);
|
|
18106
18377
|
if (actualMarkets.length !== expectedMarkets.size || actualMarkets.some((market) => !expectedMarkets.has(market)))
|
|
18107
18378
|
refuse4();
|
|
18108
18379
|
for (const market of actualMarkets) {
|
|
18109
18380
|
const marketPath = join25(cacheRoot, market), marketStat = lstatSync20(marketPath);
|
|
18110
18381
|
if (!identifier5(market) || !marketStat.isDirectory() || marketStat.isSymbolicLink())
|
|
18111
18382
|
refuse4();
|
|
18112
|
-
for (const plugin of
|
|
18383
|
+
for (const plugin of readdirSync9(marketPath)) {
|
|
18113
18384
|
const parent = join25(marketPath, plugin), stat2 = lstatSync20(parent);
|
|
18114
18385
|
if (!identifier5(plugin) || !stat2.isDirectory() || stat2.isSymbolicLink())
|
|
18115
18386
|
refuse4();
|
|
@@ -18161,7 +18432,7 @@ function assertSkillMaterializations(cacheRoot, controls, files, read2) {
|
|
|
18161
18432
|
const expectedNames = new Set(rows.map((row) => row.name));
|
|
18162
18433
|
if (expectedNames.size !== rows.length)
|
|
18163
18434
|
refuse4();
|
|
18164
|
-
const entries =
|
|
18435
|
+
const entries = readdirSync9(parent);
|
|
18165
18436
|
let roots = 0;
|
|
18166
18437
|
for (const entry of entries) {
|
|
18167
18438
|
if (entry === ".codex-remote-plugin-install.json")
|
|
@@ -18400,7 +18671,7 @@ function codexPluginCacheSkillTree(path, depth) {
|
|
|
18400
18671
|
// src/lib/agent-integration.ts
|
|
18401
18672
|
import { createHash as createHash27, randomUUID as randomUUID4 } from "crypto";
|
|
18402
18673
|
import { isDeepStrictEqual as isDeepStrictEqual8 } from "util";
|
|
18403
|
-
import { existsSync as existsSync9, lstatSync as lstatSync28, statSync as statSync11, mkdirSync as
|
|
18674
|
+
import { existsSync as existsSync9, lstatSync as lstatSync28, statSync as statSync11, mkdirSync as mkdirSync9, readFileSync as readFileSync19, readdirSync as readdirSync11, opendirSync as opendirSync4, readlinkSync as readlinkSync7, realpathSync as realpathSync12, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync6, unlinkSync as unlinkSync5, chmodSync, openSync as openSync17, closeSync as closeSync17, fsyncSync as fsyncSync7, fstatSync as fstatSync17, readSync as readSync12, constants as constants18, linkSync as linkSync3 } from "fs";
|
|
18404
18675
|
import { basename as basename11, dirname as dirname22, join as join31, resolve as resolve23, relative as relative9, isAbsolute as isAbsolute24, sep as sep14 } from "path";
|
|
18405
18676
|
import { homedir as homedir2 } from "os";
|
|
18406
18677
|
|
|
@@ -18486,7 +18757,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
|
|
|
18486
18757
|
|
|
18487
18758
|
// src/lib/agent-bridge.ts
|
|
18488
18759
|
import { createHash as createHash23 } from "crypto";
|
|
18489
|
-
import { lstatSync as lstatSync23, readFileSync as readFileSync17, readdirSync as
|
|
18760
|
+
import { lstatSync as lstatSync23, readFileSync as readFileSync17, readdirSync as readdirSync10 } from "fs";
|
|
18490
18761
|
import { join as join28 } from "path";
|
|
18491
18762
|
var CLI_BRIDGE_NAME = "skills-cli";
|
|
18492
18763
|
var CLI_BRIDGE_VERSION = 1;
|
|
@@ -18516,7 +18787,7 @@ function isOwnedCliBridge(path, expectedPaths) {
|
|
|
18516
18787
|
try {
|
|
18517
18788
|
if (!lstatSync23(path).isDirectory())
|
|
18518
18789
|
return false;
|
|
18519
|
-
if (JSON.stringify(
|
|
18790
|
+
if (JSON.stringify(readdirSync10(path).sort()) !== JSON.stringify(Object.keys(CLI_BRIDGE_FILES).sort()))
|
|
18520
18791
|
return false;
|
|
18521
18792
|
return Object.entries(CLI_BRIDGE_FILES).every(([name, content]) => {
|
|
18522
18793
|
const file = join28(path, name), stat2 = lstatSync23(file);
|
|
@@ -18796,7 +19067,7 @@ function disableCodexBundledSkills(text2) {
|
|
|
18796
19067
|
}
|
|
18797
19068
|
|
|
18798
19069
|
// src/lib/agent-sumi.ts
|
|
18799
|
-
import { spawnSync as
|
|
19070
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
18800
19071
|
import { accessSync as accessSync2, constants as constants14, existsSync as existsSync8, lstatSync as lstatSync24, realpathSync as realpathSync10, statSync as statSync10 } from "fs";
|
|
18801
19072
|
import { delimiter as delimiter2, isAbsolute as isAbsolute20, join as join29, resolve as resolve20 } from "path";
|
|
18802
19073
|
|
|
@@ -18954,7 +19225,7 @@ function sumiPathPlan(home, cwd = process.cwd(), env = process.env) {
|
|
|
18954
19225
|
childEnv[key2] = env[key2];
|
|
18955
19226
|
let child2;
|
|
18956
19227
|
try {
|
|
18957
|
-
child2 =
|
|
19228
|
+
child2 = spawnSync5(executable2, ["--json", "--home", resolve20(home), "--cwd", resolve20(cwd)], {
|
|
18958
19229
|
cwd: resolve20(cwd),
|
|
18959
19230
|
env: childEnv,
|
|
18960
19231
|
encoding: "buffer",
|
|
@@ -19420,7 +19691,7 @@ function assertPinnedLauncherRuntimeSafe(runtime) {
|
|
|
19420
19691
|
|
|
19421
19692
|
// src/lib/retained-review-artifacts.ts
|
|
19422
19693
|
import { createHash as createHash26 } from "crypto";
|
|
19423
|
-
import { constants as constants17, closeSync as closeSync16, fstatSync as fstatSync16, fsyncSync as fsyncSync6, lstatSync as lstatSync27, mkdirSync as
|
|
19694
|
+
import { constants as constants17, closeSync as closeSync16, fstatSync as fstatSync16, fsyncSync as fsyncSync6, lstatSync as lstatSync27, mkdirSync as mkdirSync8, openSync as openSync16, readSync as readSync11, writeSync as writeSync4 } from "fs";
|
|
19424
19695
|
import { dirname as dirname21, isAbsolute as isAbsolute23, join as join30, resolve as resolve22, sep as sep13 } from "path";
|
|
19425
19696
|
var sha3 = (bytes) => createHash26("sha256").update(bytes).digest("hex");
|
|
19426
19697
|
var hex = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
|
|
@@ -19550,7 +19821,7 @@ function writeReviewArtifactExclusive(change) {
|
|
|
19550
19821
|
for (let parent = dirname21(change.path);!lstatSync27(parent, { throwIfNoEntry: false }); parent = dirname21(parent))
|
|
19551
19822
|
missing2.push(parent);
|
|
19552
19823
|
for (const parent of missing2.reverse())
|
|
19553
|
-
|
|
19824
|
+
mkdirSync8(parent, { mode: 448 });
|
|
19554
19825
|
safe4(change.path);
|
|
19555
19826
|
privateStore(change.artifact.storeRoot);
|
|
19556
19827
|
for (let parent = dirname21(change.path);parent !== change.artifact.storeRoot; parent = dirname21(parent)) {
|
|
@@ -19800,7 +20071,7 @@ function treeHash(root) {
|
|
|
19800
20071
|
const rel = relative9(root, path);
|
|
19801
20072
|
if (stat2.isDirectory()) {
|
|
19802
20073
|
hash3.update(`d\x00${rel}\x00`);
|
|
19803
|
-
for (const name of
|
|
20074
|
+
for (const name of readdirSync11(path).sort())
|
|
19804
20075
|
visit2(join31(path, name));
|
|
19805
20076
|
return;
|
|
19806
20077
|
}
|
|
@@ -20695,7 +20966,7 @@ function planClaudeHookEventsUpdate(options) {
|
|
|
20695
20966
|
}
|
|
20696
20967
|
function atomicWrite2(path, content) {
|
|
20697
20968
|
assertSafePath(path);
|
|
20698
|
-
|
|
20969
|
+
mkdirSync9(dirname22(path), { recursive: true, mode: 448 });
|
|
20699
20970
|
const temporary = `${path}.skills-${randomUUID4()}`;
|
|
20700
20971
|
try {
|
|
20701
20972
|
writeFileSync6(temporary, content, { mode: 384, flag: "wx" });
|
|
@@ -20863,7 +21134,7 @@ function planCodexSemanticCacheWitnessUpgrade(options) {
|
|
|
20863
21134
|
throw new Error("Local marketplace hook parent is not enabled in the unchanged Codex settings");
|
|
20864
21135
|
identity5 = { role: "reviewed-hook", pluginId: pluginId2, namespace: parts[1], pluginParent: parent, installation: "local-marketplace", marketplaceSourcePath: source.path, marketplaceSha256: source.sha256 };
|
|
20865
21136
|
}
|
|
20866
|
-
const versions =
|
|
21137
|
+
const versions = readdirSync11(parent).filter((name) => name !== ".codex-remote-plugin-install.json");
|
|
20867
21138
|
if (!versions.length || versions.length > 4096)
|
|
20868
21139
|
throw new Error("Reviewed native-hook parent has no bounded materializations");
|
|
20869
21140
|
for (const version2 of versions) {
|
|
@@ -20957,9 +21228,10 @@ function applyAgentIntegration(plan, options = {}) {
|
|
|
20957
21228
|
const alias = plan.rootAliases?.find((item) => item.agent === "codex" && (change.path === item.target || change.path.startsWith(item.target + "/")));
|
|
20958
21229
|
return lexical ? [lexical] : alias ? [alias.alias] : [];
|
|
20959
21230
|
});
|
|
20960
|
-
return withCodexCorpusWrite(roots, (assertCurrent) => applyAgentIntegrationUnlocked(plan, options, assertCurrent), options);
|
|
21231
|
+
return withCodexCorpusWrite(roots, (assertCurrent, admission) => applyAgentIntegrationUnlocked(plan, options, assertCurrent, admission), options);
|
|
20961
21232
|
}
|
|
20962
|
-
function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
21233
|
+
function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent, admission) {
|
|
21234
|
+
const fallback = codexAdmissionReceipt(admission);
|
|
20963
21235
|
for (const source of plan.reviewArtifactSources ?? [])
|
|
20964
21236
|
verifyReviewArtifactOriginal(source.path, source.sha256);
|
|
20965
21237
|
for (const source of plan.observedNativeSources ?? [])
|
|
@@ -21023,10 +21295,10 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
21023
21295
|
recheckRootAliases(aliases);
|
|
21024
21296
|
for (const agent of plan.retainedReviewChecks?.agents ?? [])
|
|
21025
21297
|
assertManagedAgentBridge(agent, { ...plan.retainedReviewChecks, dataDir: plan.dataDir });
|
|
21026
|
-
return { changed: [], backups, ...aliases.length ? { rootAliases: aliases } : {} };
|
|
21298
|
+
return { changed: [], backups, ...aliases.length ? { rootAliases: aliases } : {}, ...fallback };
|
|
21027
21299
|
}
|
|
21028
21300
|
assertSafePath(backupRoot);
|
|
21029
|
-
|
|
21301
|
+
mkdirSync9(backupRoot, { recursive: true, mode: 448 });
|
|
21030
21302
|
chmodSync(backupRoot, 448);
|
|
21031
21303
|
for (const [index, change] of plan.changes.entries())
|
|
21032
21304
|
if (change.before !== null) {
|
|
@@ -21074,7 +21346,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
21074
21346
|
assertManagedAgentBridge(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.projectDir ?? plan.managedAgentChecks.home });
|
|
21075
21347
|
for (const agent of plan.retainedReviewChecks?.agents ?? [])
|
|
21076
21348
|
assertManagedAgentBridge(agent, { ...plan.retainedReviewChecks, dataDir: plan.dataDir });
|
|
21077
|
-
atomicWrite2(join31(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha4(change.before), afterHash: sha4(change.after) })), backups, ...plan.cacheWitnessUpgrade ? { cacheWitnessUpgrade: plan.cacheWitnessUpgrade } : {}, ...plan.retainedReviewArtifacts?.length ? { retainedReviewArtifacts: plan.retainedReviewArtifacts.map((item) => ({ path: item.path, ...item.artifact })) } : {}, ...aliases.length ? { rootAliases: aliases } : {} }) + `
|
|
21349
|
+
atomicWrite2(join31(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha4(change.before), afterHash: sha4(change.after) })), backups, ...plan.cacheWitnessUpgrade ? { cacheWitnessUpgrade: plan.cacheWitnessUpgrade } : {}, ...plan.retainedReviewArtifacts?.length ? { retainedReviewArtifacts: plan.retainedReviewArtifacts.map((item) => ({ path: item.path, ...item.artifact })) } : {}, ...aliases.length ? { rootAliases: aliases } : {}, ...fallback }) + `
|
|
21078
21350
|
`);
|
|
21079
21351
|
} catch (error) {
|
|
21080
21352
|
assertCurrent();
|
|
@@ -21102,7 +21374,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
21102
21374
|
}
|
|
21103
21375
|
throw error;
|
|
21104
21376
|
}
|
|
21105
|
-
return { changed: plan.changes.map((change) => change.path), backups, ...aliases.length ? { rootAliases: aliases } : {} };
|
|
21377
|
+
return { changed: plan.changes.map((change) => change.path), backups, ...aliases.length ? { rootAliases: aliases } : {}, ...fallback };
|
|
21106
21378
|
}
|
|
21107
21379
|
function syncArchiveDirectory(path) {
|
|
21108
21380
|
assertSafePath(path);
|
|
@@ -21142,9 +21414,10 @@ function archiveNativeSkills(inventory, options) {
|
|
|
21142
21414
|
throw new Error("CODEX_CORPUS_ROOT_UNVERIFIED");
|
|
21143
21415
|
return [...new Set([root, owner2].filter((value) => value !== undefined))];
|
|
21144
21416
|
});
|
|
21145
|
-
return withCodexCorpusWrite(roots, (assertCurrent) => archiveNativeSkillsUnlocked(inventory, options, assertCurrent), options);
|
|
21417
|
+
return withCodexCorpusWrite(roots, (assertCurrent, admission) => archiveNativeSkillsUnlocked(inventory, options, assertCurrent, admission), options);
|
|
21146
21418
|
}
|
|
21147
|
-
function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
21419
|
+
function archiveNativeSkillsUnlocked(inventory, options, assertCurrent, admission) {
|
|
21420
|
+
const fallback = codexAdmissionReceipt(admission);
|
|
21148
21421
|
const aliases = [...new Map(inventory.filter((entry) => entry.rootAlias).map((entry) => [entry.rootAlias.alias, entry.rootAlias])).values()];
|
|
21149
21422
|
if (aliases.length && !options.allowRootAliases)
|
|
21150
21423
|
throw new Error("Native migration requires explicit allowRootAliases for agent root aliases");
|
|
@@ -21162,7 +21435,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
21162
21435
|
throw new Error(`Native skill changed after planning: ${entry.path}`);
|
|
21163
21436
|
const targetManifest = options.targetManifest ? { schema: options.targetManifest.schema, digest: options.targetManifest.digest, targetCount: options.targetManifest.targets.length } : undefined;
|
|
21164
21437
|
if (!selected.length)
|
|
21165
|
-
return { entries: [], ...targetManifest ? { targetManifest } : {}, ...aliases.length ? { rootAliases: aliases } : {} };
|
|
21438
|
+
return { entries: [], ...targetManifest ? { targetManifest } : {}, ...aliases.length ? { rootAliases: aliases } : {}, ...fallback };
|
|
21166
21439
|
const operationId = randomUUID4(), archiveRoot = join31(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join31(archiveRoot, "receipt.json");
|
|
21167
21440
|
const entries = selected.map((entry, index) => ({
|
|
21168
21441
|
source: entry.vendor ? join31(entry.path, "SKILL.md") : entry.path,
|
|
@@ -21171,7 +21444,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
21171
21444
|
...entry.vendor ? { discoveryOnly: true } : {},
|
|
21172
21445
|
status: "planned"
|
|
21173
21446
|
}));
|
|
21174
|
-
const journal = { version: 2, operationId, status: "planned", entries, ...targetManifest ? { targetManifest } : {}, ...aliases.length ? { rootAliases: aliases } : {} };
|
|
21447
|
+
const journal = { version: 2, operationId, status: "planned", entries, ...targetManifest ? { targetManifest } : {}, ...aliases.length ? { rootAliases: aliases } : {}, ...fallback };
|
|
21175
21448
|
const moved = [];
|
|
21176
21449
|
const verifyArchive = (entry) => {
|
|
21177
21450
|
assertSafePath(entry.archive);
|
|
@@ -21185,7 +21458,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
21185
21458
|
const created = [];
|
|
21186
21459
|
for (let path = archiveRoot;!existsSync9(path); path = dirname22(path))
|
|
21187
21460
|
created.push(path);
|
|
21188
|
-
|
|
21461
|
+
mkdirSync9(archiveRoot, { recursive: true, mode: 448 });
|
|
21189
21462
|
try {
|
|
21190
21463
|
for (const directory2 of created)
|
|
21191
21464
|
syncArchiveDirectory(directory2);
|
|
@@ -21268,7 +21541,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
21268
21541
|
} catch {}
|
|
21269
21542
|
throw new Error(`Native archive failed; inspect the recovery journal at ${receiptPath} before retrying.`, { cause: error });
|
|
21270
21543
|
}
|
|
21271
|
-
return { entries: entries.map(({ status, conflict, ...entry }) => entry), receiptPath, ...targetManifest ? { targetManifest } : {}, ...aliases.length ? { rootAliases: aliases } : {} };
|
|
21544
|
+
return { entries: entries.map(({ status, conflict, ...entry }) => entry), receiptPath, ...targetManifest ? { targetManifest } : {}, ...aliases.length ? { rootAliases: aliases } : {}, ...fallback };
|
|
21272
21545
|
}
|
|
21273
21546
|
function classifiedCodexPluginCacheCopy(entry, cache, read2, admit) {
|
|
21274
21547
|
try {
|
|
@@ -21716,7 +21989,7 @@ function packageSourceRoots(source) {
|
|
|
21716
21989
|
function containsSkillDirectories(path) {
|
|
21717
21990
|
let entries;
|
|
21718
21991
|
try {
|
|
21719
|
-
entries =
|
|
21992
|
+
entries = readdirSync12(path);
|
|
21720
21993
|
} catch {
|
|
21721
21994
|
return false;
|
|
21722
21995
|
}
|
|
@@ -21811,12 +22084,16 @@ function writeManagedAgentSkill(params) {
|
|
|
21811
22084
|
agent: params.agent,
|
|
21812
22085
|
path: result.path,
|
|
21813
22086
|
action: result.action,
|
|
21814
|
-
...result.reason ? { reason: result.reason } : {}
|
|
22087
|
+
...result.reason ? { reason: result.reason } : {},
|
|
22088
|
+
...result.nativeAdmission ? { nativeAdmission: result.nativeAdmission, nativeAdmissionProbe: result.nativeAdmissionProbe } : {}
|
|
21815
22089
|
};
|
|
21816
22090
|
}
|
|
21817
22091
|
function writeManagedSkillDir(dir, skillMd, options) {
|
|
21818
22092
|
const root = options.dryRun ? undefined : codexCorpusRootForPath(dir);
|
|
21819
|
-
return withCodexCorpusWrite(root ? [root] : [], (assertCurrent) =>
|
|
22093
|
+
return withCodexCorpusWrite(root ? [root] : [], (assertCurrent, admission) => {
|
|
22094
|
+
const result = writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent);
|
|
22095
|
+
return { ...result, ...codexAdmissionReceipt(admission) };
|
|
22096
|
+
}, options);
|
|
21820
22097
|
}
|
|
21821
22098
|
function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
21822
22099
|
const skillMdPath = join32(dir, "SKILL.md");
|
|
@@ -21857,8 +22134,8 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
|
21857
22134
|
if (options.dryRun)
|
|
21858
22135
|
return { action, path: skillMdPath };
|
|
21859
22136
|
const parentDir = dirname23(dir);
|
|
21860
|
-
|
|
21861
|
-
const transactionDir =
|
|
22137
|
+
mkdirSync10(parentDir, { recursive: true });
|
|
22138
|
+
const transactionDir = mkdtempSync2(join32(parentDir, `.hasna-skills-write-${basename12(dir)}-`));
|
|
21862
22139
|
const candidateDir = join32(transactionDir, "candidate");
|
|
21863
22140
|
const backupDir = join32(transactionDir, "backup");
|
|
21864
22141
|
const candidateSkillMdPath = join32(candidateDir, "SKILL.md");
|
|
@@ -21876,7 +22153,7 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
|
21876
22153
|
if (options.resourceDir) {
|
|
21877
22154
|
cpSync2(options.resourceDir, candidateDir, { recursive: true, force: true });
|
|
21878
22155
|
} else {
|
|
21879
|
-
|
|
22156
|
+
mkdirSync10(candidateDir, { recursive: true });
|
|
21880
22157
|
}
|
|
21881
22158
|
writeFileSync7(candidateSkillMdPath, skillMd.endsWith(`
|
|
21882
22159
|
`) ? skillMd : `${skillMd}
|
|
@@ -21900,7 +22177,7 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
|
21900
22177
|
try {
|
|
21901
22178
|
assertCurrent();
|
|
21902
22179
|
if (existsSync10(dir))
|
|
21903
|
-
|
|
22180
|
+
rmSync3(dir, { recursive: true, force: true });
|
|
21904
22181
|
renameDirectory(backupDir, dir);
|
|
21905
22182
|
originalMoved = false;
|
|
21906
22183
|
} catch (rollbackError) {
|
|
@@ -21913,22 +22190,26 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
|
21913
22190
|
if (!preserveTransaction) {
|
|
21914
22191
|
try {
|
|
21915
22192
|
assertCurrent();
|
|
21916
|
-
|
|
22193
|
+
rmSync3(transactionDir, { recursive: true, force: true });
|
|
21917
22194
|
} catch {}
|
|
21918
22195
|
}
|
|
21919
22196
|
}
|
|
21920
22197
|
return { action, path: skillMdPath };
|
|
21921
22198
|
}
|
|
21922
22199
|
function removeManagedAgentSkill(skill, agent, homeDir2 = homedir3(), options = {}) {
|
|
22200
|
+
const record5 = codexAdmissionRecord(options);
|
|
21923
22201
|
const dir = join32(agentGlobalSkillsDir(agent, homeDir2), skill);
|
|
21924
22202
|
const root = codexCorpusRootForPath(dir);
|
|
21925
|
-
return withCodexCorpusWrite(root ? [root] : [], () =>
|
|
22203
|
+
return withCodexCorpusWrite(root ? [root] : [], (_assertCurrent, admission) => {
|
|
22204
|
+
record5.deliver(admission);
|
|
22205
|
+
return removeManagedAgentSkillUnlocked(skill, agent, homeDir2, options);
|
|
22206
|
+
}, options, record5.policy);
|
|
21926
22207
|
}
|
|
21927
22208
|
function removeManagedAgentSkillUnlocked(skill, agent, homeDir2 = homedir3(), options = {}) {
|
|
21928
22209
|
const dir = join32(agentGlobalSkillsDir(agent, homeDir2), skill);
|
|
21929
22210
|
if (!hasSkillsOwnershipMarker(dir))
|
|
21930
22211
|
return false;
|
|
21931
|
-
|
|
22212
|
+
rmSync3(dir, { recursive: true, force: true });
|
|
21932
22213
|
return true;
|
|
21933
22214
|
}
|
|
21934
22215
|
function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = false) {
|
|
@@ -21975,7 +22256,7 @@ function resolveSkillAlias(name) {
|
|
|
21975
22256
|
}
|
|
21976
22257
|
|
|
21977
22258
|
// src/lib/project-state.ts
|
|
21978
|
-
import { existsSync as existsSync11, mkdirSync as
|
|
22259
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync11, readFileSync as readFileSync21, writeFileSync as writeFileSync8 } from "fs";
|
|
21979
22260
|
import { join as join33 } from "path";
|
|
21980
22261
|
var VALID_PIN_SOURCES = [
|
|
21981
22262
|
"official",
|
|
@@ -22022,7 +22303,7 @@ function ensureProjectConfig(targetDir = process.cwd()) {
|
|
|
22022
22303
|
}
|
|
22023
22304
|
function saveProjectConfig(config, targetDir = process.cwd()) {
|
|
22024
22305
|
const dir = getProjectStateDir(targetDir);
|
|
22025
|
-
|
|
22306
|
+
mkdirSync11(dir, { recursive: true });
|
|
22026
22307
|
const normalized2 = normalizeProjectConfig({ ...config, updatedAt: new Date().toISOString() });
|
|
22027
22308
|
writeFileSync8(getProjectConfigPath(targetDir), JSON.stringify(normalized2, null, 2) + `
|
|
22028
22309
|
`);
|
|
@@ -22291,15 +22572,20 @@ function installSkillForAgent(name, options, generateSkillMd) {
|
|
|
22291
22572
|
codexCommand: options.codexCommand,
|
|
22292
22573
|
codexSha256: options.codexSha256
|
|
22293
22574
|
});
|
|
22575
|
+
const fallback = result.nativeAdmission ? { nativeAdmission: result.nativeAdmission, nativeAdmissionProbe: result.nativeAdmissionProbe } : {};
|
|
22294
22576
|
if (result.action === "skip") {
|
|
22295
|
-
return { skill: canonicalName, success: false, error: result.reason ?? "skipped", path: result.path };
|
|
22577
|
+
return { skill: canonicalName, success: false, error: result.reason ?? "skipped", path: result.path, ...fallback };
|
|
22296
22578
|
}
|
|
22297
|
-
return { skill: canonicalName, success: true, path: result.path };
|
|
22579
|
+
return { skill: canonicalName, success: true, path: result.path, ...fallback };
|
|
22298
22580
|
}
|
|
22299
22581
|
function removeSkillForAgent(name, options) {
|
|
22582
|
+
const record5 = codexAdmissionRecord(options);
|
|
22300
22583
|
const dir = getAgentSkillPath(name, options.agent, options.scope ?? "global", options.projectDir);
|
|
22301
22584
|
const root = codexCorpusRootForPath(dir);
|
|
22302
|
-
return withCodexCorpusWrite(root ? [root] : [], () =>
|
|
22585
|
+
return withCodexCorpusWrite(root ? [root] : [], (_assertCurrent, admission) => {
|
|
22586
|
+
record5.deliver(admission);
|
|
22587
|
+
return removeSkillForAgentUnlocked(name, options);
|
|
22588
|
+
}, options, record5.policy);
|
|
22303
22589
|
}
|
|
22304
22590
|
function removeSkillForAgentUnlocked(name, options) {
|
|
22305
22591
|
const canonicalName = getCanonicalSkillName(name);
|
|
@@ -22307,7 +22593,7 @@ function removeSkillForAgentUnlocked(name, options) {
|
|
|
22307
22593
|
const dir = getAgentSkillPath(canonicalName, options.agent, scope, options.projectDir);
|
|
22308
22594
|
if (!hasSkillsOwnershipMarker(dir))
|
|
22309
22595
|
return false;
|
|
22310
|
-
|
|
22596
|
+
rmSync4(dir, { recursive: true, force: true });
|
|
22311
22597
|
return true;
|
|
22312
22598
|
}
|
|
22313
22599
|
function resolveAgentSkillMd(name, generateSkillMd) {
|
|
@@ -22727,6 +23013,115 @@ function readIfExists(path) {
|
|
|
22727
23013
|
return null;
|
|
22728
23014
|
}
|
|
22729
23015
|
|
|
23016
|
+
// src/lib/search.ts
|
|
23017
|
+
function editDistance(a, b) {
|
|
23018
|
+
if (a === b)
|
|
23019
|
+
return 0;
|
|
23020
|
+
if (a.length === 0)
|
|
23021
|
+
return b.length;
|
|
23022
|
+
if (b.length === 0)
|
|
23023
|
+
return a.length;
|
|
23024
|
+
const prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
23025
|
+
const curr = new Array(b.length + 1);
|
|
23026
|
+
for (let i = 1;i <= a.length; i++) {
|
|
23027
|
+
curr[0] = i;
|
|
23028
|
+
for (let j = 1;j <= b.length; j++) {
|
|
23029
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
23030
|
+
curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);
|
|
23031
|
+
}
|
|
23032
|
+
prev.splice(0, prev.length, ...curr);
|
|
23033
|
+
}
|
|
23034
|
+
return prev[b.length];
|
|
23035
|
+
}
|
|
23036
|
+
function fuzzyMatchScore(word, target) {
|
|
23037
|
+
if (target.includes(word))
|
|
23038
|
+
return 1;
|
|
23039
|
+
const tokens = target.split(/[\s\-_]+/).filter(Boolean);
|
|
23040
|
+
for (const token of tokens) {
|
|
23041
|
+
if (token.startsWith(word))
|
|
23042
|
+
return 0.6;
|
|
23043
|
+
}
|
|
23044
|
+
if (word.length >= 3) {
|
|
23045
|
+
const maxDist = word.length <= 3 ? 1 : 2;
|
|
23046
|
+
for (const token of tokens) {
|
|
23047
|
+
if (Math.abs(token.length - word.length) <= maxDist) {
|
|
23048
|
+
const dist = editDistance(word, token);
|
|
23049
|
+
if (dist <= maxDist)
|
|
23050
|
+
return 0.4;
|
|
23051
|
+
}
|
|
23052
|
+
}
|
|
23053
|
+
}
|
|
23054
|
+
return 0;
|
|
23055
|
+
}
|
|
23056
|
+
function searchSkills(query, registry = loadRegistry()) {
|
|
23057
|
+
const words = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
23058
|
+
if (words.length === 0)
|
|
23059
|
+
return [];
|
|
23060
|
+
const scored = [];
|
|
23061
|
+
for (const skill of registry) {
|
|
23062
|
+
const nameLower = skill.name.toLowerCase();
|
|
23063
|
+
const displayNameLower = skill.displayName.toLowerCase();
|
|
23064
|
+
const descriptionLower = skill.description.toLowerCase();
|
|
23065
|
+
const tagsLower = skill.tags.map((t2) => t2.toLowerCase());
|
|
23066
|
+
const tagsCombined = tagsLower.join(" ");
|
|
23067
|
+
let score = 0;
|
|
23068
|
+
let allWordsMatch = true;
|
|
23069
|
+
for (const word of words) {
|
|
23070
|
+
let wordScore = 0;
|
|
23071
|
+
const nameMatch = fuzzyMatchScore(word, nameLower);
|
|
23072
|
+
if (nameMatch > 0)
|
|
23073
|
+
wordScore += 10 * nameMatch;
|
|
23074
|
+
const displayMatch = fuzzyMatchScore(word, displayNameLower);
|
|
23075
|
+
if (displayMatch > 0)
|
|
23076
|
+
wordScore += 7 * displayMatch;
|
|
23077
|
+
const tagMatch = Math.max(...tagsLower.map((t2) => fuzzyMatchScore(word, t2)), fuzzyMatchScore(word, tagsCombined));
|
|
23078
|
+
if (tagMatch > 0)
|
|
23079
|
+
wordScore += 5 * tagMatch;
|
|
23080
|
+
const descMatch = fuzzyMatchScore(word, descriptionLower);
|
|
23081
|
+
if (descMatch > 0)
|
|
23082
|
+
wordScore += 2 * descMatch;
|
|
23083
|
+
if (wordScore === 0) {
|
|
23084
|
+
allWordsMatch = false;
|
|
23085
|
+
break;
|
|
23086
|
+
}
|
|
23087
|
+
score += wordScore;
|
|
23088
|
+
}
|
|
23089
|
+
if (allWordsMatch && score > 0) {
|
|
23090
|
+
scored.push({ skill, score });
|
|
23091
|
+
}
|
|
23092
|
+
}
|
|
23093
|
+
scored.sort((a, b) => b.score - a.score);
|
|
23094
|
+
return scored.map((s) => s.skill);
|
|
23095
|
+
}
|
|
23096
|
+
function findCloseSkillNames(query, names, maxResults = 3) {
|
|
23097
|
+
if (maxResults <= 0)
|
|
23098
|
+
return [];
|
|
23099
|
+
const q = query.trim().toLowerCase();
|
|
23100
|
+
if (q.length === 0)
|
|
23101
|
+
return [];
|
|
23102
|
+
const tokens = q.split("-").filter(Boolean);
|
|
23103
|
+
const ranked = [];
|
|
23104
|
+
if (q.length >= 3) {
|
|
23105
|
+
for (const name of names) {
|
|
23106
|
+
const candidate = name.toLowerCase();
|
|
23107
|
+
const rank = candidate === q ? 0 : candidate.endsWith(`-${q}`) || candidate.startsWith(`${q}-`) ? 1 : tokens.length > 1 && tokens.every((token) => candidate.split("-").includes(token)) ? 2 : undefined;
|
|
23108
|
+
if (rank !== undefined)
|
|
23109
|
+
ranked.push([name, rank]);
|
|
23110
|
+
}
|
|
23111
|
+
}
|
|
23112
|
+
ranked.sort((a, b) => a[1] - b[1] || a[0].length - b[0].length || a[0].localeCompare(b[0]));
|
|
23113
|
+
const found = ranked.slice(0, maxResults).map(([name]) => name);
|
|
23114
|
+
if (found.length === maxResults)
|
|
23115
|
+
return found;
|
|
23116
|
+
const taken = new Set(found);
|
|
23117
|
+
const threshold = Math.max(3, Math.floor(q.length / 2));
|
|
23118
|
+
const byDistance = names.filter((name) => !taken.has(name)).map((name) => ({ name, distance: editDistance(q, name.toLowerCase()) })).filter((entry) => entry.distance <= threshold).sort((a, b) => a.distance - b.distance || a.name.localeCompare(b.name));
|
|
23119
|
+
return [...found, ...byDistance.slice(0, maxResults - found.length).map((entry) => entry.name)];
|
|
23120
|
+
}
|
|
23121
|
+
function findSimilarSkills(query, maxResults = 3, registry = loadRegistry()) {
|
|
23122
|
+
return findCloseSkillNames(query, registry.map((skill) => skill.name), maxResults);
|
|
23123
|
+
}
|
|
23124
|
+
|
|
22730
23125
|
// src/lib/selected-document.ts
|
|
22731
23126
|
var DOCUMENT_PATHS = ["SKILL.md", "README.md", "CLAUDE.md"];
|
|
22732
23127
|
function readSelectedDocument(entries, file) {
|
|
@@ -22843,11 +23238,31 @@ function exactProfileSelection(spec, profile) {
|
|
|
22843
23238
|
const at = spec.lastIndexOf("@");
|
|
22844
23239
|
const slug = at > 0 ? spec.slice(0, at) : spec;
|
|
22845
23240
|
const version2 = at > 0 ? spec.slice(at + 1) : undefined;
|
|
22846
|
-
const
|
|
22847
|
-
if (
|
|
22848
|
-
throw new SkillSelectionError("SKILL_NOT_SELECTED",
|
|
23241
|
+
const named = profile.selections.filter((entry) => entry.slug === slug || entry.aliases?.includes(slug));
|
|
23242
|
+
if (version2 === "")
|
|
23243
|
+
throw new SkillSelectionError("SKILL_NOT_SELECTED", emptyVersionRefusal(spec));
|
|
23244
|
+
if (named.length === 0)
|
|
23245
|
+
throw new SkillSelectionError("SKILL_NOT_SELECTED", unknownNameRefusal(slug, profile));
|
|
23246
|
+
const selection = version2 === undefined ? named[0] : named.find((entry) => entry.version === version2);
|
|
23247
|
+
if (!selection)
|
|
23248
|
+
throw new SkillSelectionError("SKILL_NOT_SELECTED", wrongVersionRefusal(slug, version2, named));
|
|
22849
23249
|
return selection;
|
|
22850
23250
|
}
|
|
23251
|
+
var ACCEPTED_FORM = "Accepted form: '<slug>' or '<slug>@<version>'.";
|
|
23252
|
+
function emptyVersionRefusal(spec) {
|
|
23253
|
+
return `The requested name '${spec}' has an empty version. ${ACCEPTED_FORM}`;
|
|
23254
|
+
}
|
|
23255
|
+
function wrongVersionRefusal(slug, version2, named) {
|
|
23256
|
+
const versions = [...new Set(named.map((entry) => entry.version))].sort();
|
|
23257
|
+
const canonical9 = named[0].slug;
|
|
23258
|
+
return `Skill '${slug}' is selected at version '${versions.join("', '")}', but '${version2}' was requested. ` + `Accepted form: '${canonical9}@${versions[0]}'.`;
|
|
23259
|
+
}
|
|
23260
|
+
function unknownNameRefusal(slug, profile) {
|
|
23261
|
+
const names = profile.selections.flatMap((entry) => [entry.slug, ...entry.aliases ?? []]);
|
|
23262
|
+
const close = findCloseSkillNames(slug, names);
|
|
23263
|
+
const hint = close.length > 0 ? ` Did you mean: ${close.join(", ")}?` : "";
|
|
23264
|
+
return `Skill '${slug}' is not selected by this Skills profile or project lock.${hint} ` + `Read the accepted names with 'skills search <term>' or 'skills list --all --json'; accept one with 'skills pin <name>'. ${ACCEPTED_FORM}`;
|
|
23265
|
+
}
|
|
22851
23266
|
|
|
22852
23267
|
// src/lib/selected-manifest.ts
|
|
22853
23268
|
function jsonEntry(entries, path) {
|
|
@@ -24336,13 +24751,13 @@ function assertProjectDiscovery(agent, directories, home, canonical9 = resolve27
|
|
|
24336
24751
|
for (const name of ["plugin", "plugins"]) {
|
|
24337
24752
|
const path = canonical9(join38(directory2, ".sumi", name));
|
|
24338
24753
|
safe6(path);
|
|
24339
|
-
if (lstatSync32(path, { throwIfNoEntry: false })?.isDirectory() &&
|
|
24754
|
+
if (lstatSync32(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync13(path).length)
|
|
24340
24755
|
throw new Error(`NATIVE_SKILL_DRIFT: project Sumi plugins require a dedicated discovery review: ${path}`);
|
|
24341
24756
|
}
|
|
24342
24757
|
if (agent === "claude") {
|
|
24343
24758
|
const commands = canonical9(join38(directory2, ".claude/commands"));
|
|
24344
24759
|
safe6(commands);
|
|
24345
|
-
if (lstatSync32(commands, { throwIfNoEntry: false })?.isDirectory() &&
|
|
24760
|
+
if (lstatSync32(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync13(commands).length)
|
|
24346
24761
|
throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
|
|
24347
24762
|
}
|
|
24348
24763
|
}
|
|
@@ -24491,7 +24906,7 @@ function resolveAgentDiscovery(options) {
|
|
|
24491
24906
|
for (const path of plugins) {
|
|
24492
24907
|
safe6(path);
|
|
24493
24908
|
if (lstatSync32(path, { throwIfNoEntry: false })?.isDirectory())
|
|
24494
|
-
for (const name of
|
|
24909
|
+
for (const name of readdirSync13(path).sort()) {
|
|
24495
24910
|
if (name === "skills-cli.js" && path === plugins[1])
|
|
24496
24911
|
continue;
|
|
24497
24912
|
const target = join38(path, name);
|
|
@@ -24502,7 +24917,7 @@ function resolveAgentDiscovery(options) {
|
|
|
24502
24917
|
}
|
|
24503
24918
|
for (const root2 of roots) {
|
|
24504
24919
|
safe6(root2);
|
|
24505
|
-
if (lstatSync32(root2, { throwIfNoEntry: false })?.isDirectory() &&
|
|
24920
|
+
if (lstatSync32(root2, { throwIfNoEntry: false })?.isDirectory() && readdirSync13(root2).some((name) => name.endsWith(".md")))
|
|
24506
24921
|
unresolved("flat markdown skills require a dedicated native migration adapter");
|
|
24507
24922
|
}
|
|
24508
24923
|
}
|
|
@@ -24546,7 +24961,7 @@ function resolveAgentDiscovery(options) {
|
|
|
24546
24961
|
safe6(builtinRoot);
|
|
24547
24962
|
if (!lstatSync32(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
|
|
24548
24963
|
unresolved("installed Gemini builtin root is missing");
|
|
24549
|
-
for (const name of
|
|
24964
|
+
for (const name of readdirSync13(builtinRoot).sort()) {
|
|
24550
24965
|
const text2 = witness(join38(builtinRoot, name, "SKILL.md"));
|
|
24551
24966
|
const match = text2?.match(/^---\r?\n[\s\S]*?^name:\s*([a-z0-9][a-z0-9-]*)\s*$/m);
|
|
24552
24967
|
if (!match?.[1] || builtinNames.includes(match[1]))
|
|
@@ -24644,7 +25059,7 @@ function resolveAgentDiscovery(options) {
|
|
|
24644
25059
|
unresolved("plugin hooks require a separate no-skill-injection review");
|
|
24645
25060
|
const commands = join38(root2, "commands");
|
|
24646
25061
|
safe6(commands);
|
|
24647
|
-
if (agent === "claude" && (manifest.commands !== undefined || lstatSync32(commands, { throwIfNoEntry: false })?.isDirectory() &&
|
|
25062
|
+
if (agent === "claude" && (manifest.commands !== undefined || lstatSync32(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync13(commands).length))
|
|
24648
25063
|
unresolved("legacy command discovery requires retirement or a dedicated format adapter");
|
|
24649
25064
|
const rootSkill = witness(join38(root2, "SKILL.md"));
|
|
24650
25065
|
if (rootSkill !== null)
|
|
@@ -24666,7 +25081,7 @@ function resolveAgentDiscovery(options) {
|
|
|
24666
25081
|
const installed = registrations === null ? {} : parseConfig(registrations, join38(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
24667
25082
|
const commands = canonical9(join38(home, ".claude/commands"));
|
|
24668
25083
|
safe6(commands);
|
|
24669
|
-
if (lstatSync32(commands, { throwIfNoEntry: false })?.isDirectory() &&
|
|
25084
|
+
if (lstatSync32(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync13(commands).length)
|
|
24670
25085
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
24671
25086
|
for (const [id, enabled] of Object.entries(config.enabledPlugins ?? {})) {
|
|
24672
25087
|
if (enabled === false)
|
|
@@ -24708,7 +25123,7 @@ function resolveAgentDiscovery(options) {
|
|
|
24708
25123
|
}
|
|
24709
25124
|
const localPlugins = join38(home, ".config/opencode/plugins");
|
|
24710
25125
|
safe6(localPlugins);
|
|
24711
|
-
if (lstatSync32(localPlugins, { throwIfNoEntry: false }) &&
|
|
25126
|
+
if (lstatSync32(localPlugins, { throwIfNoEntry: false }) && readdirSync13(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
24712
25127
|
unresolved("additional local plugin hooks require review");
|
|
24713
25128
|
} else if (agent === "sumi") {
|
|
24714
25129
|
if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical9(configPath) && source.path !== canonical9(join38(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
|
|
@@ -24727,7 +25142,7 @@ function resolveAgentDiscovery(options) {
|
|
|
24727
25142
|
const directory2 = join38(home, ".gemini/extensions");
|
|
24728
25143
|
safe6(directory2);
|
|
24729
25144
|
if (lstatSync32(directory2, { throwIfNoEntry: false }))
|
|
24730
|
-
for (const name of
|
|
25145
|
+
for (const name of readdirSync13(directory2)) {
|
|
24731
25146
|
const root2 = join38(directory2, name);
|
|
24732
25147
|
safe6(root2);
|
|
24733
25148
|
if (!lstatSync32(root2)?.isDirectory())
|
|
@@ -24772,7 +25187,7 @@ function physicalPath(path) {
|
|
|
24772
25187
|
}
|
|
24773
25188
|
return resolve28(realpathSync14(cursor), ...suffix);
|
|
24774
25189
|
}
|
|
24775
|
-
function
|
|
25190
|
+
function contains2(root2, path) {
|
|
24776
25191
|
return path === root2 || path.startsWith(root2 + sep16);
|
|
24777
25192
|
}
|
|
24778
25193
|
function configuredRoots(home, explicitHome) {
|
|
@@ -24825,14 +25240,14 @@ function assertPortableAuthoringPath(path, options = {}) {
|
|
|
24825
25240
|
const defaults = NATIVE_DISCOVERY_ROOTS.map((parts) => join39(home, ...parts));
|
|
24826
25241
|
defaults.push(join39(home, ".codex/plugins/cache"), join39(home, ".claude/plugins/cache"), join39(home, ".claude/plugins/synced"), join39(home, ".gemini/extensions"));
|
|
24827
25242
|
for (const root2 of defaults) {
|
|
24828
|
-
if (candidates.some((candidate2) =>
|
|
25243
|
+
if (candidates.some((candidate2) => contains2(resolve28(root2), candidate2) || contains2(physicalPath(root2), candidate2)))
|
|
24829
25244
|
native ??= root2;
|
|
24830
25245
|
}
|
|
24831
25246
|
if (native) {
|
|
24832
25247
|
throw new Error(`Refusing portable Skills authoring below native discovery root '${native}': ${lexical}. Set HASNA_SKILLS_DIR to a private authoring corpus outside native roots.`);
|
|
24833
25248
|
}
|
|
24834
25249
|
for (const root2 of configuredRoots(home, options.homeDir !== undefined)) {
|
|
24835
|
-
if (candidates.some((candidate2) =>
|
|
25250
|
+
if (candidates.some((candidate2) => contains2(resolve28(root2), candidate2) || contains2(physicalPath(root2), candidate2))) {
|
|
24836
25251
|
throw new Error(`Refusing portable Skills authoring below configured native discovery root: ${lexical}`);
|
|
24837
25252
|
}
|
|
24838
25253
|
}
|
|
@@ -24875,7 +25290,7 @@ function listPortableSkills(options = {}) {
|
|
|
24875
25290
|
if (!safeIsDirectory(root2))
|
|
24876
25291
|
return [];
|
|
24877
25292
|
const skills = [];
|
|
24878
|
-
for (const entry of
|
|
25293
|
+
for (const entry of readdirSync14(root2).sort()) {
|
|
24879
25294
|
if (entry.startsWith("."))
|
|
24880
25295
|
continue;
|
|
24881
25296
|
const path = join40(root2, entry);
|
|
@@ -24919,7 +25334,7 @@ function scaffoldPortableSkill(name, options = {}) {
|
|
|
24919
25334
|
if (existsSync14(skillPath)) {
|
|
24920
25335
|
if (!options.overwrite)
|
|
24921
25336
|
throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
|
|
24922
|
-
|
|
25337
|
+
rmSync5(skillPath, { recursive: true, force: true });
|
|
24923
25338
|
}
|
|
24924
25339
|
const kind = options.kind ?? "executable";
|
|
24925
25340
|
const description = options.description ?? `${displayName(skillName)} skill`;
|
|
@@ -24946,7 +25361,7 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
|
|
|
24946
25361
|
};
|
|
24947
25362
|
const imported = [];
|
|
24948
25363
|
const skipped = [];
|
|
24949
|
-
const entries =
|
|
25364
|
+
const entries = readdirSync14(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
|
|
24950
25365
|
for (const entryName of entries) {
|
|
24951
25366
|
const childPath = join40(absoluteSource, entryName);
|
|
24952
25367
|
if (!safeIsDirectory(childPath))
|
|
@@ -24991,11 +25406,11 @@ function physicalImportPath(path) {
|
|
|
24991
25406
|
function assertDisjointImportPaths(source, destination) {
|
|
24992
25407
|
const sourcePath = realpathSync15(source);
|
|
24993
25408
|
const destinationPath = physicalImportPath(destination);
|
|
24994
|
-
const
|
|
25409
|
+
const contains3 = (parent, child2) => {
|
|
24995
25410
|
const path = relative11(parent, child2);
|
|
24996
25411
|
return path === "" || !isAbsolute29(path) && path !== ".." && !path.startsWith(`..${sep17}`);
|
|
24997
25412
|
};
|
|
24998
|
-
if (
|
|
25413
|
+
if (contains3(sourcePath, destinationPath) || contains3(destinationPath, sourcePath)) {
|
|
24999
25414
|
throw new Error("Source and destination skill directories must not overlap");
|
|
25000
25415
|
}
|
|
25001
25416
|
}
|
|
@@ -25022,9 +25437,9 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
25022
25437
|
if (existsSync14(destination)) {
|
|
25023
25438
|
if (!options.overwrite)
|
|
25024
25439
|
throw new Error(`Skill '${skillName}' already exists at ${destination}`);
|
|
25025
|
-
|
|
25440
|
+
rmSync5(destination, { recursive: true, force: true });
|
|
25026
25441
|
}
|
|
25027
|
-
|
|
25442
|
+
mkdirSync12(dirname28(destination), { recursive: true });
|
|
25028
25443
|
copySkillDirectory(absoluteSource, destination);
|
|
25029
25444
|
const base = {
|
|
25030
25445
|
...inferred,
|
|
@@ -25066,7 +25481,7 @@ function writeCorpusSkill(input, options = {}) {
|
|
|
25066
25481
|
const skillPath = join40(root2, name);
|
|
25067
25482
|
assertPortableAuthoringPath(skillPath, options);
|
|
25068
25483
|
const created = !existsSync14(skillPath);
|
|
25069
|
-
|
|
25484
|
+
mkdirSync12(skillPath, { recursive: true });
|
|
25070
25485
|
writeFileSync9(join40(skillPath, "SKILL.md"), input.skillMd);
|
|
25071
25486
|
const manifest = buildCorpusManifest(input, name);
|
|
25072
25487
|
writeSkillJsonWithHash(skillPath, manifest);
|
|
@@ -25080,8 +25495,8 @@ function installCorpusSkillAtomically(input, options = {}) {
|
|
|
25080
25495
|
const target = join40(root2, name);
|
|
25081
25496
|
assertPortableAuthoringPath(target, options);
|
|
25082
25497
|
const created = !existsSync14(target);
|
|
25083
|
-
|
|
25084
|
-
const staging =
|
|
25498
|
+
mkdirSync12(root2, { recursive: true });
|
|
25499
|
+
const staging = mkdtempSync3(join40(root2, `.pull-${name}-`));
|
|
25085
25500
|
let moved = false;
|
|
25086
25501
|
let backup = null;
|
|
25087
25502
|
try {
|
|
@@ -25089,16 +25504,16 @@ function installCorpusSkillAtomically(input, options = {}) {
|
|
|
25089
25504
|
const manifest = buildCorpusManifest(input, name);
|
|
25090
25505
|
writeSkillJsonWithHash(staging, manifest);
|
|
25091
25506
|
if (existsSync14(target)) {
|
|
25092
|
-
backup =
|
|
25507
|
+
backup = mkdtempSync3(join40(root2, `.pull-backup-${name}-`));
|
|
25093
25508
|
renameSync6(target, join40(backup, name));
|
|
25094
25509
|
moved = true;
|
|
25095
25510
|
}
|
|
25096
25511
|
renameSync6(staging, target);
|
|
25097
25512
|
if (moved && backup)
|
|
25098
|
-
|
|
25513
|
+
rmSync5(backup, { recursive: true, force: true });
|
|
25099
25514
|
return { name, path: target, manifest, created };
|
|
25100
25515
|
} catch (error) {
|
|
25101
|
-
|
|
25516
|
+
rmSync5(staging, { recursive: true, force: true });
|
|
25102
25517
|
if (moved && backup && existsSync14(join40(backup, name))) {
|
|
25103
25518
|
try {
|
|
25104
25519
|
renameSync6(join40(backup, name), target);
|
|
@@ -25354,92 +25769,6 @@ var CATEGORIES = [
|
|
|
25354
25769
|
"Event Management"
|
|
25355
25770
|
];
|
|
25356
25771
|
var BASIC_SKILL_NAMES = [];
|
|
25357
|
-
|
|
25358
|
-
// src/lib/search.ts
|
|
25359
|
-
function editDistance(a, b) {
|
|
25360
|
-
if (a === b)
|
|
25361
|
-
return 0;
|
|
25362
|
-
if (a.length === 0)
|
|
25363
|
-
return b.length;
|
|
25364
|
-
if (b.length === 0)
|
|
25365
|
-
return a.length;
|
|
25366
|
-
const prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
25367
|
-
const curr = new Array(b.length + 1);
|
|
25368
|
-
for (let i = 1;i <= a.length; i++) {
|
|
25369
|
-
curr[0] = i;
|
|
25370
|
-
for (let j = 1;j <= b.length; j++) {
|
|
25371
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
25372
|
-
curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);
|
|
25373
|
-
}
|
|
25374
|
-
prev.splice(0, prev.length, ...curr);
|
|
25375
|
-
}
|
|
25376
|
-
return prev[b.length];
|
|
25377
|
-
}
|
|
25378
|
-
function fuzzyMatchScore(word, target) {
|
|
25379
|
-
if (target.includes(word))
|
|
25380
|
-
return 1;
|
|
25381
|
-
const tokens = target.split(/[\s\-_]+/).filter(Boolean);
|
|
25382
|
-
for (const token of tokens) {
|
|
25383
|
-
if (token.startsWith(word))
|
|
25384
|
-
return 0.6;
|
|
25385
|
-
}
|
|
25386
|
-
if (word.length >= 3) {
|
|
25387
|
-
const maxDist = word.length <= 3 ? 1 : 2;
|
|
25388
|
-
for (const token of tokens) {
|
|
25389
|
-
if (Math.abs(token.length - word.length) <= maxDist) {
|
|
25390
|
-
const dist = editDistance(word, token);
|
|
25391
|
-
if (dist <= maxDist)
|
|
25392
|
-
return 0.4;
|
|
25393
|
-
}
|
|
25394
|
-
}
|
|
25395
|
-
}
|
|
25396
|
-
return 0;
|
|
25397
|
-
}
|
|
25398
|
-
function searchSkills(query, registry = loadRegistry()) {
|
|
25399
|
-
const words = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
25400
|
-
if (words.length === 0)
|
|
25401
|
-
return [];
|
|
25402
|
-
const scored = [];
|
|
25403
|
-
for (const skill of registry) {
|
|
25404
|
-
const nameLower = skill.name.toLowerCase();
|
|
25405
|
-
const displayNameLower = skill.displayName.toLowerCase();
|
|
25406
|
-
const descriptionLower = skill.description.toLowerCase();
|
|
25407
|
-
const tagsLower = skill.tags.map((t2) => t2.toLowerCase());
|
|
25408
|
-
const tagsCombined = tagsLower.join(" ");
|
|
25409
|
-
let score = 0;
|
|
25410
|
-
let allWordsMatch = true;
|
|
25411
|
-
for (const word of words) {
|
|
25412
|
-
let wordScore = 0;
|
|
25413
|
-
const nameMatch = fuzzyMatchScore(word, nameLower);
|
|
25414
|
-
if (nameMatch > 0)
|
|
25415
|
-
wordScore += 10 * nameMatch;
|
|
25416
|
-
const displayMatch = fuzzyMatchScore(word, displayNameLower);
|
|
25417
|
-
if (displayMatch > 0)
|
|
25418
|
-
wordScore += 7 * displayMatch;
|
|
25419
|
-
const tagMatch = Math.max(...tagsLower.map((t2) => fuzzyMatchScore(word, t2)), fuzzyMatchScore(word, tagsCombined));
|
|
25420
|
-
if (tagMatch > 0)
|
|
25421
|
-
wordScore += 5 * tagMatch;
|
|
25422
|
-
const descMatch = fuzzyMatchScore(word, descriptionLower);
|
|
25423
|
-
if (descMatch > 0)
|
|
25424
|
-
wordScore += 2 * descMatch;
|
|
25425
|
-
if (wordScore === 0) {
|
|
25426
|
-
allWordsMatch = false;
|
|
25427
|
-
break;
|
|
25428
|
-
}
|
|
25429
|
-
score += wordScore;
|
|
25430
|
-
}
|
|
25431
|
-
if (allWordsMatch && score > 0) {
|
|
25432
|
-
scored.push({ skill, score });
|
|
25433
|
-
}
|
|
25434
|
-
}
|
|
25435
|
-
scored.sort((a, b) => b.score - a.score);
|
|
25436
|
-
return scored.map((s) => s.skill);
|
|
25437
|
-
}
|
|
25438
|
-
function findSimilarSkills(query, maxResults = 3, registry = loadRegistry()) {
|
|
25439
|
-
const q = query.toLowerCase();
|
|
25440
|
-
const scored = registry.map((s) => ({ name: s.name, dist: editDistance(q, s.name.toLowerCase()) })).filter((s) => s.dist <= Math.max(3, Math.floor(q.length / 2))).sort((a, b) => a.dist - b.dist);
|
|
25441
|
-
return scored.slice(0, maxResults).map((s) => s.name);
|
|
25442
|
-
}
|
|
25443
25772
|
// src/lib/registry.ts
|
|
25444
25773
|
function isBasicSkillName(name) {
|
|
25445
25774
|
return BASIC_SKILL_NAMES.includes(name);
|
|
@@ -25480,7 +25809,7 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
25480
25809
|
return [];
|
|
25481
25810
|
const result = [];
|
|
25482
25811
|
try {
|
|
25483
|
-
const entries =
|
|
25812
|
+
const entries = readdirSync15(dir, { withFileTypes: true });
|
|
25484
25813
|
for (const entry of entries) {
|
|
25485
25814
|
if (!entry.isDirectory())
|
|
25486
25815
|
continue;
|
|
@@ -25516,7 +25845,7 @@ function findExtensionSkillPath(name) {
|
|
|
25516
25845
|
if (!config.extensionsDir || !existsSync15(config.extensionsDir))
|
|
25517
25846
|
return null;
|
|
25518
25847
|
try {
|
|
25519
|
-
const entries =
|
|
25848
|
+
const entries = readdirSync15(config.extensionsDir, { withFileTypes: true });
|
|
25520
25849
|
for (const entry of entries) {
|
|
25521
25850
|
if (!entry.isDirectory())
|
|
25522
25851
|
continue;
|
|
@@ -25591,7 +25920,7 @@ function getAllTags(catalog) {
|
|
|
25591
25920
|
}
|
|
25592
25921
|
// src/lib/run-state.ts
|
|
25593
25922
|
import { createHash as createHash31, randomBytes } from "crypto";
|
|
25594
|
-
import { existsSync as existsSync16, mkdirSync as
|
|
25923
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync13, readFileSync as readFileSync28, readdirSync as readdirSync16, statSync as statSync14, writeFileSync as writeFileSync10 } from "fs";
|
|
25595
25924
|
import { extname, join as join42, relative as relative12 } from "path";
|
|
25596
25925
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
25597
25926
|
const now = new Date;
|
|
@@ -25602,9 +25931,9 @@ function createSkillRun(params, targetDir = process.cwd()) {
|
|
|
25602
25931
|
const runDir = join42(root2, "runs", day, id);
|
|
25603
25932
|
const logsDir = join42(runDir, "logs");
|
|
25604
25933
|
const exportDir = join42(root2, "exports", skillName, id);
|
|
25605
|
-
|
|
25606
|
-
|
|
25607
|
-
|
|
25934
|
+
mkdirSync13(logsDir, { recursive: true });
|
|
25935
|
+
mkdirSync13(exportDir, { recursive: true });
|
|
25936
|
+
mkdirSync13(join42(root2, "tmp"), { recursive: true });
|
|
25608
25937
|
const record5 = {
|
|
25609
25938
|
id,
|
|
25610
25939
|
skill: skillName,
|
|
@@ -25671,11 +26000,11 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
|
|
|
25671
26000
|
if (!existsSync16(runsRoot))
|
|
25672
26001
|
return [];
|
|
25673
26002
|
const records = [];
|
|
25674
|
-
for (const day of
|
|
26003
|
+
for (const day of readdirSync16(runsRoot).sort().reverse()) {
|
|
25675
26004
|
const dayDir = join42(runsRoot, day);
|
|
25676
26005
|
if (!statSync14(dayDir).isDirectory())
|
|
25677
26006
|
continue;
|
|
25678
|
-
for (const runId of
|
|
26007
|
+
for (const runId of readdirSync16(dayDir).sort().reverse()) {
|
|
25679
26008
|
const record5 = readRunRecord(join42(dayDir, runId));
|
|
25680
26009
|
if (record5)
|
|
25681
26010
|
records.push(record5);
|
|
@@ -25689,7 +26018,7 @@ function findSkillRun(runId, targetDir = process.cwd()) {
|
|
|
25689
26018
|
const runsRoot = join42(getProjectStateDir(targetDir), "runs");
|
|
25690
26019
|
if (!existsSync16(runsRoot))
|
|
25691
26020
|
return null;
|
|
25692
|
-
for (const day of
|
|
26021
|
+
for (const day of readdirSync16(runsRoot)) {
|
|
25693
26022
|
const record5 = readRunRecord(join42(runsRoot, day, runId));
|
|
25694
26023
|
if (record5)
|
|
25695
26024
|
return record5;
|
|
@@ -25735,7 +26064,7 @@ function readRunRecord(runDir) {
|
|
|
25735
26064
|
}
|
|
25736
26065
|
function walkFiles(dir) {
|
|
25737
26066
|
const files = [];
|
|
25738
|
-
for (const entry of
|
|
26067
|
+
for (const entry of readdirSync16(dir)) {
|
|
25739
26068
|
const full = join42(dir, entry);
|
|
25740
26069
|
if (statSync14(full).isDirectory())
|
|
25741
26070
|
files.push(...walkFiles(full));
|
|
@@ -47243,7 +47572,7 @@ async function createRemoteSkillsClient(env = process.env) {
|
|
|
47243
47572
|
return connection ? new RemoteSkillsClient(connection.apiKey, connection.apiOrigin) : null;
|
|
47244
47573
|
}
|
|
47245
47574
|
// src/lib/scheduler.ts
|
|
47246
|
-
import { existsSync as existsSync17, readFileSync as readFileSync29, writeFileSync as writeFileSync11, mkdirSync as
|
|
47575
|
+
import { existsSync as existsSync17, readFileSync as readFileSync29, writeFileSync as writeFileSync11, mkdirSync as mkdirSync14 } from "fs";
|
|
47247
47576
|
import { join as join43 } from "path";
|
|
47248
47577
|
function getSchedulesPath(targetDir = process.cwd()) {
|
|
47249
47578
|
return join43(targetDir, ".skills", "schedules.json");
|
|
@@ -47261,7 +47590,7 @@ function saveSchedules(data, targetDir = process.cwd()) {
|
|
|
47261
47590
|
const path = getSchedulesPath(targetDir);
|
|
47262
47591
|
const dir = join43(targetDir, ".skills");
|
|
47263
47592
|
if (!existsSync17(dir))
|
|
47264
|
-
|
|
47593
|
+
mkdirSync14(dir, { recursive: true });
|
|
47265
47594
|
writeFileSync11(path, JSON.stringify(data, null, 2));
|
|
47266
47595
|
}
|
|
47267
47596
|
function validateCronField(expr, min, max, label) {
|
|
@@ -47475,7 +47804,7 @@ function revisionIdOfRecord(record10) {
|
|
|
47475
47804
|
return revisionIdOf(record10);
|
|
47476
47805
|
}
|
|
47477
47806
|
// src/lib/pull.ts
|
|
47478
|
-
import { existsSync as existsSync18, mkdirSync as
|
|
47807
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync15, mkdtempSync as mkdtempSync4, readFileSync as readFileSync30, renameSync as renameSync7, rmSync as rmSync6, writeFileSync as writeFileSync12 } from "fs";
|
|
47479
47808
|
import { dirname as dirname29, join as join44 } from "path";
|
|
47480
47809
|
|
|
47481
47810
|
// src/lib/skill-bundles.ts
|
|
@@ -47670,7 +47999,7 @@ function reconcileTombstone(slug2, corpusOptions) {
|
|
|
47670
47999
|
if (!hasSkillsOwnershipMarker(target)) {
|
|
47671
48000
|
return { name: slug2, success: true, tombstoned: true, removed: false, leftInPlace: true };
|
|
47672
48001
|
}
|
|
47673
|
-
|
|
48002
|
+
rmSync6(target, { recursive: true, force: true });
|
|
47674
48003
|
return { name: slug2, success: true, tombstoned: true, removed: true };
|
|
47675
48004
|
}
|
|
47676
48005
|
function readPullMarker(dir) {
|
|
@@ -47809,16 +48138,16 @@ function verifyBundleResponseBytes(buffer, response, verify = {}) {
|
|
|
47809
48138
|
}
|
|
47810
48139
|
function installBundleAtomically(name, entries, options = {}, marker = {}) {
|
|
47811
48140
|
const root2 = getPortableSkillsRoot(options);
|
|
47812
|
-
|
|
48141
|
+
mkdirSync15(root2, { recursive: true });
|
|
47813
48142
|
const target = join44(root2, name);
|
|
47814
48143
|
const created = !existsSync18(target);
|
|
47815
|
-
const staging =
|
|
48144
|
+
const staging = mkdtempSync4(join44(root2, `.pull-${name}-`));
|
|
47816
48145
|
let moved = false;
|
|
47817
48146
|
let backup = null;
|
|
47818
48147
|
try {
|
|
47819
48148
|
for (const entry of entries) {
|
|
47820
48149
|
const destination = join44(staging, entry.path);
|
|
47821
|
-
|
|
48150
|
+
mkdirSync15(dirname29(destination), { recursive: true });
|
|
47822
48151
|
writeFileSync12(destination, entry.bytes, { mode: entry.mode });
|
|
47823
48152
|
}
|
|
47824
48153
|
writePullMarker(staging, {
|
|
@@ -47830,15 +48159,15 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
|
|
|
47830
48159
|
...marker.revisionId ? { revisionId: marker.revisionId } : {}
|
|
47831
48160
|
});
|
|
47832
48161
|
if (existsSync18(target)) {
|
|
47833
|
-
backup =
|
|
48162
|
+
backup = mkdtempSync4(join44(root2, `.pull-backup-${name}-`));
|
|
47834
48163
|
renameSync7(target, join44(backup, name));
|
|
47835
48164
|
moved = true;
|
|
47836
48165
|
}
|
|
47837
48166
|
renameSync7(staging, target);
|
|
47838
48167
|
if (moved && backup)
|
|
47839
|
-
|
|
48168
|
+
rmSync6(backup, { recursive: true, force: true });
|
|
47840
48169
|
} catch (error61) {
|
|
47841
|
-
|
|
48170
|
+
rmSync6(staging, { recursive: true, force: true });
|
|
47842
48171
|
if (moved && backup && existsSync18(join44(backup, name))) {
|
|
47843
48172
|
try {
|
|
47844
48173
|
renameSync7(join44(backup, name), target);
|
|
@@ -48721,7 +49050,7 @@ function findSkillsParityForMcpTool(tool) {
|
|
|
48721
49050
|
return SKILLS_CLI_MCP_PARITY.find((entry) => entry.mcpTools.includes(tool));
|
|
48722
49051
|
}
|
|
48723
49052
|
// src/lib/registry-sync.ts
|
|
48724
|
-
import { mkdirSync as
|
|
49053
|
+
import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync13 } from "fs";
|
|
48725
49054
|
import { dirname as dirname30, relative as relative13 } from "path";
|
|
48726
49055
|
function createRegistrySyncArtifact(options = {}) {
|
|
48727
49056
|
const profile = options.profile ?? "all";
|
|
@@ -48779,7 +49108,7 @@ function createRegistrySyncArtifact(options = {}) {
|
|
|
48779
49108
|
};
|
|
48780
49109
|
}
|
|
48781
49110
|
function writeRegistrySyncArtifact(path, artifact) {
|
|
48782
|
-
|
|
49111
|
+
mkdirSync16(dirname30(path), { recursive: true });
|
|
48783
49112
|
writeFileSync13(path, `${JSON.stringify(artifact, null, 2)}
|
|
48784
49113
|
`);
|
|
48785
49114
|
}
|
|
@@ -49863,7 +50192,7 @@ function clone3(value) {
|
|
|
49863
50192
|
return JSON.parse(JSON.stringify(value));
|
|
49864
50193
|
}
|
|
49865
50194
|
// src/lib/feedback.ts
|
|
49866
|
-
import { appendFileSync, existsSync as existsSync19, mkdirSync as
|
|
50195
|
+
import { appendFileSync, existsSync as existsSync19, mkdirSync as mkdirSync17 } from "fs";
|
|
49867
50196
|
import { dirname as dirname31, join as join45 } from "path";
|
|
49868
50197
|
import { Database } from "bun:sqlite";
|
|
49869
50198
|
function getFeedbackDbPath() {
|
|
@@ -49873,7 +50202,7 @@ function getFeedbackDb() {
|
|
|
49873
50202
|
const dbPath = getFeedbackDbPath();
|
|
49874
50203
|
const dir = dirname31(dbPath);
|
|
49875
50204
|
if (!existsSync19(dir))
|
|
49876
|
-
|
|
50205
|
+
mkdirSync17(dir, { recursive: true });
|
|
49877
50206
|
const db = new Database(dbPath);
|
|
49878
50207
|
db.exec("PRAGMA journal_mode = WAL");
|
|
49879
50208
|
db.exec([
|
|
@@ -49902,7 +50231,7 @@ function saveFeedback(input2) {
|
|
|
49902
50231
|
const path = join45(getDataDir(), "feedback.jsonl");
|
|
49903
50232
|
const dir = dirname31(path);
|
|
49904
50233
|
if (!existsSync19(dir))
|
|
49905
|
-
|
|
50234
|
+
mkdirSync17(dir, { recursive: true });
|
|
49906
50235
|
appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
|
|
49907
50236
|
`);
|
|
49908
50237
|
return { saved: true, category, path };
|
|
@@ -49926,9 +50255,9 @@ function isApiMode(env = process.env) {
|
|
|
49926
50255
|
import { createHash as createHash35, createHmac as createHmac2 } from "crypto";
|
|
49927
50256
|
import {
|
|
49928
50257
|
existsSync as existsSync20,
|
|
49929
|
-
mkdirSync as
|
|
50258
|
+
mkdirSync as mkdirSync18,
|
|
49930
50259
|
readFileSync as readFileSync31,
|
|
49931
|
-
readdirSync as
|
|
50260
|
+
readdirSync as readdirSync17,
|
|
49932
50261
|
statSync as statSync15,
|
|
49933
50262
|
writeFileSync as writeFileSync14
|
|
49934
50263
|
} from "fs";
|
|
@@ -50128,7 +50457,7 @@ function importSkillsLocalSnapshot(snapshot2, targetDir = process.cwd(), options
|
|
|
50128
50457
|
if (hash5 !== file2.sha256) {
|
|
50129
50458
|
throw new Error(`Snapshot file checksum mismatch: ${file2.path}`);
|
|
50130
50459
|
}
|
|
50131
|
-
|
|
50460
|
+
mkdirSync18(dirname32(absolutePath5), { recursive: true });
|
|
50132
50461
|
writeFileSync14(absolutePath5, bytes);
|
|
50133
50462
|
written += 1;
|
|
50134
50463
|
}
|
|
@@ -50425,7 +50754,7 @@ function parsePositiveInteger(value) {
|
|
|
50425
50754
|
}
|
|
50426
50755
|
function walkFiles2(dir) {
|
|
50427
50756
|
const files = [];
|
|
50428
|
-
for (const entry of
|
|
50757
|
+
for (const entry of readdirSync17(dir)) {
|
|
50429
50758
|
const full = join46(dir, entry);
|
|
50430
50759
|
const stats = statSync15(full);
|
|
50431
50760
|
if (stats.isDirectory())
|
|
@@ -50511,7 +50840,7 @@ function toArrayBuffer(bytes) {
|
|
|
50511
50840
|
import { createHash as createHash36 } from "crypto";
|
|
50512
50841
|
import {
|
|
50513
50842
|
copyFileSync,
|
|
50514
|
-
mkdirSync as
|
|
50843
|
+
mkdirSync as mkdirSync19,
|
|
50515
50844
|
readFileSync as readFileSync32,
|
|
50516
50845
|
statSync as statSync17,
|
|
50517
50846
|
writeFileSync as writeFileSync15
|
|
@@ -50519,7 +50848,7 @@ import {
|
|
|
50519
50848
|
import { dirname as dirname33, isAbsolute as isAbsolute31, relative as relative15, resolve as resolve30, sep as sep20 } from "path";
|
|
50520
50849
|
|
|
50521
50850
|
// src/lib/portable-snapshot-filter.ts
|
|
50522
|
-
import { readdirSync as
|
|
50851
|
+
import { readdirSync as readdirSync18, statSync as statSync16 } from "fs";
|
|
50523
50852
|
import { homedir as homedir7 } from "os";
|
|
50524
50853
|
import { join as join47, sep as sep19 } from "path";
|
|
50525
50854
|
var SYNC_HOMES = [
|
|
@@ -50628,7 +50957,7 @@ function destinationFor(definition, stationId, relativePath) {
|
|
|
50628
50957
|
function walkEntries(absoluteRoot) {
|
|
50629
50958
|
let entries;
|
|
50630
50959
|
try {
|
|
50631
|
-
entries =
|
|
50960
|
+
entries = readdirSync18(absoluteRoot, { withFileTypes: true });
|
|
50632
50961
|
} catch {
|
|
50633
50962
|
return [];
|
|
50634
50963
|
}
|
|
@@ -50804,7 +51133,7 @@ function writeStationSnapshot(options) {
|
|
|
50804
51133
|
let written = 0;
|
|
50805
51134
|
for (const plan of untouched) {
|
|
50806
51135
|
const destination = resolve30(repoRoot, plan.destination);
|
|
50807
|
-
|
|
51136
|
+
mkdirSync19(dirname33(destination), { recursive: true });
|
|
50808
51137
|
copyFileSync(plan.source.fullPath, destination);
|
|
50809
51138
|
written += 1;
|
|
50810
51139
|
}
|
|
@@ -50823,7 +51152,7 @@ function writeStationSnapshot(options) {
|
|
|
50823
51152
|
files: manifestFiles
|
|
50824
51153
|
};
|
|
50825
51154
|
const manifestPath = resolve30(repoRoot, "resources", options.stationId, "skills", "sync-manifest.json");
|
|
50826
|
-
|
|
51155
|
+
mkdirSync19(dirname33(manifestPath), { recursive: true });
|
|
50827
51156
|
writeFileSync15(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
50828
51157
|
`);
|
|
50829
51158
|
return {
|
|
@@ -50837,8 +51166,8 @@ function writeStationSnapshot(options) {
|
|
|
50837
51166
|
import { createHash as createHash37 } from "crypto";
|
|
50838
51167
|
import {
|
|
50839
51168
|
copyFileSync as copyFileSync2,
|
|
50840
|
-
mkdirSync as
|
|
50841
|
-
readdirSync as
|
|
51169
|
+
mkdirSync as mkdirSync20,
|
|
51170
|
+
readdirSync as readdirSync19,
|
|
50842
51171
|
readFileSync as readFileSync33,
|
|
50843
51172
|
statSync as statSync18,
|
|
50844
51173
|
writeFileSync as writeFileSync16
|
|
@@ -50885,7 +51214,7 @@ function planStationHydration(stationId, repoRoot) {
|
|
|
50885
51214
|
const agentRoot = join48(snapshotRoot, "agent-homes", agent);
|
|
50886
51215
|
let identEntries;
|
|
50887
51216
|
try {
|
|
50888
|
-
identEntries =
|
|
51217
|
+
identEntries = readdirSync19(agentRoot, { withFileTypes: true });
|
|
50889
51218
|
} catch {
|
|
50890
51219
|
continue;
|
|
50891
51220
|
}
|
|
@@ -51099,7 +51428,7 @@ function writeStationHydration(options) {
|
|
|
51099
51428
|
}
|
|
51100
51429
|
let written = 0;
|
|
51101
51430
|
for (const entry of toWrite) {
|
|
51102
|
-
|
|
51431
|
+
mkdirSync20(dirname34(entry.destination), { recursive: true });
|
|
51103
51432
|
copyFileSync2(entry.fullPath, entry.destination);
|
|
51104
51433
|
written += 1;
|
|
51105
51434
|
}
|
|
@@ -51121,7 +51450,7 @@ function writeStationHydration(options) {
|
|
|
51121
51450
|
skills: resultSkills
|
|
51122
51451
|
};
|
|
51123
51452
|
const hydrationManifestPath = join48(dirname34(cacheRoot), `hydration-${options.stationId}.json`);
|
|
51124
|
-
|
|
51453
|
+
mkdirSync20(dirname34(hydrationManifestPath), { recursive: true });
|
|
51125
51454
|
writeFileSync16(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
|
|
51126
51455
|
`);
|
|
51127
51456
|
return {
|
|
@@ -51132,7 +51461,7 @@ function writeStationHydration(options) {
|
|
|
51132
51461
|
};
|
|
51133
51462
|
}
|
|
51134
51463
|
// src/lib/private-publication-recovery.ts
|
|
51135
|
-
import { constants as constants21, closeSync as closeSync20, fsyncSync as fsyncSync8, fstatSync as fstatSync20, lstatSync as lstatSync34, mkdirSync as
|
|
51464
|
+
import { constants as constants21, closeSync as closeSync20, fsyncSync as fsyncSync8, fstatSync as fstatSync20, lstatSync as lstatSync34, mkdirSync as mkdirSync21, openSync as openSync20, readSync as readSync15, realpathSync as realpathSync16, renameSync as renameSync8, unlinkSync as unlinkSync6, writeFileSync as writeFileSync17 } from "fs";
|
|
51136
51465
|
import { dirname as dirname35, isAbsolute as isAbsolute32, join as join49, resolve as resolve32 } from "path";
|
|
51137
51466
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
51138
51467
|
var fail3 = () => {
|
|
@@ -51279,7 +51608,7 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
|
|
|
51279
51608
|
};
|
|
51280
51609
|
if (!isAbsolute32(recoveryDirectory) || resolve32(recoveryDirectory) !== recoveryDirectory || realpathSync16(dirname35(recoveryDirectory)) !== dirname35(recoveryDirectory))
|
|
51281
51610
|
return fail3();
|
|
51282
|
-
|
|
51611
|
+
mkdirSync21(recoveryDirectory, { mode: 448 });
|
|
51283
51612
|
safeDirectory(recoveryDirectory);
|
|
51284
51613
|
const parent = openSync20(dirname35(recoveryDirectory), constants21.O_RDONLY | constants21.O_NOFOLLOW);
|
|
51285
51614
|
try {
|
|
@@ -51603,7 +51932,7 @@ function applySessionReconciliation(snapshot2, target, planned, record12, verifi
|
|
|
51603
51932
|
}
|
|
51604
51933
|
// src/lib/claude-prospective-review.ts
|
|
51605
51934
|
import { createHash as createHash40 } from "crypto";
|
|
51606
|
-
import { lstatSync as lstatSync35, readFileSync as readFileSync34, readdirSync as
|
|
51935
|
+
import { lstatSync as lstatSync35, readFileSync as readFileSync34, readdirSync as readdirSync20, realpathSync as realpathSync17 } from "fs";
|
|
51607
51936
|
import { basename as basename18, dirname as dirname36, isAbsolute as isAbsolute33, join as join50, relative as relative16, resolve as resolve34, sep as sep22 } from "path";
|
|
51608
51937
|
var MAX_CANDIDATE_FILES = 16384;
|
|
51609
51938
|
var MAX_CANDIDATE_BYTES = 256 * 1024 * 1024;
|
|
@@ -51650,7 +51979,7 @@ function captureClaudeProspectiveCandidateClosure(root2) {
|
|
|
51650
51979
|
let bytes = 0;
|
|
51651
51980
|
const walk2 = (directory3) => {
|
|
51652
51981
|
const beforeDirectory = lstatSync35(directory3);
|
|
51653
|
-
const names =
|
|
51982
|
+
const names = readdirSync20(directory3).sort();
|
|
51654
51983
|
if (new Set(names).size !== names.length)
|
|
51655
51984
|
refuse6("candidate contains ambiguous directory entries");
|
|
51656
51985
|
for (const name of names) {
|