@hasna/skills 0.10.47 → 0.10.49
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 +34 -0
- package/bin/index.js +1091 -649
- package/bin/maintenance.js +18 -0
- package/bin/mcp.js +65 -2
- package/bin/migrate.js +19 -1
- package/bin/server.js +19 -1
- package/bin/worker.js +19 -1
- package/dist/cli/commands/runtime-launcher.d.ts +102 -0
- package/dist/cli/commands/runtime.d.ts +7 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/index.js +414 -262
- package/dist/lib/launch-cwd-apply.d.ts +1 -0
- package/dist/lib/launch-cwd.d.ts +5 -0
- package/dist/lib/self-spawn.d.ts +21 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/sdk/index.js +397 -245
- package/dist/server/index.d.ts +1 -1
- package/dist/server/maintenance.d.ts +1 -1
- package/dist/server/migrate.d.ts +17 -0
- package/dist/server/worker.d.ts +1 -0
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -47,6 +47,26 @@ var __export = (target, all) => {
|
|
|
47
47
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
48
48
|
var __require = import.meta.require;
|
|
49
49
|
|
|
50
|
+
// src/lib/launch-cwd.ts
|
|
51
|
+
function restoreLaunchCwd(env = process.env) {
|
|
52
|
+
const requested = env[LAUNCH_CWD_VARIABLE];
|
|
53
|
+
delete env[LAUNCH_CWD_VARIABLE];
|
|
54
|
+
if (!requested || !requested.startsWith("/"))
|
|
55
|
+
return { restored: false, cwd: process.cwd() };
|
|
56
|
+
try {
|
|
57
|
+
process.chdir(requested);
|
|
58
|
+
return { restored: true, cwd: process.cwd() };
|
|
59
|
+
} catch {
|
|
60
|
+
return { restored: false, cwd: process.cwd() };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
var LAUNCH_CWD_VARIABLE = "HASNA_SKILLS_LAUNCH_CWD";
|
|
64
|
+
|
|
65
|
+
// src/lib/launch-cwd-apply.ts
|
|
66
|
+
var init_launch_cwd_apply = __esm(() => {
|
|
67
|
+
restoreLaunchCwd();
|
|
68
|
+
});
|
|
69
|
+
|
|
50
70
|
// src/cli/output.ts
|
|
51
71
|
async function writeCliOutput(text, newline = true) {
|
|
52
72
|
await new Promise((resolve, reject) => {
|
|
@@ -36868,7 +36888,7 @@ var package_default;
|
|
|
36868
36888
|
var init_package = __esm(() => {
|
|
36869
36889
|
package_default = {
|
|
36870
36890
|
name: "@hasna/skills",
|
|
36871
|
-
version: "0.10.
|
|
36891
|
+
version: "0.10.49",
|
|
36872
36892
|
description: "Skills library for AI coding agents",
|
|
36873
36893
|
type: "module",
|
|
36874
36894
|
bin: {
|
|
@@ -53976,11 +53996,256 @@ function save(file, content) {
|
|
|
53976
53996
|
var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
|
|
53977
53997
|
var init_codex_hook_trust_files = () => {};
|
|
53978
53998
|
|
|
53999
|
+
// src/cli/commands/runtime-launcher.ts
|
|
54000
|
+
import { createHash as createHash18 } from "crypto";
|
|
54001
|
+
import { closeSync as closeSync10, constants as constants11, fchmodSync, fstatSync as fstatSync10, fsyncSync as fsyncSync4, lstatSync as lstatSync19, openSync as openSync10, readFileSync as readFileSync15, readlinkSync as readlinkSync5, realpathSync as realpathSync9, symlinkSync, writeSync as writeSync2 } from "fs";
|
|
54002
|
+
import { isAbsolute as isAbsolute13 } from "path";
|
|
54003
|
+
function pinnedLauncherEnvironment(env3) {
|
|
54004
|
+
const result2 = {};
|
|
54005
|
+
for (const [name, value] of Object.entries(env3)) {
|
|
54006
|
+
if (value === undefined || !ENV_NAME.test(name) || !ENV_EXACT.has(name) && !ENV_PREFIX.test(name))
|
|
54007
|
+
continue;
|
|
54008
|
+
result2[name] = value;
|
|
54009
|
+
}
|
|
54010
|
+
return result2;
|
|
54011
|
+
}
|
|
54012
|
+
function sha2562(bytes) {
|
|
54013
|
+
return createHash18("sha256").update(bytes).digest("hex");
|
|
54014
|
+
}
|
|
54015
|
+
function assertLauncherPath(value, code) {
|
|
54016
|
+
if (typeof value !== "string" || !isAbsolute13(value) || /['\x00-\x1f\x7f]/.test(value))
|
|
54017
|
+
throw new Error(code);
|
|
54018
|
+
}
|
|
54019
|
+
function renderPinnedLauncher(binding) {
|
|
54020
|
+
assertLauncherPath(binding.runtime, "LAUNCHER_RUNTIME_PATH_INVALID");
|
|
54021
|
+
assertLauncherPath(binding.cwd, "LAUNCHER_CWD_PATH_INVALID");
|
|
54022
|
+
assertLauncherPath(binding.entry, "LAUNCHER_ENTRY_PATH_INVALID");
|
|
54023
|
+
const names = PINNED_LAUNCHER_ENV_NAMES.join(" ");
|
|
54024
|
+
const prefixes = PINNED_LAUNCHER_ENV_PREFIXES.join("|");
|
|
54025
|
+
return [
|
|
54026
|
+
"#!/bin/sh -p",
|
|
54027
|
+
`# ${PINNED_LAUNCHER_SCHEMA}`,
|
|
54028
|
+
"# Written by `skills self-update`; rewrite it with `skills self-update`, do not edit by hand.",
|
|
54029
|
+
"# Runs the exact Skills entry below under one exact Bun from one trusted directory with",
|
|
54030
|
+
"# no working-directory configuration (no bunfig.toml, no .env, no macros, no auto-install)",
|
|
54031
|
+
"# and only the environment names allowed here. Everything else, BUN_* and NODE_OPTIONS",
|
|
54032
|
+
"# included, never reaches the runtime. The CLI returns to the caller's directory itself.",
|
|
54033
|
+
"# `-p` keeps the caller's exported functions and shell options out of this shell.",
|
|
54034
|
+
"set -eu",
|
|
54035
|
+
`${LAUNCH_CWD_VARIABLE2}=$(pwd -P 2>/dev/null || :)`,
|
|
54036
|
+
`export ${LAUNCH_CWD_VARIABLE2}`,
|
|
54037
|
+
`set -- '${binding.runtime}' ${PINNED_LAUNCHER_BUN_FLAGS.join(" ")} '--cwd=${binding.cwd}' '${binding.entry}' "$@"`,
|
|
54038
|
+
"hasna_skills_env=$(LC_ALL=C /usr/bin/awk 'BEGIN {",
|
|
54039
|
+
` n = split("${names}", exact, " ")`,
|
|
54040
|
+
" for (i = 1; i <= n; i++) allow[exact[i]] = 1",
|
|
54041
|
+
" for (name in ENVIRON) {",
|
|
54042
|
+
" if (name !~ /^[A-Za-z_][A-Za-z0-9_]*$/) continue",
|
|
54043
|
+
` if (name == "LC_ALL" || (!(name in allow) && name !~ /^(${prefixes})_/)) continue`,
|
|
54044
|
+
' value = ENVIRON[name]; quoted = ""',
|
|
54045
|
+
' while ((k = index(value, "\\047")) > 0) { quoted = quoted substr(value, 1, k - 1) "\\047\\\\\\047\\047"; value = substr(value, k + 1) }',
|
|
54046
|
+
' printf "\\047%s=%s\\047 ", name, quoted value',
|
|
54047
|
+
" }",
|
|
54048
|
+
"}')",
|
|
54049
|
+
'eval "set -- $hasna_skills_env \\"\\$@\\""',
|
|
54050
|
+
'if [ "${LC_ALL+x}" = x ]; then set -- "LC_ALL=$LC_ALL" "$@"; fi',
|
|
54051
|
+
'exec /usr/bin/env -i "$@"',
|
|
54052
|
+
""
|
|
54053
|
+
].join(`
|
|
54054
|
+
`);
|
|
54055
|
+
}
|
|
54056
|
+
function parsePinnedLauncher(text2) {
|
|
54057
|
+
const match = COMMAND_LINE.exec(text2);
|
|
54058
|
+
if (!match)
|
|
54059
|
+
return null;
|
|
54060
|
+
const binding = { runtime: match[1], cwd: match[2], entry: match[3] };
|
|
54061
|
+
try {
|
|
54062
|
+
if (renderPinnedLauncher(binding) !== text2)
|
|
54063
|
+
return null;
|
|
54064
|
+
} catch {
|
|
54065
|
+
return null;
|
|
54066
|
+
}
|
|
54067
|
+
return binding;
|
|
54068
|
+
}
|
|
54069
|
+
function resolveLauncherCommand(path) {
|
|
54070
|
+
const physical = realpathSync9(path);
|
|
54071
|
+
const stat = lstatSync19(physical);
|
|
54072
|
+
if (stat.isFile() && stat.size <= PINNED_LAUNCHER_MAX_BYTES) {
|
|
54073
|
+
const text2 = readFileSync15(physical, "utf8");
|
|
54074
|
+
const binding = parsePinnedLauncher(text2);
|
|
54075
|
+
if (binding) {
|
|
54076
|
+
let entry;
|
|
54077
|
+
try {
|
|
54078
|
+
entry = realpathSync9(binding.entry);
|
|
54079
|
+
} catch {
|
|
54080
|
+
throw new Error("LAUNCHER_ENTRY_UNREADABLE");
|
|
54081
|
+
}
|
|
54082
|
+
if (entry !== binding.entry)
|
|
54083
|
+
throw new Error("LAUNCHER_ENTRY_NOT_PHYSICAL");
|
|
54084
|
+
return { physical, entry, pinned: { ...binding, sha256: sha2562(text2) } };
|
|
54085
|
+
}
|
|
54086
|
+
}
|
|
54087
|
+
return { physical, entry: physical, pinned: null };
|
|
54088
|
+
}
|
|
54089
|
+
function inspectLauncher(path) {
|
|
54090
|
+
const stat = lstatSync19(path);
|
|
54091
|
+
if (stat.isSymbolicLink()) {
|
|
54092
|
+
const linkTarget = readlinkSync5(path);
|
|
54093
|
+
let target;
|
|
54094
|
+
try {
|
|
54095
|
+
target = realpathSync9(path);
|
|
54096
|
+
} catch {
|
|
54097
|
+
throw new Error("LAUNCHER_TARGET_UNREADABLE");
|
|
54098
|
+
}
|
|
54099
|
+
return { kind: "symlink", linkTarget, target };
|
|
54100
|
+
}
|
|
54101
|
+
if (!stat.isFile())
|
|
54102
|
+
return { kind: "foreign" };
|
|
54103
|
+
const text2 = readFileSync15(path, "utf8");
|
|
54104
|
+
const binding = parsePinnedLauncher(text2);
|
|
54105
|
+
if (!binding)
|
|
54106
|
+
return { kind: "foreign" };
|
|
54107
|
+
return { kind: "pinned", runtime: binding.runtime, cwd: binding.cwd, target: binding.entry, sha256: sha2562(text2), text: text2 };
|
|
54108
|
+
}
|
|
54109
|
+
function launcherTarget(path) {
|
|
54110
|
+
const inspected = inspectLauncher(path);
|
|
54111
|
+
if (inspected.kind === "foreign")
|
|
54112
|
+
throw new Error("LAUNCHER_SHAPE_UNSUPPORTED");
|
|
54113
|
+
return inspected.target;
|
|
54114
|
+
}
|
|
54115
|
+
function launcherIs(path, state) {
|
|
54116
|
+
let inspected;
|
|
54117
|
+
try {
|
|
54118
|
+
inspected = inspectLauncher(path);
|
|
54119
|
+
} catch {
|
|
54120
|
+
return false;
|
|
54121
|
+
}
|
|
54122
|
+
if (state.shape === "symlink")
|
|
54123
|
+
return inspected.kind === "symlink" && inspected.linkTarget === state.linkTarget && inspected.target === state.target;
|
|
54124
|
+
return inspected.kind === "pinned" && inspected.sha256 === state.sha256 && inspected.runtime === state.runtime && inspected.cwd === state.cwd && inspected.target === state.target;
|
|
54125
|
+
}
|
|
54126
|
+
function pinnedLauncherText(state) {
|
|
54127
|
+
const text2 = renderPinnedLauncher({ runtime: state.runtime, cwd: state.cwd, entry: state.target });
|
|
54128
|
+
if (sha2562(text2) !== state.sha256)
|
|
54129
|
+
throw new Error("LAUNCHER_TEXT_DIGEST_MISMATCH");
|
|
54130
|
+
return text2;
|
|
54131
|
+
}
|
|
54132
|
+
function pinnedLauncherState(runtime, cwd2, target) {
|
|
54133
|
+
const text2 = renderPinnedLauncher({ runtime, cwd: cwd2, entry: target });
|
|
54134
|
+
return { shape: "pinned", runtime, cwd: cwd2, target, sha256: sha2562(text2) };
|
|
54135
|
+
}
|
|
54136
|
+
function materializeLauncher(path, state) {
|
|
54137
|
+
if (state.shape === "symlink") {
|
|
54138
|
+
symlinkSync(state.linkTarget, path);
|
|
54139
|
+
if (readlinkSync5(path) !== state.linkTarget || realpathSync9(path) !== state.target)
|
|
54140
|
+
throw new Error("LAUNCHER_READBACK_MISMATCH");
|
|
54141
|
+
return;
|
|
54142
|
+
}
|
|
54143
|
+
const text2 = pinnedLauncherText(state);
|
|
54144
|
+
const fd = openSync10(path, constants11.O_WRONLY | constants11.O_CREAT | constants11.O_EXCL | constants11.O_NOFOLLOW, 493);
|
|
54145
|
+
try {
|
|
54146
|
+
const bytes = Buffer.from(text2, "utf8");
|
|
54147
|
+
let written = 0;
|
|
54148
|
+
while (written < bytes.length)
|
|
54149
|
+
written += writeSync2(fd, bytes, written, bytes.length - written);
|
|
54150
|
+
fchmodSync(fd, 493);
|
|
54151
|
+
fsyncSync4(fd);
|
|
54152
|
+
if ((fstatSync10(fd).mode & 511) !== 493)
|
|
54153
|
+
throw new Error("LAUNCHER_READBACK_MISMATCH");
|
|
54154
|
+
} finally {
|
|
54155
|
+
closeSync10(fd);
|
|
54156
|
+
}
|
|
54157
|
+
const stat = lstatSync19(path);
|
|
54158
|
+
if (!stat.isFile() || stat.isSymbolicLink() || readFileSync15(path, "utf8") !== text2)
|
|
54159
|
+
throw new Error("LAUNCHER_READBACK_MISMATCH");
|
|
54160
|
+
}
|
|
54161
|
+
function pinnedLauncherRuntime() {
|
|
54162
|
+
let runtime;
|
|
54163
|
+
try {
|
|
54164
|
+
runtime = realpathSync9(process.execPath);
|
|
54165
|
+
} catch {
|
|
54166
|
+
throw new Error("LAUNCHER_RUNTIME_UNREADABLE");
|
|
54167
|
+
}
|
|
54168
|
+
assertPinnedLauncherRuntimeSafe(runtime);
|
|
54169
|
+
assertPinnedLauncherShell();
|
|
54170
|
+
return runtime;
|
|
54171
|
+
}
|
|
54172
|
+
function assertPinnedLauncherRuntimeSafe(runtime) {
|
|
54173
|
+
assertLauncherPath(runtime, "LAUNCHER_RUNTIME_PATH_INVALID");
|
|
54174
|
+
let stat;
|
|
54175
|
+
try {
|
|
54176
|
+
stat = lstatSync19(runtime);
|
|
54177
|
+
} catch {
|
|
54178
|
+
throw new Error("LAUNCHER_RUNTIME_UNSAFE");
|
|
54179
|
+
}
|
|
54180
|
+
const uid = process.getuid?.() ?? -1;
|
|
54181
|
+
if (!stat.isFile() || stat.isSymbolicLink() || ![0, uid].includes(stat.uid) || (stat.mode & 18) !== 0 || (stat.mode & 64) === 0) {
|
|
54182
|
+
throw new Error("LAUNCHER_RUNTIME_UNSAFE");
|
|
54183
|
+
}
|
|
54184
|
+
}
|
|
54185
|
+
function assertPinnedLauncherShell() {
|
|
54186
|
+
for (const tool of ["/bin/sh", "/usr/bin/awk", "/usr/bin/env"]) {
|
|
54187
|
+
let stat;
|
|
54188
|
+
try {
|
|
54189
|
+
stat = lstatSync19(realpathSync9(tool));
|
|
54190
|
+
} catch {
|
|
54191
|
+
throw new Error("LAUNCHER_SHELL_UNSUPPORTED");
|
|
54192
|
+
}
|
|
54193
|
+
if (!stat.isFile() || (stat.mode & 73) === 0)
|
|
54194
|
+
throw new Error("LAUNCHER_SHELL_UNSUPPORTED");
|
|
54195
|
+
}
|
|
54196
|
+
const probe = Bun.spawnSync(["/bin/sh", "-p", "-c", "exit 0"], { env: {}, stdin: "ignore", stdout: "ignore", stderr: "ignore" });
|
|
54197
|
+
if (probe.exitCode !== 0)
|
|
54198
|
+
throw new Error("LAUNCHER_SHELL_UNSUPPORTED");
|
|
54199
|
+
}
|
|
54200
|
+
var PINNED_LAUNCHER_SCHEMA = "hasna-skills-pinned-launcher-v1", LAUNCH_CWD_VARIABLE2 = "HASNA_SKILLS_LAUNCH_CWD", PINNED_LAUNCHER_BUN_FLAGS, PINNED_LAUNCHER_ENV_NAMES, PINNED_LAUNCHER_ENV_PREFIXES, ENV_NAME, ENV_PREFIX, ENV_EXACT, COMMAND_LINE, PINNED_LAUNCHER_MAX_BYTES;
|
|
54201
|
+
var init_runtime_launcher = __esm(() => {
|
|
54202
|
+
PINNED_LAUNCHER_BUN_FLAGS = ["--config=/dev/null", "--no-env-file", "--no-macros", "--no-install"];
|
|
54203
|
+
PINNED_LAUNCHER_ENV_NAMES = [
|
|
54204
|
+
"HOME",
|
|
54205
|
+
"PATH",
|
|
54206
|
+
"TMPDIR",
|
|
54207
|
+
"TERM",
|
|
54208
|
+
"TERM_PROGRAM",
|
|
54209
|
+
"TERM_PROGRAM_VERSION",
|
|
54210
|
+
"COLORTERM",
|
|
54211
|
+
"LANG",
|
|
54212
|
+
"USER",
|
|
54213
|
+
"LOGNAME",
|
|
54214
|
+
"SHELL",
|
|
54215
|
+
"TZ",
|
|
54216
|
+
"NO_COLOR",
|
|
54217
|
+
"FORCE_COLOR",
|
|
54218
|
+
"CI",
|
|
54219
|
+
"COLUMNS",
|
|
54220
|
+
"LINES",
|
|
54221
|
+
"EDITOR",
|
|
54222
|
+
"VISUAL",
|
|
54223
|
+
"PAGER",
|
|
54224
|
+
"SSH_AUTH_SOCK",
|
|
54225
|
+
"DATABASE_URL",
|
|
54226
|
+
"TERMINAL_CWD",
|
|
54227
|
+
"CODEX_HOME",
|
|
54228
|
+
"HERMES_HOME",
|
|
54229
|
+
"HERMES_ENABLE_PROJECT_PLUGINS",
|
|
54230
|
+
"HOST",
|
|
54231
|
+
"PORT",
|
|
54232
|
+
"NODE_ENV",
|
|
54233
|
+
"AGENT_ID",
|
|
54234
|
+
"ECS_CONTAINER_METADATA_URI_V4"
|
|
54235
|
+
];
|
|
54236
|
+
PINNED_LAUNCHER_ENV_PREFIXES = ["HASNA", "SKILLS", "SKILL", "MCP", "XDG", "LC", "AWS"];
|
|
54237
|
+
ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
54238
|
+
ENV_PREFIX = new RegExp(`^(${PINNED_LAUNCHER_ENV_PREFIXES.join("|")})_`);
|
|
54239
|
+
ENV_EXACT = new Set(PINNED_LAUNCHER_ENV_NAMES);
|
|
54240
|
+
COMMAND_LINE = new RegExp(`^set -- '([^']+)' ${PINNED_LAUNCHER_BUN_FLAGS.join(" ")} '--cwd=([^']+)' '([^']+)' "\\$@"$`, "m");
|
|
54241
|
+
PINNED_LAUNCHER_MAX_BYTES = 16 * 1024;
|
|
54242
|
+
});
|
|
54243
|
+
|
|
53979
54244
|
// src/lib/agent-integration.ts
|
|
53980
|
-
import { createHash as
|
|
54245
|
+
import { createHash as createHash19, randomUUID as randomUUID6 } from "crypto";
|
|
53981
54246
|
import { isDeepStrictEqual as isDeepStrictEqual7 } from "util";
|
|
53982
|
-
import { existsSync as existsSync13, lstatSync as
|
|
53983
|
-
import { dirname as dirname14, join as join28, resolve as resolve14, relative as relative6, isAbsolute as
|
|
54247
|
+
import { existsSync as existsSync13, lstatSync as lstatSync20, statSync as statSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync16, readdirSync as readdirSync8, opendirSync as opendirSync3, readlinkSync as readlinkSync6, realpathSync as realpathSync10, renameSync as renameSync3, rmdirSync as rmdirSync2, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, chmodSync, openSync as openSync11, closeSync as closeSync11, fsyncSync as fsyncSync5, fstatSync as fstatSync11, readSync as readSync8, constants as constants12, linkSync as linkSync2 } from "fs";
|
|
54248
|
+
import { dirname as dirname14, join as join28, resolve as resolve14, relative as relative6, isAbsolute as isAbsolute14, sep as sep7 } from "path";
|
|
53984
54249
|
import { homedir as homedir3 } from "os";
|
|
53985
54250
|
function hasTrustedDarwinAcl(fd, allowDenyOnly = false) {
|
|
53986
54251
|
try {
|
|
@@ -54031,11 +54296,11 @@ function isSystemRootAlias(path) {
|
|
|
54031
54296
|
const target = `/private${path}`, link2 = `private${path}`;
|
|
54032
54297
|
const identity6 = (stat) => `${stat.dev}:${stat.ino}:${stat.ctimeNs}:${stat.uid}:${stat.mode}`;
|
|
54033
54298
|
try {
|
|
54034
|
-
const before2 =
|
|
54035
|
-
if (!before2.isSymbolicLink() || before2.uid !== 0n ||
|
|
54299
|
+
const before2 = lstatSync20(path, { bigint: true });
|
|
54300
|
+
if (!before2.isSymbolicLink() || before2.uid !== 0n || readlinkSync6(path) !== link2)
|
|
54036
54301
|
return false;
|
|
54037
54302
|
const directories = ["/", "/private", target].map((directory) => {
|
|
54038
|
-
const stat =
|
|
54303
|
+
const stat = lstatSync20(directory, { bigint: true });
|
|
54039
54304
|
if (!stat.isDirectory() || stat.uid !== 0n)
|
|
54040
54305
|
throw new Error("Untrusted system alias directory");
|
|
54041
54306
|
if (directory !== "/private/tmp") {
|
|
@@ -54043,23 +54308,23 @@ function isSystemRootAlias(path) {
|
|
|
54043
54308
|
throw new Error("Writable system alias directory");
|
|
54044
54309
|
} else if ((stat.mode & 0o1000n) === 0n)
|
|
54045
54310
|
throw new Error("Unprotected system temporary directory");
|
|
54046
|
-
const fd =
|
|
54311
|
+
const fd = openSync11(directory, constants12.O_RDONLY | constants12.O_DIRECTORY | constants12.O_NOFOLLOW);
|
|
54047
54312
|
try {
|
|
54048
|
-
if (identity6(
|
|
54313
|
+
if (identity6(fstatSync11(fd, { bigint: true })) !== identity6(stat) || !hasTrustedDarwinAcl(fd) || identity6(fstatSync11(fd, { bigint: true })) !== identity6(stat))
|
|
54049
54314
|
throw new Error("Unverified system alias directory ACL");
|
|
54050
54315
|
} finally {
|
|
54051
|
-
|
|
54316
|
+
closeSync11(fd);
|
|
54052
54317
|
}
|
|
54053
54318
|
return { directory, identity: identity6(stat) };
|
|
54054
54319
|
});
|
|
54055
|
-
return
|
|
54320
|
+
return realpathSync10(path) === target && readlinkSync6(path) === link2 && identity6(lstatSync20(path, { bigint: true })) === identity6(before2) && directories.every((item) => identity6(lstatSync20(item.directory, { bigint: true })) === item.identity);
|
|
54056
54321
|
} catch {
|
|
54057
54322
|
return false;
|
|
54058
54323
|
}
|
|
54059
54324
|
}
|
|
54060
54325
|
function canonicalSystemPath(path) {
|
|
54061
54326
|
const absolute = resolve14(path), root = `/${absolute.split(sep7)[1]}`;
|
|
54062
|
-
if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root) || !
|
|
54327
|
+
if (process.platform !== "darwin" || !["/var", "/tmp", "/etc"].includes(root) || !lstatSync20(root, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
54063
54328
|
return absolute;
|
|
54064
54329
|
if (!isSystemRootAlias(root))
|
|
54065
54330
|
throw new Error(`Refusing symlink path: ${root}`);
|
|
@@ -54068,7 +54333,7 @@ function canonicalSystemPath(path) {
|
|
|
54068
54333
|
function assertSafePath(path) {
|
|
54069
54334
|
let cursor = resolve14(path);
|
|
54070
54335
|
while (true) {
|
|
54071
|
-
if (
|
|
54336
|
+
if (lstatSync20(cursor, { throwIfNoEntry: false })?.isSymbolicLink() && !isSystemRootAlias(cursor))
|
|
54072
54337
|
throw new Error(`Refusing symlink path: ${cursor}`);
|
|
54073
54338
|
const parent = dirname14(cursor);
|
|
54074
54339
|
if (parent === cursor)
|
|
@@ -54078,17 +54343,17 @@ function assertSafePath(path) {
|
|
|
54078
54343
|
}
|
|
54079
54344
|
function readRootAlias(home, agent) {
|
|
54080
54345
|
assertSafePath(home);
|
|
54081
|
-
const realHome =
|
|
54082
|
-
const stat =
|
|
54346
|
+
const realHome = realpathSync10(home), alias = join28(realHome, `.${agent}`);
|
|
54347
|
+
const stat = lstatSync20(alias, { throwIfNoEntry: false, bigint: true });
|
|
54083
54348
|
if (!stat?.isSymbolicLink())
|
|
54084
54349
|
throw new Error(`Agent root alias changed after planning: ${alias}`);
|
|
54085
|
-
const link2 =
|
|
54350
|
+
const link2 = readlinkSync6(alias), targetPath = resolve14(dirname14(alias), link2);
|
|
54086
54351
|
assertSafePath(targetPath);
|
|
54087
|
-
const targetStat =
|
|
54352
|
+
const targetStat = lstatSync20(targetPath, { throwIfNoEntry: false });
|
|
54088
54353
|
if (!targetStat?.isDirectory())
|
|
54089
54354
|
throw new Error(`Agent root alias must target an existing directory: ${alias}`);
|
|
54090
|
-
const target =
|
|
54091
|
-
if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) ||
|
|
54355
|
+
const target = realpathSync10(targetPath), inside = relative6(realHome, target);
|
|
54356
|
+
if (!inside || inside === ".." || inside.startsWith(`..${sep7}`) || isAbsolute14(inside))
|
|
54092
54357
|
throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
|
|
54093
54358
|
return { agent, home: realHome, alias, target, link: link2, aliasIdentity: `${stat.dev}:${stat.ino}:${stat.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
|
|
54094
54359
|
}
|
|
@@ -54097,7 +54362,7 @@ function rootAliases(home, allowed = false) {
|
|
|
54097
54362
|
return [];
|
|
54098
54363
|
const result2 = [];
|
|
54099
54364
|
for (const agent of ["claude", "codex"])
|
|
54100
|
-
if (
|
|
54365
|
+
if (lstatSync20(join28(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
|
|
54101
54366
|
result2.push(readRootAlias(home, agent));
|
|
54102
54367
|
if (result2.some((item, index) => result2.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep7) || other.target.startsWith(item.target + sep7))))
|
|
54103
54368
|
throw new Error("Agent root alias targets must not overlap");
|
|
@@ -54114,17 +54379,17 @@ function disabledCodexSkillPaths(config, aliases) {
|
|
|
54114
54379
|
const rows = skills.config;
|
|
54115
54380
|
if (!Array.isArray(rows))
|
|
54116
54381
|
return [];
|
|
54117
|
-
if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined === (entry.name !== undefined) || entry.path !== undefined && (typeof entry.path !== "string" || !
|
|
54382
|
+
if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined === (entry.name !== undefined) || entry.path !== undefined && (typeof entry.path !== "string" || !isAbsolute14(entry.path)) || entry.name !== undefined && (typeof entry.name !== "string" || !entry.name.trim())))
|
|
54118
54383
|
return [];
|
|
54119
54384
|
if (rows.some((entry) => entry.name !== undefined && entry.enabled !== false))
|
|
54120
54385
|
return [];
|
|
54121
54386
|
const settings = new Map;
|
|
54122
54387
|
for (const entry of rows) {
|
|
54123
|
-
if (typeof entry.path !== "string" || !
|
|
54388
|
+
if (typeof entry.path !== "string" || !isAbsolute14(entry.path))
|
|
54124
54389
|
continue;
|
|
54125
54390
|
let document3;
|
|
54126
54391
|
try {
|
|
54127
|
-
document3 =
|
|
54392
|
+
document3 = realpathSync10(canonicalAgentPath(entry.path, aliases));
|
|
54128
54393
|
} catch {
|
|
54129
54394
|
continue;
|
|
54130
54395
|
}
|
|
@@ -54145,16 +54410,16 @@ function recheckRootAliases(aliases) {
|
|
|
54145
54410
|
}
|
|
54146
54411
|
function nativeSourceDigest(path) {
|
|
54147
54412
|
assertSafePath(path);
|
|
54148
|
-
return
|
|
54413
|
+
return lstatSync20(path, { throwIfNoEntry: false }) ? sha3(readNativeBytes(path, 1024 * 1024)) : null;
|
|
54149
54414
|
}
|
|
54150
54415
|
function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
|
|
54151
54416
|
assertSafePath(path);
|
|
54152
|
-
const before2 =
|
|
54417
|
+
const before2 = lstatSync20(path);
|
|
54153
54418
|
if (!before2.isFile() || before2.size > maximum)
|
|
54154
54419
|
throw new Error("Unsupported or oversized native skill file");
|
|
54155
|
-
const descriptor =
|
|
54420
|
+
const descriptor = openSync11(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
|
|
54156
54421
|
try {
|
|
54157
|
-
const opened =
|
|
54422
|
+
const opened = fstatSync11(descriptor);
|
|
54158
54423
|
if (!opened.isFile() || opened.dev !== before2.dev || opened.ino !== before2.ino || opened.size !== before2.size)
|
|
54159
54424
|
throw new Error("Native skill file changed while reading");
|
|
54160
54425
|
const bytes = Buffer.allocUnsafe(before2.size + 1);
|
|
@@ -54165,19 +54430,19 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
|
|
|
54165
54430
|
break;
|
|
54166
54431
|
length += count;
|
|
54167
54432
|
}
|
|
54168
|
-
const after2 =
|
|
54433
|
+
const after2 = fstatSync11(descriptor), current = lstatSync20(path);
|
|
54169
54434
|
if (current.dev !== opened.dev || current.ino !== opened.ino || current.size !== after2.size || current.mtimeMs !== after2.mtimeMs || current.ctimeMs !== after2.ctimeMs || length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== opened.mtimeMs || after2.ctimeMs !== opened.ctimeMs)
|
|
54170
54435
|
throw new Error("Native skill file changed while reading");
|
|
54171
54436
|
return bytes.subarray(0, length);
|
|
54172
54437
|
} finally {
|
|
54173
|
-
|
|
54438
|
+
closeSync11(descriptor);
|
|
54174
54439
|
}
|
|
54175
54440
|
}
|
|
54176
54441
|
function treeHash(root) {
|
|
54177
|
-
const hash2 =
|
|
54442
|
+
const hash2 = createHash19("sha256");
|
|
54178
54443
|
let bytes = 0, files = 0;
|
|
54179
54444
|
function visit2(path) {
|
|
54180
|
-
const stat =
|
|
54445
|
+
const stat = lstatSync20(path);
|
|
54181
54446
|
if (stat.isSymbolicLink())
|
|
54182
54447
|
throw new Error(`Refusing symlink in skill: ${path}`);
|
|
54183
54448
|
const rel = relative6(root, path);
|
|
@@ -54225,16 +54490,16 @@ function parseNativeMigrationTargetManifest(input) {
|
|
|
54225
54490
|
throw new Error("Invalid native migration target fields");
|
|
54226
54491
|
if (!ROOTS.some(([agent]) => agent === item.agent))
|
|
54227
54492
|
throw new Error(`Unsupported native migration target agent: ${item.agent}`);
|
|
54228
|
-
if (!
|
|
54493
|
+
if (!isAbsolute14(item.projectRoot) || resolve14(item.projectRoot) !== item.projectRoot)
|
|
54229
54494
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${item.projectRoot}`);
|
|
54230
54495
|
const projectRoot = canonicalSystemPath(item.projectRoot);
|
|
54231
|
-
if (!existsSync13(projectRoot) || !
|
|
54496
|
+
if (!existsSync13(projectRoot) || !lstatSync20(projectRoot).isDirectory())
|
|
54232
54497
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${item.projectRoot}`);
|
|
54233
54498
|
assertSafePath(projectRoot);
|
|
54234
|
-
if (
|
|
54499
|
+
if (isAbsolute14(item.path) || item.path.includes("\\") || item.path.length === 0 || item.path.includes("\x00"))
|
|
54235
54500
|
throw new Error(`Native migration target path must be normalized and project-relative: ${item.path}`);
|
|
54236
54501
|
const resolved = resolve14(projectRoot, item.path), normalized = relative6(projectRoot, resolved);
|
|
54237
|
-
if (!normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) ||
|
|
54502
|
+
if (!normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || isAbsolute14(normalized) || normalized !== item.path)
|
|
54238
54503
|
throw new Error(`Native migration target path escapes or is not normalized: ${item.path}`);
|
|
54239
54504
|
if (!/^[0-9a-f]{64}$/.test(item.treeSha256))
|
|
54240
54505
|
throw new Error(`Invalid native migration tree digest for ${item.path}`);
|
|
@@ -54255,13 +54520,13 @@ function selectNativeMigrationTargets(inventory, manifest) {
|
|
|
54255
54520
|
const identities = new Set;
|
|
54256
54521
|
const selected = [];
|
|
54257
54522
|
for (const target of manifest.targets) {
|
|
54258
|
-
if (!
|
|
54523
|
+
if (!isAbsolute14(target.projectRoot) || resolve14(target.projectRoot) !== target.projectRoot)
|
|
54259
54524
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
|
|
54260
54525
|
const projectRoot = canonicalSystemPath(target.projectRoot), normalized = relative6(projectRoot, resolve14(projectRoot, target.path));
|
|
54261
|
-
if (!existsSync13(projectRoot) || !
|
|
54526
|
+
if (!existsSync13(projectRoot) || !lstatSync20(projectRoot).isDirectory())
|
|
54262
54527
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
|
|
54263
54528
|
assertSafePath(projectRoot);
|
|
54264
|
-
if (
|
|
54529
|
+
if (isAbsolute14(target.path) || target.path.includes("\\") || target.path.includes("\x00") || !normalized || normalized === ".." || normalized.startsWith(`..${sep7}`) || normalized !== target.path || !/^[0-9a-f]{64}$/.test(target.treeSha256))
|
|
54265
54530
|
throw new Error(`Invalid native migration target: ${target.path}`);
|
|
54266
54531
|
const identity6 = `${target.agent}\x00${canonicalSystemPath(projectRoot)}\x00${normalized}`;
|
|
54267
54532
|
if (identities.has(identity6))
|
|
@@ -54304,9 +54569,9 @@ function isCodexSkillDiscoveryInput(path) {
|
|
|
54304
54569
|
}
|
|
54305
54570
|
function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
54306
54571
|
home = canonicalSystemPath(home);
|
|
54307
|
-
if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !
|
|
54572
|
+
if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute14(options.reviewedCacheAlias) || resolve14(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
|
|
54308
54573
|
throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
|
|
54309
|
-
if (options.disabledVendorPaths?.some((path) => !
|
|
54574
|
+
if (options.disabledVendorPaths?.some((path) => !isAbsolute14(path) || resolve14(path) !== path))
|
|
54310
54575
|
throw new Error("Disabled vendor paths must be exact absolute paths");
|
|
54311
54576
|
const reviewedCacheAlias = options.reviewedCacheAlias === undefined ? undefined : canonicalSystemPath(options.reviewedCacheAlias);
|
|
54312
54577
|
const disabledVendorPaths = new Set((options.disabledVendorPaths ?? []).map(canonicalSystemPath));
|
|
@@ -54325,7 +54590,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
54325
54590
|
roots.push(["sumi", canonicalAgentPath(join28(project, directory, name), aliases)]);
|
|
54326
54591
|
}
|
|
54327
54592
|
const installationInputs = options.codexInstallationInputRoots ?? [];
|
|
54328
|
-
if (installationInputs.some((input) => resolve14(input) !== input ||
|
|
54593
|
+
if (installationInputs.some((input) => resolve14(input) !== input || realpathSync10(input) !== input || roots.some(([agent, path]) => agent === "codex" && (path === input || path.startsWith(input + sep7) || input.startsWith(path + sep7)))))
|
|
54329
54594
|
throw new Error("Native installation input overlaps an unconditional skill-loading root");
|
|
54330
54595
|
const entries = [], seen = new Set;
|
|
54331
54596
|
const cacheScans = new Map, maxAliasProofEntries = 1e4;
|
|
@@ -54339,13 +54604,13 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
54339
54604
|
}
|
|
54340
54605
|
let reviewedCacheAliasFound = false;
|
|
54341
54606
|
function verifiedSiblingCacheAlias(agent, path, parent) {
|
|
54342
|
-
const link2 =
|
|
54343
|
-
if (
|
|
54607
|
+
const link2 = readlinkSync6(path), lexicalTarget = resolve14(parent, link2);
|
|
54608
|
+
if (isAbsolute14(link2) ? link2 !== lexicalTarget : dirname14(link2) !== ".")
|
|
54344
54609
|
return false;
|
|
54345
54610
|
const target = canonicalSystemPath(lexicalTarget);
|
|
54346
54611
|
if (dirname14(target) !== parent)
|
|
54347
54612
|
return false;
|
|
54348
|
-
if (!
|
|
54613
|
+
if (!lstatSync20(target, { throwIfNoEntry: false })?.isDirectory())
|
|
54349
54614
|
return false;
|
|
54350
54615
|
const scan = cacheScans.get(target);
|
|
54351
54616
|
if (!scan?.complete || scan.entries > maxAliasProofEntries)
|
|
@@ -54370,7 +54635,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
54370
54635
|
return scan;
|
|
54371
54636
|
if (!existsSync13(path))
|
|
54372
54637
|
return scan;
|
|
54373
|
-
const stat =
|
|
54638
|
+
const stat = lstatSync20(path);
|
|
54374
54639
|
if (stat.isFile()) {
|
|
54375
54640
|
if (agent === "sumi" && depth === 1 && path.endsWith(".md"))
|
|
54376
54641
|
throw new Error("NATIVE_SKILL_DRIFT: flat Sumi skill documents require a dedicated migration adapter");
|
|
@@ -54387,7 +54652,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
54387
54652
|
const marker = join28(path, ".hasna-skills.json");
|
|
54388
54653
|
if (existsSync13(marker)) {
|
|
54389
54654
|
try {
|
|
54390
|
-
managed = JSON.parse(
|
|
54655
|
+
managed = JSON.parse(readFileSync16(marker, "utf8")).managedBy === "@hasna/skills";
|
|
54391
54656
|
} catch {}
|
|
54392
54657
|
}
|
|
54393
54658
|
const bridge = (!vendor || agent === "sumi") && isOwnedCliBridge(path, bridgePaths);
|
|
@@ -54419,7 +54684,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
54419
54684
|
if (isVendor && !options.includeVendor)
|
|
54420
54685
|
continue;
|
|
54421
54686
|
const child = join28(path, name);
|
|
54422
|
-
if (isVendor &&
|
|
54687
|
+
if (isVendor && lstatSync20(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
54423
54688
|
const target = statSync9(child, { throwIfNoEntry: false });
|
|
54424
54689
|
if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child, path)) {
|
|
54425
54690
|
scan.entries++;
|
|
@@ -54462,7 +54727,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
|
|
|
54462
54727
|
}
|
|
54463
54728
|
function readOptional(path) {
|
|
54464
54729
|
assertSafePath(path);
|
|
54465
|
-
return existsSync13(path) ?
|
|
54730
|
+
return existsSync13(path) ? readFileSync16(path, "utf8") : null;
|
|
54466
54731
|
}
|
|
54467
54732
|
function jsonObject(text2, path) {
|
|
54468
54733
|
if (text2 === null)
|
|
@@ -54794,23 +55059,23 @@ function projectedHookAcl(path, observed) {
|
|
|
54794
55059
|
if (process.platform !== "darwin")
|
|
54795
55060
|
return;
|
|
54796
55061
|
const identity6 = (stat) => `${stat.dev}:${stat.ino}:${stat.ctimeNs}:${stat.uid}:${stat.mode}:${stat.nlink}:${stat.size}:${stat.mtimeNs}`;
|
|
54797
|
-
const fd =
|
|
55062
|
+
const fd = openSync11(path, constants12.O_RDONLY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK | (observed.isDirectory() ? constants12.O_DIRECTORY : 0));
|
|
54798
55063
|
try {
|
|
54799
|
-
if (identity6(
|
|
55064
|
+
if (identity6(fstatSync11(fd, { bigint: true })) !== identity6(observed) || !hasTrustedDarwinAcl(fd, true) || identity6(fstatSync11(fd, { bigint: true })) !== identity6(observed) || identity6(lstatSync20(path, { bigint: true })) !== identity6(observed))
|
|
54800
55065
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
54801
55066
|
} finally {
|
|
54802
|
-
|
|
55067
|
+
closeSync11(fd);
|
|
54803
55068
|
}
|
|
54804
55069
|
}
|
|
54805
55070
|
function projectedHookExecutable(command, expectedResolved) {
|
|
54806
55071
|
try {
|
|
54807
|
-
if (!
|
|
55072
|
+
if (!isAbsolute14(command) || /[\0\r\n]/.test(command) || resolve14(command) !== command)
|
|
54808
55073
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
54809
55074
|
command = canonicalSystemPath(command);
|
|
54810
55075
|
const parents2 = (file = command) => {
|
|
54811
55076
|
const result2 = [];
|
|
54812
55077
|
for (let path = dirname14(file);; path = dirname14(path)) {
|
|
54813
|
-
const stat =
|
|
55078
|
+
const stat = lstatSync20(path, { bigint: true });
|
|
54814
55079
|
if (!stat.isDirectory() || (stat.mode & 0o022n) !== 0n && !(stat.uid === 0n && (stat.mode & 0o1000n) !== 0n))
|
|
54815
55080
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
54816
55081
|
projectedHookAcl(path, stat);
|
|
@@ -54820,13 +55085,22 @@ function projectedHookExecutable(command, expectedResolved) {
|
|
|
54820
55085
|
}
|
|
54821
55086
|
return result2;
|
|
54822
55087
|
};
|
|
54823
|
-
const parentIdentity = parents2(), link2 =
|
|
55088
|
+
const parentIdentity = parents2(), link2 = lstatSync20(command, { bigint: true });
|
|
54824
55089
|
if (link2.uid !== BigInt(process.getuid()) || !link2.isFile() && !link2.isSymbolicLink())
|
|
54825
55090
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
54826
55091
|
const linkIdentity = (stat) => `${stat.dev}:${stat.ino}:${stat.mode}:${stat.uid}:${stat.ctimeNs}`;
|
|
54827
|
-
const
|
|
55092
|
+
const target = resolveLauncherCommand(command), resolved = target.entry;
|
|
54828
55093
|
if (expectedResolved !== undefined && resolved !== expectedResolved)
|
|
54829
55094
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
55095
|
+
let launcher, launcherParentIdentity;
|
|
55096
|
+
if (target.pinned) {
|
|
55097
|
+
launcherParentIdentity = parents2(target.physical);
|
|
55098
|
+
launcher = snapshot(target.physical, false);
|
|
55099
|
+
projectedHookAcl(launcher.file, launcher.stat);
|
|
55100
|
+
if (launcher.sha256 !== target.pinned.sha256 || (launcher.stat.mode & 0o100n) === 0n)
|
|
55101
|
+
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
55102
|
+
assertPinnedLauncherRuntimeSafe(target.pinned.runtime);
|
|
55103
|
+
}
|
|
54830
55104
|
const resolvedParentIdentity = parents2(resolved);
|
|
54831
55105
|
const manifest = snapshot(join28(dirname14(dirname14(resolved)), "package.json"), false, { readOnlyPackage: true });
|
|
54832
55106
|
projectedHookAcl(manifest.file, manifest.stat);
|
|
@@ -54839,8 +55113,15 @@ function projectedHookExecutable(command, expectedResolved) {
|
|
|
54839
55113
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
54840
55114
|
const recheck = () => {
|
|
54841
55115
|
try {
|
|
54842
|
-
|
|
55116
|
+
const again = resolveLauncherCommand(command);
|
|
55117
|
+
if (again.entry !== resolved || again.physical !== target.physical || linkIdentity(lstatSync20(command, { bigint: true })) !== linkIdentity(link2) || !isDeepStrictEqual7(parents2(), parentIdentity) || !isDeepStrictEqual7(parents2(resolved), resolvedParentIdentity))
|
|
54843
55118
|
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
55119
|
+
if (launcher) {
|
|
55120
|
+
if (!isDeepStrictEqual7(parents2(target.physical), launcherParentIdentity))
|
|
55121
|
+
hookProjectionRefusal("EXECUTABLE_UNVERIFIED");
|
|
55122
|
+
projectedHookAcl(launcher.file, launcher.stat);
|
|
55123
|
+
unchanged2(launcher);
|
|
55124
|
+
}
|
|
54844
55125
|
projectedHookAcl(cli.file, cli.stat);
|
|
54845
55126
|
projectedHookAcl(manifest.file, manifest.stat);
|
|
54846
55127
|
unchanged2(cli);
|
|
@@ -55105,7 +55386,7 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
55105
55386
|
if (change.before !== null) {
|
|
55106
55387
|
const backup = join28(backupRoot, `${index}-${sha3(change.path).slice(0, 12)}.backup`);
|
|
55107
55388
|
writeFileSync6(backup, change.before, { mode: 384, flag: "wx" });
|
|
55108
|
-
if (
|
|
55389
|
+
if (readFileSync16(backup, "utf8") !== change.before)
|
|
55109
55390
|
throw new Error("Native configuration preservation readback failed");
|
|
55110
55391
|
backups.push(backup);
|
|
55111
55392
|
}
|
|
@@ -55168,11 +55449,11 @@ function applyAgentIntegrationUnlocked(plan, options = {}, assertCurrent) {
|
|
|
55168
55449
|
}
|
|
55169
55450
|
function syncArchiveDirectory(path) {
|
|
55170
55451
|
assertSafePath(path);
|
|
55171
|
-
const descriptor =
|
|
55452
|
+
const descriptor = openSync11(path, constants12.O_RDONLY | constants12.O_DIRECTORY | constants12.O_NOFOLLOW | constants12.O_NONBLOCK);
|
|
55172
55453
|
try {
|
|
55173
|
-
|
|
55454
|
+
fsyncSync5(descriptor);
|
|
55174
55455
|
} finally {
|
|
55175
|
-
|
|
55456
|
+
closeSync11(descriptor);
|
|
55176
55457
|
}
|
|
55177
55458
|
}
|
|
55178
55459
|
function writeArchiveJournal(path, value) {
|
|
@@ -55180,18 +55461,18 @@ function writeArchiveJournal(path, value) {
|
|
|
55180
55461
|
const temporary = `${path}.skills-${randomUUID6()}`;
|
|
55181
55462
|
let descriptor;
|
|
55182
55463
|
try {
|
|
55183
|
-
descriptor =
|
|
55464
|
+
descriptor = openSync11(temporary, constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
|
|
55184
55465
|
writeFileSync6(descriptor, `${JSON.stringify(value)}
|
|
55185
55466
|
`);
|
|
55186
|
-
|
|
55187
|
-
|
|
55467
|
+
fsyncSync5(descriptor);
|
|
55468
|
+
closeSync11(descriptor);
|
|
55188
55469
|
descriptor = undefined;
|
|
55189
55470
|
renameSync3(temporary, path);
|
|
55190
55471
|
syncArchiveDirectory(dirname14(path));
|
|
55191
55472
|
} finally {
|
|
55192
55473
|
if (descriptor !== undefined)
|
|
55193
|
-
|
|
55194
|
-
if (
|
|
55474
|
+
closeSync11(descriptor);
|
|
55475
|
+
if (lstatSync20(temporary, { throwIfNoEntry: false }))
|
|
55195
55476
|
unlinkSync4(temporary);
|
|
55196
55477
|
}
|
|
55197
55478
|
}
|
|
@@ -55237,7 +55518,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
55237
55518
|
const moved = [];
|
|
55238
55519
|
const verifyArchive = (entry) => {
|
|
55239
55520
|
assertSafePath(entry.archive);
|
|
55240
|
-
const stat =
|
|
55521
|
+
const stat = lstatSync20(entry.archive);
|
|
55241
55522
|
if (entry.discoveryOnly ? !stat.isFile() : !stat.isDirectory())
|
|
55242
55523
|
throw new Error("Archive type changed");
|
|
55243
55524
|
if ((entry.discoveryOnly ? sha3(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
|
|
@@ -55288,7 +55569,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
55288
55569
|
recheckRootAliases(aliases);
|
|
55289
55570
|
assertSafePath(entry.source);
|
|
55290
55571
|
assertSafePath(entry.archive);
|
|
55291
|
-
if (
|
|
55572
|
+
if (lstatSync20(entry.source, { throwIfNoEntry: false })) {
|
|
55292
55573
|
entry.status = "recovery-required";
|
|
55293
55574
|
entry.conflict = "source-occupied";
|
|
55294
55575
|
continue;
|
|
@@ -55305,7 +55586,7 @@ function archiveNativeSkillsUnlocked(inventory, options, assertCurrent) {
|
|
|
55305
55586
|
syncArchiveDirectory(dirname14(entry.source));
|
|
55306
55587
|
unlinkSync4(entry.archive);
|
|
55307
55588
|
} else {
|
|
55308
|
-
if (
|
|
55589
|
+
if (lstatSync20(entry.source, { throwIfNoEntry: false })) {
|
|
55309
55590
|
entry.status = "recovery-required";
|
|
55310
55591
|
entry.conflict = "source-occupied";
|
|
55311
55592
|
continue;
|
|
@@ -55338,12 +55619,12 @@ function isInertCodexPluginCacheCopy(entry, cache3, allowedHostPaths, read2) {
|
|
|
55338
55619
|
return false;
|
|
55339
55620
|
const document3 = join28(entry.path, "SKILL.md");
|
|
55340
55621
|
const inside = relative6(cache3, entry.path);
|
|
55341
|
-
if (!inside ||
|
|
55622
|
+
if (!inside || isAbsolute14(inside) || inside.split(sep7).some((segment) => segment === ".."))
|
|
55342
55623
|
return false;
|
|
55343
55624
|
assertSafePath(entry.path);
|
|
55344
|
-
if (!
|
|
55625
|
+
if (!lstatSync20(cache3).isDirectory() || !lstatSync20(entry.path).isDirectory() || !lstatSync20(document3).isFile())
|
|
55345
55626
|
return false;
|
|
55346
|
-
if (
|
|
55627
|
+
if (realpathSync10.native(cache3) !== cache3 || realpathSync10.native(entry.path) !== entry.path || realpathSync10.native(document3) !== document3)
|
|
55347
55628
|
return false;
|
|
55348
55629
|
if (!classifyCodexPluginCacheDocument(document3, cache3, read2))
|
|
55349
55630
|
return false;
|
|
@@ -55535,7 +55816,7 @@ function assertNativeExportAllowed(dataDir3 = getDataDirReadOnly()) {
|
|
|
55535
55816
|
if (requiresCliSkillLoading(dataDir3))
|
|
55536
55817
|
throw new Error("NATIVE_SKILL_EXPORT_DISABLED: this station loads skills through the Skills CLI; use skills sync --selection-profile <id>");
|
|
55537
55818
|
}
|
|
55538
|
-
var sha3 = (data) =>
|
|
55819
|
+
var sha3 = (data) => createHash19("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
|
|
55539
55820
|
var init_agent_integration = __esm(() => {
|
|
55540
55821
|
init_sumi_settings_witness();
|
|
55541
55822
|
init_codex_corpus_write();
|
|
@@ -55555,6 +55836,7 @@ var init_agent_integration = __esm(() => {
|
|
|
55555
55836
|
init_agent_hermes();
|
|
55556
55837
|
init_claude_settings_witness();
|
|
55557
55838
|
init_codex_hook_trust_files();
|
|
55839
|
+
init_runtime_launcher();
|
|
55558
55840
|
HOOK_EVENTS = ["UserPromptSubmit", "SessionStart", "SubagentStart"];
|
|
55559
55841
|
ROOTS = NATIVE_SKILL_ROOTS;
|
|
55560
55842
|
});
|
|
@@ -55698,10 +55980,10 @@ var init_home_migration = __esm(() => {
|
|
|
55698
55980
|
import {
|
|
55699
55981
|
cpSync as cpSync2,
|
|
55700
55982
|
existsSync as existsSync15,
|
|
55701
|
-
lstatSync as
|
|
55983
|
+
lstatSync as lstatSync21,
|
|
55702
55984
|
mkdirSync as mkdirSync8,
|
|
55703
55985
|
mkdtempSync,
|
|
55704
|
-
readFileSync as
|
|
55986
|
+
readFileSync as readFileSync17,
|
|
55705
55987
|
readdirSync as readdirSync10,
|
|
55706
55988
|
renameSync as renameSync5,
|
|
55707
55989
|
rmSync as rmSync2,
|
|
@@ -55716,9 +55998,9 @@ function isSkillsOwnershipMarker(marker) {
|
|
|
55716
55998
|
function hasSkillsOwnershipMarker(dir) {
|
|
55717
55999
|
const path = join30(dir, SYNC_MARKER_FILE);
|
|
55718
56000
|
try {
|
|
55719
|
-
if (!
|
|
56001
|
+
if (!lstatSync21(path).isFile())
|
|
55720
56002
|
return false;
|
|
55721
|
-
const marker = JSON.parse(
|
|
56003
|
+
const marker = JSON.parse(readFileSync17(path, "utf8"));
|
|
55722
56004
|
return isSkillsOwnershipMarker(marker);
|
|
55723
56005
|
} catch {
|
|
55724
56006
|
return false;
|
|
@@ -55934,7 +56216,7 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
|
55934
56216
|
if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
|
|
55935
56217
|
let existingIsStub = false;
|
|
55936
56218
|
try {
|
|
55937
|
-
existingIsStub = isPointerSkillMd(
|
|
56219
|
+
existingIsStub = isPointerSkillMd(readFileSync17(skillMdPath, "utf-8"));
|
|
55938
56220
|
} catch {
|
|
55939
56221
|
existingIsStub = false;
|
|
55940
56222
|
}
|
|
@@ -55984,7 +56266,7 @@ function writeManagedSkillDirUnlocked(dir, skillMd, options, assertCurrent) {
|
|
|
55984
56266
|
assertCurrent();
|
|
55985
56267
|
renameDirectory(candidateDir, dir);
|
|
55986
56268
|
assertCurrent();
|
|
55987
|
-
if (
|
|
56269
|
+
if (readFileSync17(skillMdPath, "utf8") !== (skillMd.endsWith(`
|
|
55988
56270
|
`) ? skillMd : `${skillMd}
|
|
55989
56271
|
`))
|
|
55990
56272
|
throw new Error("Managed skill readback failed");
|
|
@@ -56016,7 +56298,7 @@ function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = f
|
|
|
56016
56298
|
if (kind === undefined || kind === "instruction" || preferBundledDocs) {
|
|
56017
56299
|
const skillMdPath = join30(skillPath, "SKILL.md");
|
|
56018
56300
|
if (existsSync15(skillMdPath))
|
|
56019
|
-
return
|
|
56301
|
+
return readFileSync17(skillMdPath, "utf-8");
|
|
56020
56302
|
}
|
|
56021
56303
|
return pointerSkillMd(name, description);
|
|
56022
56304
|
}
|
|
@@ -56067,7 +56349,7 @@ var init_skill_aliases = __esm(() => {
|
|
|
56067
56349
|
});
|
|
56068
56350
|
|
|
56069
56351
|
// src/lib/project-state.ts
|
|
56070
|
-
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as
|
|
56352
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync18, writeFileSync as writeFileSync9 } from "fs";
|
|
56071
56353
|
import { join as join31 } from "path";
|
|
56072
56354
|
function getProjectStateDir(targetDir = process.cwd()) {
|
|
56073
56355
|
return join31(targetDir, SKILLS_PROJECT_DIR);
|
|
@@ -56080,7 +56362,7 @@ function loadProjectConfig(targetDir = process.cwd()) {
|
|
|
56080
56362
|
if (!existsSync16(path))
|
|
56081
56363
|
return null;
|
|
56082
56364
|
try {
|
|
56083
|
-
return normalizeProjectConfig(JSON.parse(
|
|
56365
|
+
return normalizeProjectConfig(JSON.parse(readFileSync18(path, "utf-8")));
|
|
56084
56366
|
} catch {
|
|
56085
56367
|
return null;
|
|
56086
56368
|
}
|
|
@@ -56234,7 +56516,7 @@ __export(exports_installer, {
|
|
|
56234
56516
|
AGENT_TARGETS: () => AGENT_TARGETS,
|
|
56235
56517
|
AGENT_LABELS: () => AGENT_LABELS
|
|
56236
56518
|
});
|
|
56237
|
-
import { existsSync as existsSync17, readFileSync as
|
|
56519
|
+
import { existsSync as existsSync17, readFileSync as readFileSync19, rmSync as rmSync3 } from "fs";
|
|
56238
56520
|
import { join as join32 } from "path";
|
|
56239
56521
|
import { homedir as homedir5 } from "os";
|
|
56240
56522
|
function getSkillPath(name) {
|
|
@@ -56333,7 +56615,7 @@ function createLocalSkillManifest(name, generateSkillMd) {
|
|
|
56333
56615
|
let skillMd = "";
|
|
56334
56616
|
const skillMdPath = join32(sourcePath, "SKILL.md");
|
|
56335
56617
|
if (existsSync17(skillMdPath)) {
|
|
56336
|
-
skillMd =
|
|
56618
|
+
skillMd = readFileSync19(skillMdPath, "utf-8");
|
|
56337
56619
|
} else if (generateSkillMd) {
|
|
56338
56620
|
skillMd = generateSkillMd(name) ?? "";
|
|
56339
56621
|
} else {
|
|
@@ -56467,7 +56749,7 @@ function resolveAgentSkillMd(name, generateSkillMd) {
|
|
|
56467
56749
|
const sourcePath = getSkillPath(name);
|
|
56468
56750
|
const skillMdPath = join32(sourcePath, "SKILL.md");
|
|
56469
56751
|
if (existsSync17(skillMdPath))
|
|
56470
|
-
return
|
|
56752
|
+
return readFileSync19(skillMdPath, "utf-8");
|
|
56471
56753
|
if (generateSkillMd)
|
|
56472
56754
|
return generateSkillMd(name);
|
|
56473
56755
|
return generateMinimalSkillMd(name);
|
|
@@ -56523,14 +56805,14 @@ function readBundledSkillVersion(name) {
|
|
|
56523
56805
|
if (!existsSync17(pkgPath))
|
|
56524
56806
|
return "unknown";
|
|
56525
56807
|
try {
|
|
56526
|
-
const pkg = JSON.parse(
|
|
56808
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
|
|
56527
56809
|
return pkg.version || "unknown";
|
|
56528
56810
|
} catch {
|
|
56529
56811
|
return "unknown";
|
|
56530
56812
|
}
|
|
56531
56813
|
}
|
|
56532
56814
|
function readFileIfExists(path) {
|
|
56533
|
-
return existsSync17(path) ?
|
|
56815
|
+
return existsSync17(path) ? readFileSync19(path, "utf-8") : null;
|
|
56534
56816
|
}
|
|
56535
56817
|
function loadProjectConfigCompat(targetDir) {
|
|
56536
56818
|
return loadProjectConfig(targetDir);
|
|
@@ -56606,7 +56888,7 @@ __export(exports_skillinfo, {
|
|
|
56606
56888
|
generateEnvExample: () => generateEnvExample,
|
|
56607
56889
|
detectProjectSkills: () => detectProjectSkills
|
|
56608
56890
|
});
|
|
56609
|
-
import { existsSync as existsSync18, readFileSync as
|
|
56891
|
+
import { existsSync as existsSync18, readFileSync as readFileSync20 } from "fs";
|
|
56610
56892
|
import { join as join33 } from "path";
|
|
56611
56893
|
function isInstructionSkillDir(skillPath, meta) {
|
|
56612
56894
|
if (meta?.kind === "instruction")
|
|
@@ -56615,7 +56897,7 @@ function isInstructionSkillDir(skillPath, meta) {
|
|
|
56615
56897
|
if (!existsSync18(skillMdPath))
|
|
56616
56898
|
return false;
|
|
56617
56899
|
try {
|
|
56618
|
-
return parseSkillFrontmatter(
|
|
56900
|
+
return parseSkillFrontmatter(readFileSync20(skillMdPath, "utf-8"))?.kind === "instruction";
|
|
56619
56901
|
} catch {
|
|
56620
56902
|
return false;
|
|
56621
56903
|
}
|
|
@@ -56650,7 +56932,7 @@ function getSkillRequirements(name) {
|
|
|
56650
56932
|
const meta = getSkill(name);
|
|
56651
56933
|
let dependencies = {};
|
|
56652
56934
|
try {
|
|
56653
|
-
dependencies = JSON.parse(
|
|
56935
|
+
dependencies = JSON.parse(readFileSync20(join33(skillPath, "package.json"), "utf8")).dependencies || {};
|
|
56654
56936
|
} catch {}
|
|
56655
56937
|
return getSkillRequirementsFromContent(name, texts, dependencies, meta);
|
|
56656
56938
|
}
|
|
@@ -56739,7 +57021,7 @@ async function runSkill(name, args, options = {}) {
|
|
|
56739
57021
|
}
|
|
56740
57022
|
let entryPoint2;
|
|
56741
57023
|
try {
|
|
56742
|
-
const pkg = JSON.parse(
|
|
57024
|
+
const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
|
|
56743
57025
|
if (pkg.bin) {
|
|
56744
57026
|
const binValues = Object.values(pkg.bin);
|
|
56745
57027
|
entryPoint2 = binValues[0];
|
|
@@ -56784,7 +57066,7 @@ async function runSkill(name, args, options = {}) {
|
|
|
56784
57066
|
function detectProjectSkills(cwd2 = process.cwd()) {
|
|
56785
57067
|
let pkg;
|
|
56786
57068
|
try {
|
|
56787
|
-
pkg = JSON.parse(
|
|
57069
|
+
pkg = JSON.parse(readFileSync20(join33(cwd2, "package.json"), "utf8"));
|
|
56788
57070
|
} catch {
|
|
56789
57071
|
return { detected: [], recommended: [] };
|
|
56790
57072
|
}
|
|
@@ -56870,7 +57152,7 @@ function generateSkillMd(name) {
|
|
|
56870
57152
|
const pkgPath = join33(skillPath, "package.json");
|
|
56871
57153
|
if (existsSync18(pkgPath)) {
|
|
56872
57154
|
try {
|
|
56873
|
-
const pkg = JSON.parse(
|
|
57155
|
+
const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
|
|
56874
57156
|
if (pkg.bin) {
|
|
56875
57157
|
const binKeys = Object.keys(pkg.bin);
|
|
56876
57158
|
if (binKeys.length > 0)
|
|
@@ -56944,7 +57226,7 @@ function extractEnvVars(text2) {
|
|
|
56944
57226
|
function readIfExists(path) {
|
|
56945
57227
|
try {
|
|
56946
57228
|
if (existsSync18(path)) {
|
|
56947
|
-
return
|
|
57229
|
+
return readFileSync20(path, "utf-8");
|
|
56948
57230
|
}
|
|
56949
57231
|
} catch {}
|
|
56950
57232
|
return null;
|
|
@@ -57150,7 +57432,7 @@ var init_selection_resolver = __esm(() => {
|
|
|
57150
57432
|
});
|
|
57151
57433
|
|
|
57152
57434
|
// src/lib/plugin-projection.ts
|
|
57153
|
-
import { createHash as
|
|
57435
|
+
import { createHash as createHash20 } from "crypto";
|
|
57154
57436
|
import { posix } from "path";
|
|
57155
57437
|
function pluginRefusal(message) {
|
|
57156
57438
|
throw new SkillSelectionError("PLUGIN_ADMISSION_REFUSED", message);
|
|
@@ -57343,7 +57625,7 @@ function buildPluginProjection(entries) {
|
|
|
57343
57625
|
files.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
57344
57626
|
return { manifest, payloads: manifest.payloads, files, witnesses: pluginFileWitnesses(files), originalTreeDigest, projectionTreeDigest: pluginTreeDigest(files), removed: removed.length ? pluginFileWitnesses(removed) : [] };
|
|
57345
57627
|
}
|
|
57346
|
-
var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json", PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) =>
|
|
57628
|
+
var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json", PLUGIN_PROJECTION_LIMITS, pluginHash = (bytes) => createHash20("sha256").update(bytes).digest("hex"), MANIFEST_FIELDS;
|
|
57347
57629
|
var init_plugin_projection = __esm(() => {
|
|
57348
57630
|
init_selection_cache();
|
|
57349
57631
|
PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
|
|
@@ -57351,12 +57633,12 @@ var init_plugin_projection = __esm(() => {
|
|
|
57351
57633
|
});
|
|
57352
57634
|
|
|
57353
57635
|
// src/lib/plugin-projection-store.ts
|
|
57354
|
-
import { createHash as
|
|
57355
|
-
import { constants as
|
|
57356
|
-
import { dirname as dirname16, isAbsolute as
|
|
57636
|
+
import { createHash as createHash21, randomUUID as randomUUID7 } from "crypto";
|
|
57637
|
+
import { constants as constants13, closeSync as closeSync12, fchmodSync as fchmodSync2, fstatSync as fstatSync12, fsyncSync as fsyncSync6, linkSync as linkSync3, lstatSync as lstatSync22, mkdirSync as mkdirSync10, openSync as openSync12, opendirSync as opendirSync4, readSync as readSync9, renameSync as renameSync6, rmdirSync as rmdirSync3, rmSync as rmSync4, unlinkSync as unlinkSync5, writeSync as writeSync3 } from "fs";
|
|
57638
|
+
import { dirname as dirname16, isAbsolute as isAbsolute15, join as join34, parse as parse6, resolve as resolve15 } from "path";
|
|
57357
57639
|
function stat(path) {
|
|
57358
57640
|
try {
|
|
57359
|
-
return
|
|
57641
|
+
return lstatSync22(path, { bigint: true });
|
|
57360
57642
|
} catch (error) {
|
|
57361
57643
|
if (missing(error))
|
|
57362
57644
|
return null;
|
|
@@ -57364,7 +57646,7 @@ function stat(path) {
|
|
|
57364
57646
|
}
|
|
57365
57647
|
}
|
|
57366
57648
|
function canonical6(path) {
|
|
57367
|
-
pluginNeed(typeof path === "string" && path.length <= 8192 &&
|
|
57649
|
+
pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute15(path) && resolve15(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
|
|
57368
57650
|
}
|
|
57369
57651
|
function owner(stats, system = false) {
|
|
57370
57652
|
const current = uid();
|
|
@@ -57432,8 +57714,8 @@ function readBytes(path, maximum, kind) {
|
|
|
57432
57714
|
fileShape(before2, maximum, kind);
|
|
57433
57715
|
let fd;
|
|
57434
57716
|
try {
|
|
57435
|
-
fd =
|
|
57436
|
-
const opened =
|
|
57717
|
+
fd = openSync12(path, READ_FLAGS);
|
|
57718
|
+
const opened = fstatSync12(fd, { bigint: true });
|
|
57437
57719
|
same3(before2, opened);
|
|
57438
57720
|
fileShape(opened, maximum, kind);
|
|
57439
57721
|
const bytes = new Uint8Array(Number(opened.size));
|
|
@@ -57444,7 +57726,7 @@ function readBytes(path, maximum, kind) {
|
|
|
57444
57726
|
offset += count;
|
|
57445
57727
|
}
|
|
57446
57728
|
pluginNeed(readSync9(fd, new Uint8Array(1), 0, 1, null) === 0, "Plugin file grew while being read");
|
|
57447
|
-
same3(opened,
|
|
57729
|
+
same3(opened, fstatSync12(fd, { bigint: true }));
|
|
57448
57730
|
same3(opened, stat(path));
|
|
57449
57731
|
verifyAncestors(chain);
|
|
57450
57732
|
return bytes;
|
|
@@ -57454,7 +57736,7 @@ function readBytes(path, maximum, kind) {
|
|
|
57454
57736
|
return pluginRefusal("Cannot safely read plugin file");
|
|
57455
57737
|
} finally {
|
|
57456
57738
|
if (fd !== undefined)
|
|
57457
|
-
|
|
57739
|
+
closeSync12(fd);
|
|
57458
57740
|
}
|
|
57459
57741
|
}
|
|
57460
57742
|
function exactPaths(entries) {
|
|
@@ -57564,16 +57846,16 @@ function verifyPluginTree(root, witnesses) {
|
|
|
57564
57846
|
function writeExclusive(path, bytes, mode) {
|
|
57565
57847
|
let fd, created;
|
|
57566
57848
|
try {
|
|
57567
|
-
fd =
|
|
57568
|
-
|
|
57569
|
-
created =
|
|
57849
|
+
fd = openSync12(path, WRITE_FLAGS, mode);
|
|
57850
|
+
fchmodSync2(fd, mode);
|
|
57851
|
+
created = fstatSync12(fd, { bigint: true });
|
|
57570
57852
|
let offset = 0;
|
|
57571
57853
|
while (offset < bytes.byteLength) {
|
|
57572
|
-
const count =
|
|
57854
|
+
const count = writeSync3(fd, bytes, offset, bytes.byteLength - offset);
|
|
57573
57855
|
pluginNeed(count > 0, "Plugin file write did not progress");
|
|
57574
57856
|
offset += count;
|
|
57575
57857
|
}
|
|
57576
|
-
|
|
57858
|
+
fsyncSync6(fd);
|
|
57577
57859
|
} catch (error) {
|
|
57578
57860
|
if (created) {
|
|
57579
57861
|
same3(created, stat(path), true);
|
|
@@ -57582,7 +57864,7 @@ function writeExclusive(path, bytes, mode) {
|
|
|
57582
57864
|
throw error;
|
|
57583
57865
|
} finally {
|
|
57584
57866
|
if (fd !== undefined)
|
|
57585
|
-
|
|
57867
|
+
closeSync12(fd);
|
|
57586
57868
|
}
|
|
57587
57869
|
}
|
|
57588
57870
|
function materializePluginTree(root, entries) {
|
|
@@ -57685,11 +57967,11 @@ function pluginExecutableDigest(path) {
|
|
|
57685
57967
|
fileShape(before2, maximum, "executable");
|
|
57686
57968
|
let fd;
|
|
57687
57969
|
try {
|
|
57688
|
-
fd =
|
|
57689
|
-
const opened =
|
|
57970
|
+
fd = openSync12(path, READ_FLAGS);
|
|
57971
|
+
const opened = fstatSync12(fd, { bigint: true });
|
|
57690
57972
|
same3(before2, opened);
|
|
57691
57973
|
fileShape(opened, maximum, "executable");
|
|
57692
|
-
const hash2 =
|
|
57974
|
+
const hash2 = createHash21("sha256"), buffer = new Uint8Array(64 * 1024);
|
|
57693
57975
|
let remaining = Number(opened.size);
|
|
57694
57976
|
while (remaining > 0) {
|
|
57695
57977
|
const count = readSync9(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
|
|
@@ -57698,7 +57980,7 @@ function pluginExecutableDigest(path) {
|
|
|
57698
57980
|
remaining -= count;
|
|
57699
57981
|
}
|
|
57700
57982
|
pluginNeed(readSync9(fd, buffer, 0, 1, null) === 0, "Plugin executable grew during hashing");
|
|
57701
|
-
same3(opened,
|
|
57983
|
+
same3(opened, fstatSync12(fd, { bigint: true }));
|
|
57702
57984
|
same3(opened, stat(path));
|
|
57703
57985
|
verifyAncestors(chain);
|
|
57704
57986
|
return `sha256:${hash2.digest("hex")}`;
|
|
@@ -57708,14 +57990,14 @@ function pluginExecutableDigest(path) {
|
|
|
57708
57990
|
return pluginRefusal("Cannot safely hash plugin executable");
|
|
57709
57991
|
} finally {
|
|
57710
57992
|
if (fd !== undefined)
|
|
57711
|
-
|
|
57993
|
+
closeSync12(fd);
|
|
57712
57994
|
}
|
|
57713
57995
|
}
|
|
57714
57996
|
var READ_FLAGS, WRITE_FLAGS, uid = () => typeof process.getuid === "function" ? BigInt(process.getuid()) : undefined, missing = (error) => Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
|
|
57715
57997
|
var init_plugin_projection_store = __esm(() => {
|
|
57716
57998
|
init_plugin_projection();
|
|
57717
|
-
READ_FLAGS =
|
|
57718
|
-
WRITE_FLAGS =
|
|
57999
|
+
READ_FLAGS = constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK;
|
|
58000
|
+
WRITE_FLAGS = constants13.O_WRONLY | constants13.O_CREAT | constants13.O_EXCL | constants13.O_NOFOLLOW | constants13.O_NONBLOCK;
|
|
57719
58001
|
});
|
|
57720
58002
|
|
|
57721
58003
|
// src/lib/selected-manifest.ts
|
|
@@ -57746,7 +58028,7 @@ var init_selected_manifest = __esm(() => {
|
|
|
57746
58028
|
|
|
57747
58029
|
// src/lib/plugin-admission.ts
|
|
57748
58030
|
import { homedir as homedir6 } from "os";
|
|
57749
|
-
import { isAbsolute as
|
|
58031
|
+
import { isAbsolute as isAbsolute16, join as join35, resolve as resolve16 } from "path";
|
|
57750
58032
|
function pluginAdmissionRoot() {
|
|
57751
58033
|
return join35(homedir6(), ".hasna", "skills", "plugin-admission");
|
|
57752
58034
|
}
|
|
@@ -57759,7 +58041,7 @@ function validatePluginTarget(value) {
|
|
|
57759
58041
|
for (const registration of value.registrations) {
|
|
57760
58042
|
pluginKeys(registration, ["scope", "projectPath"]);
|
|
57761
58043
|
pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
|
|
57762
|
-
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" &&
|
|
58044
|
+
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute16(registration.projectPath) && resolve16(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
|
|
57763
58045
|
const key = JSON.stringify([registration.scope, registration.projectPath]);
|
|
57764
58046
|
pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
|
|
57765
58047
|
scopes.add(key);
|
|
@@ -57767,7 +58049,7 @@ function validatePluginTarget(value) {
|
|
|
57767
58049
|
for (const key of ["native", "resolver"]) {
|
|
57768
58050
|
pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
|
|
57769
58051
|
pluginText(value[key].executable);
|
|
57770
|
-
pluginNeed(
|
|
58052
|
+
pluginNeed(isAbsolute16(value[key].executable) && resolve16(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
|
|
57771
58053
|
pluginDigest(value[key].digest);
|
|
57772
58054
|
}
|
|
57773
58055
|
pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
|
|
@@ -57917,7 +58199,7 @@ function pluginResolverCommand(binding) {
|
|
|
57917
58199
|
}
|
|
57918
58200
|
function root(options) {
|
|
57919
58201
|
const path = options.storeRoot ?? pluginAdmissionRoot();
|
|
57920
|
-
pluginNeed(
|
|
58202
|
+
pluginNeed(isAbsolute16(path) && resolve16(path) === path, "Invalid plugin admission store root");
|
|
57921
58203
|
return path;
|
|
57922
58204
|
}
|
|
57923
58205
|
function pluginBindingPath(storeRoot, id) {
|
|
@@ -58124,8 +58406,8 @@ var init_plugin_admission = __esm(() => {
|
|
|
58124
58406
|
});
|
|
58125
58407
|
|
|
58126
58408
|
// src/lib/plugin-discovery.ts
|
|
58127
|
-
import { closeSync as
|
|
58128
|
-
import { basename as basename8, dirname as dirname17, isAbsolute as
|
|
58409
|
+
import { closeSync as closeSync13, constants as constants14, fstatSync as fstatSync13, lstatSync as lstatSync23, openSync as openSync13, opendirSync as opendirSync5, readSync as readSync10 } from "fs";
|
|
58410
|
+
import { basename as basename8, dirname as dirname17, isAbsolute as isAbsolute17, join as join36, resolve as resolve17 } from "path";
|
|
58129
58411
|
function validateManagedPluginWitnesses(value) {
|
|
58130
58412
|
pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
|
|
58131
58413
|
const seen = new Set;
|
|
@@ -58134,25 +58416,25 @@ function validateManagedPluginWitnesses(value) {
|
|
|
58134
58416
|
pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
|
|
58135
58417
|
seen.add(item.bindingId);
|
|
58136
58418
|
pluginText(item.storeRoot);
|
|
58137
|
-
pluginNeed(
|
|
58419
|
+
pluginNeed(isAbsolute17(item.storeRoot) && resolve17(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
|
|
58138
58420
|
}
|
|
58139
58421
|
}
|
|
58140
58422
|
function safe3(path) {
|
|
58141
58423
|
pluginText(path);
|
|
58142
|
-
pluginNeed(
|
|
58424
|
+
pluginNeed(isAbsolute17(path) && resolve17(path) === path, "Invalid plugin registry path");
|
|
58143
58425
|
for (let at2 = path;; at2 = dirname17(at2)) {
|
|
58144
|
-
pluginNeed(!
|
|
58426
|
+
pluginNeed(!lstatSync23(at2, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
|
|
58145
58427
|
if (at2 === dirname17(at2))
|
|
58146
58428
|
break;
|
|
58147
58429
|
}
|
|
58148
58430
|
}
|
|
58149
58431
|
function readRegistry(path) {
|
|
58150
58432
|
safe3(path);
|
|
58151
|
-
const initial2 =
|
|
58433
|
+
const initial2 = lstatSync23(path);
|
|
58152
58434
|
pluginNeed(initial2.isFile() && initial2.size <= 1024 * 1024, "Plugin registry is not a bounded regular file");
|
|
58153
|
-
const fd =
|
|
58435
|
+
const fd = openSync13(path, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
|
|
58154
58436
|
try {
|
|
58155
|
-
const opened =
|
|
58437
|
+
const opened = fstatSync13(fd);
|
|
58156
58438
|
pluginNeed(opened.isFile() && opened.ino === initial2.ino && opened.dev === initial2.dev, "Plugin registry changed during open");
|
|
58157
58439
|
const bytes = Buffer.alloc(1024 * 1024 + 1);
|
|
58158
58440
|
let length = 0;
|
|
@@ -58162,7 +58444,7 @@ function readRegistry(path) {
|
|
|
58162
58444
|
break;
|
|
58163
58445
|
length += count;
|
|
58164
58446
|
}
|
|
58165
|
-
const after2 =
|
|
58447
|
+
const after2 = fstatSync13(fd), current = lstatSync23(path);
|
|
58166
58448
|
safe3(path);
|
|
58167
58449
|
pluginNeed(length <= 1024 * 1024 && length === opened.size && after2.size === opened.size && after2.mtimeMs === opened.mtimeMs && after2.ctimeMs === opened.ctimeMs && current.dev === opened.dev && current.ino === opened.ino && current.mtimeMs === opened.mtimeMs && current.ctimeMs === opened.ctimeMs, "Plugin registry changed during read");
|
|
58168
58450
|
let value;
|
|
@@ -58174,7 +58456,7 @@ function readRegistry(path) {
|
|
|
58174
58456
|
pluginNeed(pluginObject(value) && value.version === 2 && pluginObject(value.plugins), "Unsupported native plugin registry schema");
|
|
58175
58457
|
return { value, rawDigest: pluginHash(bytes.subarray(0, length)) };
|
|
58176
58458
|
} finally {
|
|
58177
|
-
|
|
58459
|
+
closeSync13(fd);
|
|
58178
58460
|
}
|
|
58179
58461
|
}
|
|
58180
58462
|
function nativeVersionMatches(version, receipt) {
|
|
@@ -58235,7 +58517,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
58235
58517
|
return Object.fromEntries(Object.entries(row).filter(([key]) => !["version", "installPath", "sourceProducerPath", "previousProducerPaths", "lastUpdated"].includes(key)));
|
|
58236
58518
|
});
|
|
58237
58519
|
safe3(cacheRoot);
|
|
58238
|
-
const before2 =
|
|
58520
|
+
const before2 = lstatSync23(cacheRoot);
|
|
58239
58521
|
pluginNeed(before2.isDirectory(), "Invalid managed plugin cache root");
|
|
58240
58522
|
const directory = opendirSync5(cacheRoot), names = [];
|
|
58241
58523
|
try {
|
|
@@ -58258,7 +58540,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
58258
58540
|
}
|
|
58259
58541
|
for (const row of rows)
|
|
58260
58542
|
pluginNeed(names.includes(row.version), "Managed native plugin installation is missing");
|
|
58261
|
-
const after2 =
|
|
58543
|
+
const after2 = lstatSync23(cacheRoot);
|
|
58262
58544
|
safe3(cacheRoot);
|
|
58263
58545
|
pluginNeed(before2.dev === after2.dev && before2.ino === after2.ino && before2.mtimeMs === after2.mtimeMs && before2.ctimeMs === after2.ctimeMs, "Managed cache version membership changed during verification");
|
|
58264
58546
|
}
|
|
@@ -58272,20 +58554,20 @@ var init_plugin_discovery = __esm(() => {
|
|
|
58272
58554
|
});
|
|
58273
58555
|
|
|
58274
58556
|
// src/lib/claude-marketplace-registry.ts
|
|
58275
|
-
import { createHash as
|
|
58276
|
-
import { closeSync as
|
|
58277
|
-
import { basename as basename9, dirname as dirname18, isAbsolute as
|
|
58557
|
+
import { createHash as createHash22 } from "crypto";
|
|
58558
|
+
import { closeSync as closeSync14, constants as constants15, fstatSync as fstatSync14, lstatSync as lstatSync24, openSync as openSync14, readSync as readSync11 } from "fs";
|
|
58559
|
+
import { basename as basename9, dirname as dirname18, isAbsolute as isAbsolute18, resolve as resolve18 } from "path";
|
|
58278
58560
|
function need6(value, reason) {
|
|
58279
58561
|
if (!value)
|
|
58280
58562
|
throw new Error(`Claude marketplace registry ${reason}`);
|
|
58281
58563
|
}
|
|
58282
58564
|
function absolutePath3(value) {
|
|
58283
|
-
need6(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) &&
|
|
58565
|
+
need6(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute18(value) && resolve18(value) === value, "requires a normalized absolute path");
|
|
58284
58566
|
}
|
|
58285
58567
|
function parents2(path) {
|
|
58286
58568
|
const result2 = [];
|
|
58287
58569
|
for (let at2 = dirname18(path);; at2 = dirname18(at2)) {
|
|
58288
|
-
const stat2 =
|
|
58570
|
+
const stat2 = lstatSync24(at2, { bigint: true });
|
|
58289
58571
|
need6(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
58290
58572
|
result2.push([at2, stat2]);
|
|
58291
58573
|
if (at2 === dirname18(at2))
|
|
@@ -58296,12 +58578,12 @@ function readRegistry2(path, budget2) {
|
|
|
58296
58578
|
absolutePath3(path);
|
|
58297
58579
|
need6(basename9(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
58298
58580
|
need6(Number.isSafeInteger(budget2.remaining) && budget2.remaining >= 0, "has an invalid byte budget");
|
|
58299
|
-
const ancestors2 = parents2(path), initial2 =
|
|
58581
|
+
const ancestors2 = parents2(path), initial2 = lstatSync24(path, { bigint: true });
|
|
58300
58582
|
need6(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
58301
58583
|
need6(initial2.size <= BigInt(budget2.remaining), "exceeds its aggregate byte limit");
|
|
58302
|
-
const fd =
|
|
58584
|
+
const fd = openSync14(path, constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
|
|
58303
58585
|
try {
|
|
58304
|
-
const opened =
|
|
58586
|
+
const opened = fstatSync14(fd, { bigint: true });
|
|
58305
58587
|
need6(opened.isFile() && sameFile2(initial2, opened), "changed during open");
|
|
58306
58588
|
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
58307
58589
|
let length = 0;
|
|
@@ -58311,10 +58593,10 @@ function readRegistry2(path, budget2) {
|
|
|
58311
58593
|
break;
|
|
58312
58594
|
length += count;
|
|
58313
58595
|
}
|
|
58314
|
-
const after2 =
|
|
58596
|
+
const after2 = fstatSync14(fd, { bigint: true }), current = lstatSync24(path, { bigint: true });
|
|
58315
58597
|
need6(current.isFile() && sameFile2(opened, after2) && sameFile2(after2, current) && BigInt(length) === opened.size, "changed during read");
|
|
58316
58598
|
for (const [ancestor, before2] of ancestors2) {
|
|
58317
|
-
const now3 =
|
|
58599
|
+
const now3 = lstatSync24(ancestor, { bigint: true });
|
|
58318
58600
|
need6(now3.isDirectory() && before2.dev === now3.dev && before2.ino === now3.ino && before2.mode === now3.mode, "parent changed during read");
|
|
58319
58601
|
}
|
|
58320
58602
|
budget2.remaining -= length;
|
|
@@ -58324,7 +58606,7 @@ function readRegistry2(path, budget2) {
|
|
|
58324
58606
|
throw new Error("Claude marketplace registry is not strict UTF-8");
|
|
58325
58607
|
}
|
|
58326
58608
|
} finally {
|
|
58327
|
-
|
|
58609
|
+
closeSync14(fd);
|
|
58328
58610
|
}
|
|
58329
58611
|
}
|
|
58330
58612
|
function parse7(text2) {
|
|
@@ -58438,15 +58720,15 @@ function captureClaudeMarketplaceRegistry(path, budget2 = { remaining: 256 * 102
|
|
|
58438
58720
|
const value = parse7(readRegistry2(path, budget2));
|
|
58439
58721
|
for (const [, row] of value.entries)
|
|
58440
58722
|
normalizeRow(row);
|
|
58441
|
-
const
|
|
58442
|
-
return { path, hashMode: "claude-marketplace-registry", sha256:
|
|
58723
|
+
const sha2563 = createHash22("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
58724
|
+
return { path, hashMode: "claude-marketplace-registry", sha256: sha2563 };
|
|
58443
58725
|
}
|
|
58444
58726
|
function captureClaudeMarketplaceRegistryV2(path, budget2 = { remaining: 256 * 1024 * 1024 }) {
|
|
58445
58727
|
const value = parse7(readRegistry2(path, budget2));
|
|
58446
58728
|
for (const [, row] of value.entries)
|
|
58447
58729
|
normalizeRow(row, 2);
|
|
58448
|
-
const
|
|
58449
|
-
return { path, hashMode: "claude-marketplace-registry-v2", sha256:
|
|
58730
|
+
const sha2563 = createHash22("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
|
|
58731
|
+
return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2563 };
|
|
58450
58732
|
}
|
|
58451
58733
|
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS, sameFile2 = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs, field = (object6, key) => object6.entries.find(([name]) => name === key)?.[1];
|
|
58452
58734
|
var init_claude_marketplace_registry = __esm(() => {
|
|
@@ -58588,7 +58870,7 @@ var fail3 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and c
|
|
|
58588
58870
|
var init_codex_hook_trust_layout = () => {};
|
|
58589
58871
|
|
|
58590
58872
|
// src/lib/codex-hook-additions-review.ts
|
|
58591
|
-
import { isAbsolute as
|
|
58873
|
+
import { isAbsolute as isAbsolute19 } from "path";
|
|
58592
58874
|
import { isDeepStrictEqual as isDeepStrictEqual9 } from "util";
|
|
58593
58875
|
function exactKeys2(value, keys2) {
|
|
58594
58876
|
need5(value && typeof value === "object" && !Array.isArray(value) && isDeepStrictEqual9(Object.keys(value).sort(), [...keys2].sort()), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
|
|
@@ -58602,7 +58884,7 @@ function readReviewedAdditionTrustStates(proof, before2, current, journalHooks)
|
|
|
58602
58884
|
return captured.states;
|
|
58603
58885
|
}
|
|
58604
58886
|
function reviewNativeHookAdditions(options) {
|
|
58605
|
-
need5(
|
|
58887
|
+
need5(isAbsolute19(options.path), "RECONCILE_ADDITIONS_REVIEW_PATH");
|
|
58606
58888
|
const reviewFile = snapshot(options.path, true), review = JSON.parse(reviewFile.text);
|
|
58607
58889
|
exactKeys2(review, ["version", "kind", "reason", "producerEvidence", "journalIntentSha256", "policySha256", "configCurrentSha256", "hooksCurrentSha256", "producerBefore", "additions"]);
|
|
58608
58890
|
need5((review.version === 1 || review.version === 2) && review.kind === "native-hook-additions" && text2(review.reason) && text2(review.producerEvidence), "RECONCILE_ADDITIONS_REVIEW_SCHEMA");
|
|
@@ -58610,7 +58892,7 @@ function reviewNativeHookAdditions(options) {
|
|
|
58610
58892
|
need5(hash2(review[name]) && review[name] === expected, "RECONCILE_ADDITIONS_REVIEW_CHANGED");
|
|
58611
58893
|
exactKeys2(review.producerBefore, ["configPath", "configSha256", "hooksPath", "hooksSha256"]);
|
|
58612
58894
|
const before2 = review.producerBefore;
|
|
58613
|
-
need5(
|
|
58895
|
+
need5(isAbsolute19(before2.configPath) && isAbsolute19(before2.hooksPath) && hash2(before2.configSha256) && hash2(before2.hooksSha256), "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
|
|
58614
58896
|
const producerConfig = snapshot(before2.configPath, true), producerHooks = snapshot(before2.hooksPath, true);
|
|
58615
58897
|
need5(producerConfig.sha256 === before2.configSha256 && producerHooks.sha256 === before2.hooksSha256 && producerHooks.sha256 === options.hooksBefore.sha256, "RECONCILE_ADDITIONS_PRODUCER_PREIMAGE");
|
|
58616
58898
|
const original = structure(options.configBefore.text), producer = structure(producerConfig.text), expectedProducer = structuredClone(original), originalKeys = options.journalHooks.map((hook) => hook.key);
|
|
@@ -58671,7 +58953,7 @@ var init_codex_hook_additions_review = __esm(() => {
|
|
|
58671
58953
|
});
|
|
58672
58954
|
|
|
58673
58955
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
58674
|
-
import { createHash as
|
|
58956
|
+
import { createHash as createHash23 } from "crypto";
|
|
58675
58957
|
import { isDeepStrictEqual as isDeepStrictEqual10 } from "util";
|
|
58676
58958
|
function createCodexHookDiscoveryRecovery(binding, before2, current, hooks, additions) {
|
|
58677
58959
|
const journalHooks = hooks.map(({ key, currentHash }) => ({ key, currentHash }));
|
|
@@ -58721,7 +59003,7 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
|
|
|
58721
59003
|
need5(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
58722
59004
|
return true;
|
|
58723
59005
|
}
|
|
58724
|
-
var sha4 = (text3) =>
|
|
59006
|
+
var sha4 = (text3) => createHash23("sha256").update(text3).digest("hex"), fields, structure2 = (text3) => JSON.parse(JSON.stringify(Bun.TOML.parse(text3))), proofs2;
|
|
58725
59007
|
var init_codex_hook_discovery_recovery = __esm(() => {
|
|
58726
59008
|
init_codex_hook_trust_files();
|
|
58727
59009
|
init_codex_hook_trust_layout();
|
|
@@ -58732,9 +59014,9 @@ var init_codex_hook_discovery_recovery = __esm(() => {
|
|
|
58732
59014
|
});
|
|
58733
59015
|
|
|
58734
59016
|
// src/lib/agent-discovery.ts
|
|
58735
|
-
import { createHash as
|
|
58736
|
-
import { lstatSync as
|
|
58737
|
-
import { basename as basename10, dirname as dirname19, isAbsolute as
|
|
59017
|
+
import { createHash as createHash24 } from "crypto";
|
|
59018
|
+
import { lstatSync as lstatSync25, readFileSync as readFileSync21, readdirSync as readdirSync11, realpathSync as realpathSync11 } from "fs";
|
|
59019
|
+
import { basename as basename10, dirname as dirname19, isAbsolute as isAbsolute20, join as join37, resolve as resolve19, sep as sep8 } from "path";
|
|
58738
59020
|
import { isDeepStrictEqual as isDeepStrictEqual11 } from "util";
|
|
58739
59021
|
function parseConfig(text3, path, toml = false) {
|
|
58740
59022
|
try {
|
|
@@ -58747,10 +59029,10 @@ function parseConfig(text3, path, toml = false) {
|
|
|
58747
59029
|
}
|
|
58748
59030
|
}
|
|
58749
59031
|
function safe4(path) {
|
|
58750
|
-
if (!
|
|
59032
|
+
if (!isAbsolute20(path) || path.includes("\x00"))
|
|
58751
59033
|
throw new Error("Expected an absolute native discovery path");
|
|
58752
59034
|
for (let cursor = path;; cursor = dirname19(cursor)) {
|
|
58753
|
-
if (
|
|
59035
|
+
if (lstatSync25(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
58754
59036
|
throw new Error(`Refusing symlink native discovery input: ${cursor}`);
|
|
58755
59037
|
if (dirname19(cursor) === cursor)
|
|
58756
59038
|
break;
|
|
@@ -58760,12 +59042,12 @@ function read2(path, changes) {
|
|
|
58760
59042
|
safe4(path);
|
|
58761
59043
|
if (changes?.has(path))
|
|
58762
59044
|
return changes.get(path);
|
|
58763
|
-
const stat2 =
|
|
59045
|
+
const stat2 = lstatSync25(path, { throwIfNoEntry: false });
|
|
58764
59046
|
if (!stat2)
|
|
58765
59047
|
return null;
|
|
58766
59048
|
if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
|
|
58767
59049
|
throw new Error(`Unsupported or oversized native discovery input: ${path}`);
|
|
58768
|
-
return
|
|
59050
|
+
return readFileSync21(path, "utf8");
|
|
58769
59051
|
}
|
|
58770
59052
|
function projectNativeDiscoveryFields(text3, format, fields2, path) {
|
|
58771
59053
|
const object6 = format === "yaml" ? parseHermesConfig(text3) : parseConfig(text3, path, format === "toml");
|
|
@@ -58811,10 +59093,10 @@ function projected(source, changes, budget2 = discoveryByteBudget()) {
|
|
|
58811
59093
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") {
|
|
58812
59094
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256) || changes?.has(source.path))
|
|
58813
59095
|
throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
|
|
58814
|
-
const
|
|
58815
|
-
if (
|
|
59096
|
+
const sha2563 = (source.hashMode === "claude-marketplace-registry-v2" ? captureClaudeMarketplaceRegistryV2 : captureClaudeMarketplaceRegistry)(source.path, budget2).sha256;
|
|
59097
|
+
if (sha2563 !== source.sha256)
|
|
58816
59098
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
58817
|
-
return
|
|
59099
|
+
return sha2563;
|
|
58818
59100
|
}
|
|
58819
59101
|
if (source.hashMode === "claude-plugin-registry") {
|
|
58820
59102
|
if (source.format !== undefined || source.fields !== undefined || !source.managedPlugins || changes?.has(source.path))
|
|
@@ -58851,7 +59133,7 @@ function absentCodexSkillRoots(binding) {
|
|
|
58851
59133
|
return [];
|
|
58852
59134
|
if (binding.agent !== "codex" || !Array.isArray(controls) || controls.length > 4096)
|
|
58853
59135
|
throw new Error("Invalid disabled Codex discovery proof");
|
|
58854
|
-
if (binding.method !== "reviewed" || controls.every((control) =>
|
|
59136
|
+
if (binding.method !== "reviewed" || controls.every((control) => lstatSync25(control.pluginParent, { throwIfNoEntry: false })))
|
|
58855
59137
|
return [];
|
|
58856
59138
|
const cache3 = dirname19(dirname19(controls[0].pluginParent)), config = join37(dirname19(dirname19(cache3)), "config.toml");
|
|
58857
59139
|
const source = binding.sources.find((source2) => source2.path === config && source2.sha256 !== null && source2.format === undefined && source2.fields === undefined);
|
|
@@ -58919,7 +59201,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
58919
59201
|
continue;
|
|
58920
59202
|
const root2 = join37(cache3, ...parts.slice(0, 3));
|
|
58921
59203
|
safe4(root2);
|
|
58922
|
-
if (
|
|
59204
|
+
if (lstatSync25(root2, { throwIfNoEntry: false }))
|
|
58923
59205
|
continue;
|
|
58924
59206
|
const claude = dirname19(dirname19(cache3)), settings = join37(claude, "settings.json"), registry = join37(claude, "plugins/installed_plugins.json");
|
|
58925
59207
|
const full = (path) => binding.sources.find((item) => item.path === path && item.sha256 !== null && item.format === undefined && item.fields === undefined);
|
|
@@ -58938,7 +59220,7 @@ function absentRetiredClaudeRoots(binding) {
|
|
|
58938
59220
|
if (!Array.isArray(rows) || rows.length !== 1 || rows[0]?.scope !== "user" || typeof rows[0]?.installPath !== "string")
|
|
58939
59221
|
continue;
|
|
58940
59222
|
const active = rows[0].installPath;
|
|
58941
|
-
if (rows[0].version !== basename10(active) || resolve19(active) !== active || dirname19(active) !== dirname19(root2) || active === root2 || !
|
|
59223
|
+
if (rows[0].version !== basename10(active) || resolve19(active) !== active || dirname19(active) !== dirname19(root2) || active === root2 || !lstatSync25(active, { throwIfNoEntry: false })?.isDirectory() || realpathSync11(active) !== active)
|
|
58942
59224
|
continue;
|
|
58943
59225
|
const activeManifest = full(join37(active, ".claude-plugin/plugin.json"));
|
|
58944
59226
|
if (!activeManifest || projected(activeManifest) !== activeManifest.sha256)
|
|
@@ -58969,7 +59251,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
58969
59251
|
const projection = binding.codexRetiredMaterializations.directories;
|
|
58970
59252
|
if (projection.length !== ordinary.length || projection.some((item, index) => item.path !== ordinary[index]?.path))
|
|
58971
59253
|
throw new Error("Missing retired Codex directory projection");
|
|
58972
|
-
const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !
|
|
59254
|
+
const omitted = [...retiredRoots, ...(binding.codexRetiredMaterializations.parents ?? []).filter((parent) => !lstatSync25(parent, { throwIfNoEntry: false }))];
|
|
58973
59255
|
if (projection.every((item) => Array.isArray(item.entries)))
|
|
58974
59256
|
verifyDiscoveryDirectoryProjection(projection, omitted);
|
|
58975
59257
|
else {
|
|
@@ -58983,7 +59265,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
58983
59265
|
verifyDiscoveryDirectories(ordinary);
|
|
58984
59266
|
verifyDiscoveryDirectories(projected2, installationRoots);
|
|
58985
59267
|
}
|
|
58986
|
-
const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root2) => !
|
|
59268
|
+
const absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredRoots.filter((root2) => !lstatSync25(root2, { throwIfNoEntry: false }))];
|
|
58987
59269
|
const budget2 = discoveryByteBudget();
|
|
58988
59270
|
for (const source of binding.sources) {
|
|
58989
59271
|
assertMarketplaceBinding(binding, source);
|
|
@@ -59009,7 +59291,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
59009
59291
|
safe4(root2);
|
|
59010
59292
|
for (const root2 of absentRoots) {
|
|
59011
59293
|
safe4(root2);
|
|
59012
|
-
if (
|
|
59294
|
+
if (lstatSync25(root2, { throwIfNoEntry: false }))
|
|
59013
59295
|
throw new Error("Retired native materialization changed during discovery verification");
|
|
59014
59296
|
}
|
|
59015
59297
|
}
|
|
@@ -59048,19 +59330,19 @@ function assertMarketplaceBinding(binding, source) {
|
|
|
59048
59330
|
}
|
|
59049
59331
|
function rebindAgentDiscovery(binding, changes) {
|
|
59050
59332
|
const budget2 = discoveryByteBudget();
|
|
59051
|
-
const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !
|
|
59333
|
+
const installationRoots = codexInstallationRoots(binding), absentRoots = [...absentCodexSkillRoots(binding), ...absentRetiredClaudeRoots(binding), ...retiredCodexRoots(binding).filter((root2) => !lstatSync25(root2, { throwIfNoEntry: false }))];
|
|
59052
59334
|
const rebound = { ...binding, sources: binding.sources.map((source) => {
|
|
59053
59335
|
assertMarketplaceBinding(binding, source);
|
|
59054
59336
|
if (!changes.has(source.path) && (installationRoots.some((root2) => source.path.startsWith(root2 + sep8)) || absentRoots.some((root2) => source.path.startsWith(root2 + sep8)) && source.format === undefined && source.fields === undefined && source.managedPlugins === undefined && [undefined, "bytes"].includes(source.hashMode)))
|
|
59055
59337
|
return source;
|
|
59056
|
-
const
|
|
59057
|
-
if (!changes.has(source.path) &&
|
|
59338
|
+
const sha2563 = projected(source, changes, budget2);
|
|
59339
|
+
if (!changes.has(source.path) && sha2563 !== source.sha256)
|
|
59058
59340
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
59059
|
-
return { ...source, sha256:
|
|
59341
|
+
return { ...source, sha256: sha2563 };
|
|
59060
59342
|
}) };
|
|
59061
59343
|
for (const root2 of absentRoots) {
|
|
59062
59344
|
safe4(root2);
|
|
59063
|
-
if (
|
|
59345
|
+
if (lstatSync25(root2, { throwIfNoEntry: false }))
|
|
59064
59346
|
throw new Error("Retired native materialization changed during discovery rebinding");
|
|
59065
59347
|
}
|
|
59066
59348
|
return rebound;
|
|
@@ -59103,13 +59385,13 @@ function assertProjectDiscovery(agent, directories, home, canonical7 = resolve19
|
|
|
59103
59385
|
for (const name of ["plugin", "plugins"]) {
|
|
59104
59386
|
const path = canonical7(join37(directory, ".sumi", name));
|
|
59105
59387
|
safe4(path);
|
|
59106
|
-
if (
|
|
59388
|
+
if (lstatSync25(path, { throwIfNoEntry: false })?.isDirectory() && readdirSync11(path).length)
|
|
59107
59389
|
throw new Error(`NATIVE_SKILL_DRIFT: project Sumi plugins require a dedicated discovery review: ${path}`);
|
|
59108
59390
|
}
|
|
59109
59391
|
if (agent === "claude") {
|
|
59110
59392
|
const commands = canonical7(join37(directory, ".claude/commands"));
|
|
59111
59393
|
safe4(commands);
|
|
59112
|
-
if (
|
|
59394
|
+
if (lstatSync25(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync11(commands).length)
|
|
59113
59395
|
throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
|
|
59114
59396
|
}
|
|
59115
59397
|
}
|
|
@@ -59149,7 +59431,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59149
59431
|
if (config.skills !== undefined && (!Array.isArray(config.skills) || config.skills.some((path) => typeof path !== "string")))
|
|
59150
59432
|
unresolved("skills must be a string array");
|
|
59151
59433
|
for (const value of config.skills ?? []) {
|
|
59152
|
-
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(
|
|
59434
|
+
if (typeof value !== "string" || /[\0$]/.test(value) || !value || !(isAbsolute20(value) || value.startsWith("~/")))
|
|
59153
59435
|
unresolved("remote or relative skill sources need a dedicated discovery adapter");
|
|
59154
59436
|
roots.add(canonical7(value.startsWith("~/") ? join37(home, value.slice(2)) : value));
|
|
59155
59437
|
}
|
|
@@ -59159,19 +59441,19 @@ function resolveAgentDiscovery(options) {
|
|
|
59159
59441
|
const plugins = [join37(directory, "plugin"), join37(directory, "plugins")];
|
|
59160
59442
|
for (const path of plugins) {
|
|
59161
59443
|
safe4(path);
|
|
59162
|
-
if (
|
|
59444
|
+
if (lstatSync25(path, { throwIfNoEntry: false })?.isDirectory())
|
|
59163
59445
|
for (const name of readdirSync11(path).sort()) {
|
|
59164
59446
|
if (name === "skills-cli.js" && path === plugins[1])
|
|
59165
59447
|
continue;
|
|
59166
59448
|
const target = join37(path, name);
|
|
59167
|
-
if (!
|
|
59449
|
+
if (!lstatSync25(target).isFile())
|
|
59168
59450
|
unresolved("local plugin packages need a dedicated discovery adapter");
|
|
59169
59451
|
witness(target);
|
|
59170
59452
|
}
|
|
59171
59453
|
}
|
|
59172
59454
|
for (const root2 of roots) {
|
|
59173
59455
|
safe4(root2);
|
|
59174
|
-
if (
|
|
59456
|
+
if (lstatSync25(root2, { throwIfNoEntry: false })?.isDirectory() && readdirSync11(root2).some((name) => name.endsWith(".md")))
|
|
59175
59457
|
unresolved("flat markdown skills require a dedicated native migration adapter");
|
|
59176
59458
|
}
|
|
59177
59459
|
}
|
|
@@ -59199,7 +59481,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59199
59481
|
const executable2 = Bun.which("gemini");
|
|
59200
59482
|
if (executable2) {
|
|
59201
59483
|
let packageRoot;
|
|
59202
|
-
for (let directory = dirname19(
|
|
59484
|
+
for (let directory = dirname19(realpathSync11(executable2)), depth = 0;depth < 8; directory = dirname19(directory), depth++) {
|
|
59203
59485
|
const path = join37(directory, "package.json"), raw = read2(path);
|
|
59204
59486
|
if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
|
|
59205
59487
|
packageRoot = directory;
|
|
@@ -59213,7 +59495,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59213
59495
|
unresolved("installed Gemini package layout is not recognized");
|
|
59214
59496
|
const builtinRoot = join37(packageRoot, "bundle/builtin");
|
|
59215
59497
|
safe4(builtinRoot);
|
|
59216
|
-
if (!
|
|
59498
|
+
if (!lstatSync25(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
|
|
59217
59499
|
unresolved("installed Gemini builtin root is missing");
|
|
59218
59500
|
for (const name of readdirSync11(builtinRoot).sort()) {
|
|
59219
59501
|
const text3 = witness(join37(builtinRoot, name, "SKILL.md"));
|
|
@@ -59251,10 +59533,10 @@ function resolveAgentDiscovery(options) {
|
|
|
59251
59533
|
throw new Error("Discovery review must include the agent configuration source");
|
|
59252
59534
|
const reviewedSources = supersedesSettingsProjection(agent, review.sources, canonical7(configPath)) ? sources.filter((source) => !isSupersededSettingsProjection(agent, canonical7(configPath), source)) : sources;
|
|
59253
59535
|
const reviewedSourcesWithManifestProjection = review.sources.map((source) => {
|
|
59254
|
-
if (agent !== "claude" || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename10(source.path) !== "plugin.json" || !source.path.endsWith(join37(sep8, ".claude-plugin", "plugin.json")))
|
|
59536
|
+
if (agent !== "claude" || source.sha256 === null || source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || source.hashMode !== undefined && source.hashMode !== "bytes" || basename10(source.path) !== "plugin.json" || !source.path.endsWith(join37(sep8, ".claude-plugin", "plugin.json")))
|
|
59255
59537
|
return source;
|
|
59256
59538
|
const pluginRoot = dirname19(dirname19(source.path)), hooksPath = join37(pluginRoot, "hooks/hooks.json");
|
|
59257
|
-
const hookStat =
|
|
59539
|
+
const hookStat = lstatSync25(hooksPath, { throwIfNoEntry: false });
|
|
59258
59540
|
const text3 = read2(source.path);
|
|
59259
59541
|
if (text3 === null)
|
|
59260
59542
|
throw new Error("Reviewed Claude plugin manifest is missing");
|
|
@@ -59295,7 +59577,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59295
59577
|
unresolved("plugin hooks require a separate no-skill-injection review");
|
|
59296
59578
|
const commands = join37(root2, "commands");
|
|
59297
59579
|
safe4(commands);
|
|
59298
|
-
if (agent === "claude" && (manifest.commands !== undefined ||
|
|
59580
|
+
if (agent === "claude" && (manifest.commands !== undefined || lstatSync25(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync11(commands).length))
|
|
59299
59581
|
unresolved("legacy command discovery requires retirement or a dedicated format adapter");
|
|
59300
59582
|
const rootSkill = witness(join37(root2, "SKILL.md"));
|
|
59301
59583
|
if (rootSkill !== null)
|
|
@@ -59317,7 +59599,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59317
59599
|
const installed = registrations === null ? {} : parseConfig(registrations, join37(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
59318
59600
|
const commands = canonical7(join37(home, ".claude/commands"));
|
|
59319
59601
|
safe4(commands);
|
|
59320
|
-
if (
|
|
59602
|
+
if (lstatSync25(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync11(commands).length)
|
|
59321
59603
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
59322
59604
|
for (const [id, enabled] of Object.entries(config.enabledPlugins ?? {})) {
|
|
59323
59605
|
if (enabled === false)
|
|
@@ -59337,7 +59619,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59337
59619
|
unresolved("unsupported plugin enablement");
|
|
59338
59620
|
const split2 = id.lastIndexOf("@"), name = id.slice(0, split2), marketplace = id.slice(split2 + 1);
|
|
59339
59621
|
const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
|
|
59340
|
-
if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !
|
|
59622
|
+
if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute20(market.source))
|
|
59341
59623
|
unresolved("enabled plugin marketplace is not an explicit local source");
|
|
59342
59624
|
const catalogText = witness(join37(market.source, ".agents/plugins/marketplace.json"));
|
|
59343
59625
|
if (catalogText === null)
|
|
@@ -59353,13 +59635,13 @@ function resolveAgentDiscovery(options) {
|
|
|
59353
59635
|
if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
|
|
59354
59636
|
unresolved("external plugin or remote skill source");
|
|
59355
59637
|
for (const path of config.skills?.paths ?? []) {
|
|
59356
|
-
if (typeof path !== "string" || !
|
|
59638
|
+
if (typeof path !== "string" || !isAbsolute20(path))
|
|
59357
59639
|
unresolved("relative or malformed added skill root");
|
|
59358
59640
|
roots.add(path);
|
|
59359
59641
|
}
|
|
59360
59642
|
const localPlugins = join37(home, ".config/opencode/plugins");
|
|
59361
59643
|
safe4(localPlugins);
|
|
59362
|
-
if (
|
|
59644
|
+
if (lstatSync25(localPlugins, { throwIfNoEntry: false }) && readdirSync11(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
59363
59645
|
unresolved("additional local plugin hooks require review");
|
|
59364
59646
|
} else if (agent === "sumi") {
|
|
59365
59647
|
if ((config.plugin?.length ?? 0) > 0 || (config.plugins?.length ?? 0) > 0 || sources.some((source) => source.path !== canonical7(configPath) && source.path !== canonical7(join37(sumiConfigDirectory(home), "sumi.jsonc")) && source.sha256 !== null))
|
|
@@ -59367,7 +59649,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59367
59649
|
} else if (agent === "hermes") {
|
|
59368
59650
|
for (const directory of [join37(home, ".hermes/plugins"), join37(home, ".hermes/hermes-agent")]) {
|
|
59369
59651
|
safe4(directory);
|
|
59370
|
-
if (
|
|
59652
|
+
if (lstatSync25(directory, { throwIfNoEntry: false }))
|
|
59371
59653
|
unresolved("installed runtime/plugin discovery requires reviewed source bindings");
|
|
59372
59654
|
}
|
|
59373
59655
|
if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
|
|
@@ -59377,11 +59659,11 @@ function resolveAgentDiscovery(options) {
|
|
|
59377
59659
|
unresolved("custom extension or skill paths");
|
|
59378
59660
|
const directory = join37(home, ".gemini/extensions");
|
|
59379
59661
|
safe4(directory);
|
|
59380
|
-
if (
|
|
59662
|
+
if (lstatSync25(directory, { throwIfNoEntry: false }))
|
|
59381
59663
|
for (const name of readdirSync11(directory)) {
|
|
59382
59664
|
const root2 = join37(directory, name);
|
|
59383
59665
|
safe4(root2);
|
|
59384
|
-
if (!
|
|
59666
|
+
if (!lstatSync25(root2)?.isDirectory())
|
|
59385
59667
|
continue;
|
|
59386
59668
|
const raw = witness(join37(root2, "gemini-extension.json"));
|
|
59387
59669
|
if (raw === null)
|
|
@@ -59394,7 +59676,7 @@ function resolveAgentDiscovery(options) {
|
|
|
59394
59676
|
}
|
|
59395
59677
|
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join37(home, ".hermes/plugins"), join37(home, ".hermes/hermes-agent")].map((path) => canonical7(path))) } : {} };
|
|
59396
59678
|
}
|
|
59397
|
-
var digest = (text3) =>
|
|
59679
|
+
var digest = (text3) => createHash24("sha256").update(text3).digest("hex");
|
|
59398
59680
|
var init_agent_discovery = __esm(() => {
|
|
59399
59681
|
init_sumi_settings_witness();
|
|
59400
59682
|
init_agent_policy_limits();
|
|
@@ -59416,7 +59698,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
59416
59698
|
});
|
|
59417
59699
|
|
|
59418
59700
|
// src/lib/authoring-path.ts
|
|
59419
|
-
import { lstatSync as
|
|
59701
|
+
import { lstatSync as lstatSync26, realpathSync as realpathSync12 } from "fs";
|
|
59420
59702
|
import { homedir as homedir7 } from "os";
|
|
59421
59703
|
import { basename as basename11, dirname as dirname20, join as join38, resolve as resolve20, sep as sep9 } from "path";
|
|
59422
59704
|
function pathParts(path) {
|
|
@@ -59436,14 +59718,14 @@ function nativeRootMatch(path) {
|
|
|
59436
59718
|
function physicalPath(path) {
|
|
59437
59719
|
let cursor = resolve20(path);
|
|
59438
59720
|
const suffix = [];
|
|
59439
|
-
while (!
|
|
59721
|
+
while (!lstatSync26(cursor, { throwIfNoEntry: false })) {
|
|
59440
59722
|
suffix.unshift(basename11(cursor));
|
|
59441
59723
|
const parent = dirname20(cursor);
|
|
59442
59724
|
if (parent === cursor)
|
|
59443
59725
|
return resolve20(path);
|
|
59444
59726
|
cursor = parent;
|
|
59445
59727
|
}
|
|
59446
|
-
return resolve20(
|
|
59728
|
+
return resolve20(realpathSync12(cursor), ...suffix);
|
|
59447
59729
|
}
|
|
59448
59730
|
function contains(root2, path) {
|
|
59449
59731
|
return path === root2 || path.startsWith(root2 + sep9);
|
|
@@ -59481,7 +59763,7 @@ function configuredRoots(home, explicitHome) {
|
|
|
59481
59763
|
continue;
|
|
59482
59764
|
}
|
|
59483
59765
|
const nativeHome = join38(home, agent === "opencode" ? ".config/opencode" : `.${agent}`);
|
|
59484
|
-
if (!
|
|
59766
|
+
if (!lstatSync26(nativeHome, { throwIfNoEntry: false }))
|
|
59485
59767
|
continue;
|
|
59486
59768
|
roots.push(...resolveAgentDiscovery({ home, agent, canonical: physicalPath }).roots);
|
|
59487
59769
|
}
|
|
@@ -59526,13 +59808,13 @@ import {
|
|
|
59526
59808
|
mkdirSync as mkdirSync11,
|
|
59527
59809
|
mkdtempSync as mkdtempSync2,
|
|
59528
59810
|
readdirSync as readdirSync12,
|
|
59529
|
-
realpathSync as
|
|
59811
|
+
realpathSync as realpathSync13,
|
|
59530
59812
|
renameSync as renameSync7,
|
|
59531
59813
|
rmSync as rmSync5,
|
|
59532
59814
|
statSync as statSync12,
|
|
59533
59815
|
writeFileSync as writeFileSync10
|
|
59534
59816
|
} from "fs";
|
|
59535
|
-
import { basename as basename12, dirname as dirname21, isAbsolute as
|
|
59817
|
+
import { basename as basename12, dirname as dirname21, isAbsolute as isAbsolute21, join as join39, normalize as normalize4, relative as relative7, resolve as resolve21, sep as sep10 } from "path";
|
|
59536
59818
|
function getPortableSkillsRoot(options = {}) {
|
|
59537
59819
|
return resolvePortableSkillsRoot(options, true);
|
|
59538
59820
|
}
|
|
@@ -59683,14 +59965,14 @@ function physicalImportPath(path) {
|
|
|
59683
59965
|
suffix.unshift(basename12(ancestor));
|
|
59684
59966
|
ancestor = dirname21(ancestor);
|
|
59685
59967
|
}
|
|
59686
|
-
return join39(
|
|
59968
|
+
return join39(realpathSync13(ancestor), ...suffix);
|
|
59687
59969
|
}
|
|
59688
59970
|
function assertDisjointImportPaths(source, destination) {
|
|
59689
|
-
const sourcePath =
|
|
59971
|
+
const sourcePath = realpathSync13(source);
|
|
59690
59972
|
const destinationPath = physicalImportPath(destination);
|
|
59691
59973
|
const contains2 = (parent, child) => {
|
|
59692
59974
|
const path = relative7(parent, child);
|
|
59693
|
-
return path === "" || !
|
|
59975
|
+
return path === "" || !isAbsolute21(path) && path !== ".." && !path.startsWith(`..${sep10}`);
|
|
59694
59976
|
};
|
|
59695
59977
|
if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
|
|
59696
59978
|
throw new Error("Source and destination skill directories must not overlap");
|
|
@@ -59907,7 +60189,7 @@ function safeIsDirectory(path) {
|
|
|
59907
60189
|
}
|
|
59908
60190
|
}
|
|
59909
60191
|
function isSafeRelativePath2(value) {
|
|
59910
|
-
if (!value.trim() ||
|
|
60192
|
+
if (!value.trim() || isAbsolute21(value))
|
|
59911
60193
|
return false;
|
|
59912
60194
|
const normalized = normalize4(value).replace(/\\/g, "/");
|
|
59913
60195
|
return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
|
|
@@ -60115,7 +60397,7 @@ __export(exports_registry, {
|
|
|
60115
60397
|
CATEGORIES: () => CATEGORIES,
|
|
60116
60398
|
BASIC_SKILL_NAMES: () => BASIC_SKILL_NAMES
|
|
60117
60399
|
});
|
|
60118
|
-
import { existsSync as existsSync20, readFileSync as
|
|
60400
|
+
import { existsSync as existsSync20, readFileSync as readFileSync23, readdirSync as readdirSync13 } from "fs";
|
|
60119
60401
|
import { join as join40 } from "path";
|
|
60120
60402
|
function isBasicSkillName(name) {
|
|
60121
60403
|
return BASIC_SKILL_NAMES.includes(name);
|
|
@@ -60165,7 +60447,7 @@ function discoverSkillsInDir(dir, source = "custom") {
|
|
|
60165
60447
|
continue;
|
|
60166
60448
|
let content;
|
|
60167
60449
|
try {
|
|
60168
|
-
content =
|
|
60450
|
+
content = readFileSync23(skillMdPath, "utf-8");
|
|
60169
60451
|
} catch {
|
|
60170
60452
|
continue;
|
|
60171
60453
|
}
|
|
@@ -60202,7 +60484,7 @@ function findExtensionSkillPath(name) {
|
|
|
60202
60484
|
continue;
|
|
60203
60485
|
let content;
|
|
60204
60486
|
try {
|
|
60205
|
-
content =
|
|
60487
|
+
content = readFileSync23(skillMdPath, "utf-8");
|
|
60206
60488
|
} catch {
|
|
60207
60489
|
continue;
|
|
60208
60490
|
}
|
|
@@ -61914,7 +62196,7 @@ var require_cli_spinners = __commonJS((exports, module) => {
|
|
|
61914
62196
|
});
|
|
61915
62197
|
|
|
61916
62198
|
// src/lib/auth-store.ts
|
|
61917
|
-
import { chmodSync as chmodSync2, existsSync as existsSync21, mkdirSync as mkdirSync12, readFileSync as
|
|
62199
|
+
import { chmodSync as chmodSync2, existsSync as existsSync21, mkdirSync as mkdirSync12, readFileSync as readFileSync25, renameSync as renameSync8, statSync as statSync13, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
|
|
61918
62200
|
import { basename as basename13, dirname as dirname22, join as join41 } from "path";
|
|
61919
62201
|
function getAuthFilePath(env3 = process.env) {
|
|
61920
62202
|
return skillsCredentialFilePath(env3);
|
|
@@ -61928,7 +62210,7 @@ function getAuthIdentity(env3 = process.env) {
|
|
|
61928
62210
|
}
|
|
61929
62211
|
function readIdentity(env3 = process.env) {
|
|
61930
62212
|
try {
|
|
61931
|
-
const parsed = JSON.parse(
|
|
62213
|
+
const parsed = JSON.parse(readFileSync25(getIdentityFilePath(env3), "utf-8"));
|
|
61932
62214
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
61933
62215
|
return {};
|
|
61934
62216
|
const record3 = parsed;
|
|
@@ -61959,7 +62241,7 @@ function writeCredentialValues(values2, env3 = process.env) {
|
|
|
61959
62241
|
const lines = [];
|
|
61960
62242
|
const written = new Set;
|
|
61961
62243
|
if (existsSync21(file)) {
|
|
61962
|
-
for (const raw of
|
|
62244
|
+
for (const raw of readFileSync25(file, "utf-8").split(/\r?\n/)) {
|
|
61963
62245
|
const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(raw);
|
|
61964
62246
|
const key = match?.[1];
|
|
61965
62247
|
if (key && key in values2) {
|
|
@@ -61997,7 +62279,7 @@ function readCredentialValue(key, env3 = process.env) {
|
|
|
61997
62279
|
if (!existsSync21(file))
|
|
61998
62280
|
return null;
|
|
61999
62281
|
try {
|
|
62000
|
-
for (const raw of
|
|
62282
|
+
for (const raw of readFileSync25(file, "utf-8").split(/\r?\n/)) {
|
|
62001
62283
|
const match = new RegExp(`^\\s*(?:export\\s+)?${key}\\s*=\\s*(.*)$`).exec(raw);
|
|
62002
62284
|
if (!match)
|
|
62003
62285
|
continue;
|
|
@@ -62015,7 +62297,7 @@ function readCredentialValue(key, env3 = process.env) {
|
|
|
62015
62297
|
}
|
|
62016
62298
|
function readIdentityRecord(env3 = process.env) {
|
|
62017
62299
|
try {
|
|
62018
|
-
const parsed = JSON.parse(
|
|
62300
|
+
const parsed = JSON.parse(readFileSync25(getIdentityFilePath(env3), "utf-8"));
|
|
62019
62301
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
62020
62302
|
} catch {
|
|
62021
62303
|
return null;
|
|
@@ -62335,7 +62617,7 @@ var init_remote_workspace_selection = __esm(() => {
|
|
|
62335
62617
|
});
|
|
62336
62618
|
|
|
62337
62619
|
// src/lib/remote-private-publications.ts
|
|
62338
|
-
import { createHash as
|
|
62620
|
+
import { createHash as createHash25 } from "crypto";
|
|
62339
62621
|
function checkedPublicationDeclaration(value) {
|
|
62340
62622
|
if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
|
|
62341
62623
|
return bad();
|
|
@@ -62596,7 +62878,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures, PrivatePublicationError, bad = () =
|
|
|
62596
62878
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
62597
62879
|
}, invalid3 = () => {
|
|
62598
62880
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
62599
|
-
}, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record5 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record5(v) && Object.keys(v).sort().join(",") === keys2.sort().join(","), date = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) =>
|
|
62881
|
+
}, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record5 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys2) => record5(v) && Object.keys(v).sort().join(",") === keys2.sort().join(","), date = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) => createHash25("sha256").update(bytes).digest("hex");
|
|
62600
62882
|
var init_remote_private_publications = __esm(() => {
|
|
62601
62883
|
init_fleet_credentials();
|
|
62602
62884
|
init_remote_workspace_selection();
|
|
@@ -81985,7 +82267,7 @@ var init_v4 = __esm(() => {
|
|
|
81985
82267
|
});
|
|
81986
82268
|
|
|
81987
82269
|
// src/lib/canonical-json.ts
|
|
81988
|
-
import { createHash as
|
|
82270
|
+
import { createHash as createHash26 } from "crypto";
|
|
81989
82271
|
function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
|
|
81990
82272
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
81991
82273
|
}
|
|
@@ -82029,7 +82311,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
82029
82311
|
return visit3(value, 0);
|
|
82030
82312
|
}
|
|
82031
82313
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
82032
|
-
return
|
|
82314
|
+
return createHash26("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
|
|
82033
82315
|
}
|
|
82034
82316
|
var init_canonical_json = () => {};
|
|
82035
82317
|
|
|
@@ -83943,8 +84225,8 @@ var init_remote_auth = __esm(() => {
|
|
|
83943
84225
|
});
|
|
83944
84226
|
|
|
83945
84227
|
// src/lib/sign-in.ts
|
|
83946
|
-
import { createHash as
|
|
83947
|
-
import { chmodSync as chmodSync3, mkdirSync as mkdirSync13, readFileSync as
|
|
84228
|
+
import { createHash as createHash27 } from "crypto";
|
|
84229
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync13, readFileSync as readFileSync26, readdirSync as readdirSync14, renameSync as renameSync9, unlinkSync as unlinkSync7, writeFileSync as writeFileSync12 } from "fs";
|
|
83948
84230
|
import { basename as basename14, dirname as dirname23, join as join42 } from "path";
|
|
83949
84231
|
function isRecord7(value) {
|
|
83950
84232
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -84094,7 +84376,7 @@ function pendingDeviceSignInStem(env3) {
|
|
|
84094
84376
|
}
|
|
84095
84377
|
function pendingDeviceSignInPath(origin, env3 = process.env) {
|
|
84096
84378
|
const { dir, stem } = pendingDeviceSignInStem(env3);
|
|
84097
|
-
return join42(dir, `${stem}-${
|
|
84379
|
+
return join42(dir, `${stem}-${createHash27("sha256").update(origin).digest("hex").slice(0, 16)}.json`);
|
|
84098
84380
|
}
|
|
84099
84381
|
function savePendingDeviceSignIn(origin, start, env3 = process.env, now3 = Date.now()) {
|
|
84100
84382
|
const path = pendingDeviceSignInPath(origin, env3);
|
|
@@ -84120,7 +84402,7 @@ function loadPendingDeviceSignIn(origin, env3 = process.env, now3 = Date.now())
|
|
|
84120
84402
|
let parsed;
|
|
84121
84403
|
try {
|
|
84122
84404
|
path = pendingDeviceSignInPath(origin, env3);
|
|
84123
|
-
parsed = JSON.parse(
|
|
84405
|
+
parsed = JSON.parse(readFileSync26(path, "utf8"));
|
|
84124
84406
|
} catch {
|
|
84125
84407
|
return null;
|
|
84126
84408
|
}
|
|
@@ -84165,7 +84447,7 @@ function pendingDeviceSignInOrigins(env3 = process.env, now3 = Date.now()) {
|
|
|
84165
84447
|
if (!entry.startsWith(`${location.stem}-`) || !/-[0-9a-f]{16}\.json$/.test(entry))
|
|
84166
84448
|
continue;
|
|
84167
84449
|
try {
|
|
84168
|
-
const parsed = JSON.parse(
|
|
84450
|
+
const parsed = JSON.parse(readFileSync26(join42(location.dir, entry), "utf8"));
|
|
84169
84451
|
if (isRecord7(parsed) && typeof parsed.origin === "string" && Number(parsed.expiresAt) > now3 && pendingDeviceSignInPath(parsed.origin, env3) === join42(location.dir, entry))
|
|
84170
84452
|
origins.push(parsed.origin);
|
|
84171
84453
|
} catch {}
|
|
@@ -84798,7 +85080,7 @@ function optionPrefix(program2, args) {
|
|
|
84798
85080
|
}
|
|
84799
85081
|
|
|
84800
85082
|
// src/lib/revision.ts
|
|
84801
|
-
import { createHash as
|
|
85083
|
+
import { createHash as createHash28 } from "crypto";
|
|
84802
85084
|
function revisionIdOf(content) {
|
|
84803
85085
|
const canonicalContent = {
|
|
84804
85086
|
slug: content.slug,
|
|
@@ -84819,7 +85101,7 @@ function revisionIdOf(content) {
|
|
|
84819
85101
|
canonicalContent.replacementSlug = content.replacementSlug ?? null;
|
|
84820
85102
|
}
|
|
84821
85103
|
const canonical7 = JSON.stringify(canonicalContent);
|
|
84822
|
-
return
|
|
85104
|
+
return createHash28("sha256").update(canonical7).digest("hex");
|
|
84823
85105
|
}
|
|
84824
85106
|
var REVISION_ID_PATTERN;
|
|
84825
85107
|
var init_revision = __esm(() => {
|
|
@@ -84848,7 +85130,7 @@ var init_skill_bundles = __esm(() => {
|
|
|
84848
85130
|
});
|
|
84849
85131
|
|
|
84850
85132
|
// src/lib/pull.ts
|
|
84851
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync3, readFileSync as
|
|
85133
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync3, readFileSync as readFileSync27, renameSync as renameSync10, rmSync as rmSync6, writeFileSync as writeFileSync13 } from "fs";
|
|
84852
85134
|
import { dirname as dirname24, join as join43 } from "path";
|
|
84853
85135
|
async function pullSkills(options = {}) {
|
|
84854
85136
|
const client2 = options.client !== undefined ? options.client : await createRemoteSkillsClient();
|
|
@@ -85010,7 +85292,7 @@ function reconcileTombstone(slug2, corpusOptions) {
|
|
|
85010
85292
|
}
|
|
85011
85293
|
function readPullMarker(dir) {
|
|
85012
85294
|
try {
|
|
85013
|
-
return JSON.parse(
|
|
85295
|
+
return JSON.parse(readFileSync27(join43(dir, PULL_MARKER_FILE), "utf-8"));
|
|
85014
85296
|
} catch {
|
|
85015
85297
|
return null;
|
|
85016
85298
|
}
|
|
@@ -85268,7 +85550,7 @@ var init_pull = __esm(() => {
|
|
|
85268
85550
|
});
|
|
85269
85551
|
|
|
85270
85552
|
// src/lib/skill-context.ts
|
|
85271
|
-
import { createHash as
|
|
85553
|
+
import { createHash as createHash29 } from "crypto";
|
|
85272
85554
|
import { resolve as resolve22 } from "path";
|
|
85273
85555
|
function words2(value) {
|
|
85274
85556
|
return new Set(value.toLowerCase().match(/[a-z0-9]+/g) ?? []);
|
|
@@ -85361,7 +85643,7 @@ ${content}`;
|
|
|
85361
85643
|
`);
|
|
85362
85644
|
const receipt = {
|
|
85363
85645
|
schemaVersion: 1,
|
|
85364
|
-
id:
|
|
85646
|
+
id: createHash29("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
|
|
85365
85647
|
profileId: profile.profileId,
|
|
85366
85648
|
profileRevision: profile.profileRevision,
|
|
85367
85649
|
authority: profile.authority,
|
|
@@ -85383,7 +85665,7 @@ var init_skill_context = __esm(() => {
|
|
|
85383
85665
|
});
|
|
85384
85666
|
|
|
85385
85667
|
// src/lib/session-reconciliation.ts
|
|
85386
|
-
import { createHash as
|
|
85668
|
+
import { createHash as createHash30 } from "crypto";
|
|
85387
85669
|
import { isDeepStrictEqual as isDeepStrictEqual12 } from "util";
|
|
85388
85670
|
function exactTimestamp(value) {
|
|
85389
85671
|
const parsed = value === undefined ? Number.NaN : Date.parse(value);
|
|
@@ -85591,7 +85873,7 @@ async function reconcileSkillSession(input2, options = {}) {
|
|
|
85591
85873
|
const result2 = replaceSkillSession(skillSessionSnapshotBinding(snapshot2), replacement, { ...plan, planDigest }, options, () => assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)()));
|
|
85592
85874
|
return { applied: true, plan, planDigest, ...result2 };
|
|
85593
85875
|
}
|
|
85594
|
-
var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) =>
|
|
85876
|
+
var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) => createHash30("sha256").update(JSON.stringify(value)).digest("hex"), SESSION_RENEWAL_TIMEOUT_MS = 4000, SESSION_RENEWAL_CONCURRENCY = 4;
|
|
85595
85877
|
var init_session_reconciliation = __esm(() => {
|
|
85596
85878
|
init_profile_client();
|
|
85597
85879
|
init_selection_cache();
|
|
@@ -86517,7 +86799,7 @@ var exports_introspect = {};
|
|
|
86517
86799
|
__export(exports_introspect, {
|
|
86518
86800
|
registerIntrospect: () => registerIntrospect
|
|
86519
86801
|
});
|
|
86520
|
-
import { existsSync as existsSync23, readFileSync as
|
|
86802
|
+
import { existsSync as existsSync23, readFileSync as readFileSync28 } from "fs";
|
|
86521
86803
|
import { join as join44 } from "path";
|
|
86522
86804
|
import { execSync } from "child_process";
|
|
86523
86805
|
function registerIntrospect(parent) {
|
|
@@ -86739,7 +87021,7 @@ function handleDiff(name, options) {
|
|
|
86739
87021
|
present: existsSync23(canonicalSkillMd),
|
|
86740
87022
|
path: canonicalDir,
|
|
86741
87023
|
...existsSync23(canonicalSkillMd) ? { hash: hashSkillMarkdownFile(canonicalSkillMd) } : {},
|
|
86742
|
-
...existsSync23(canonicalSkillMd) ? { stub: isPointerSkillMd(
|
|
87024
|
+
...existsSync23(canonicalSkillMd) ? { stub: isPointerSkillMd(readFileSync28(canonicalSkillMd, "utf-8")) } : {}
|
|
86743
87025
|
};
|
|
86744
87026
|
const pinned = getInstalledSkills().includes(bare);
|
|
86745
87027
|
const installMeta = getInstallMeta();
|
|
@@ -86748,7 +87030,7 @@ function handleDiff(name, options) {
|
|
|
86748
87030
|
let registryVersion = "unknown";
|
|
86749
87031
|
if (existsSync23(registryPkgPath)) {
|
|
86750
87032
|
try {
|
|
86751
|
-
registryVersion = JSON.parse(
|
|
87033
|
+
registryVersion = JSON.parse(readFileSync28(registryPkgPath, "utf-8")).version || "unknown";
|
|
86752
87034
|
} catch {}
|
|
86753
87035
|
}
|
|
86754
87036
|
const upToDate = installedVersion === registryVersion;
|
|
@@ -86762,7 +87044,7 @@ function handleDiff(name, options) {
|
|
|
86762
87044
|
let stub;
|
|
86763
87045
|
if (present && existsSync23(skillMdPath)) {
|
|
86764
87046
|
try {
|
|
86765
|
-
stub = isPointerSkillMd(
|
|
87047
|
+
stub = isPointerSkillMd(readFileSync28(skillMdPath, "utf-8"));
|
|
86766
87048
|
} catch {
|
|
86767
87049
|
stub = undefined;
|
|
86768
87050
|
}
|
|
@@ -87300,7 +87582,7 @@ var exports_init = {};
|
|
|
87300
87582
|
__export(exports_init, {
|
|
87301
87583
|
registerSetup: () => registerSetup
|
|
87302
87584
|
});
|
|
87303
|
-
import { existsSync as existsSync24, readFileSync as
|
|
87585
|
+
import { existsSync as existsSync24, readFileSync as readFileSync29, writeFileSync as writeFileSync14, appendFileSync } from "fs";
|
|
87304
87586
|
import { join as join45 } from "path";
|
|
87305
87587
|
function registerSetup(parent) {
|
|
87306
87588
|
parent.command("init").option("--json", "Output as JSON", false).option("--for <agent>", "Detect project type and show MCP registration guidance for agent").option("--scope <scope>", "Deprecated; agent skill-folder installs are disabled", "global").description("Initialize project for pinned skills (.env.example, .gitignore)").action((options) => handleInit(options));
|
|
@@ -87395,7 +87677,7 @@ Use: skills render`));
|
|
|
87395
87677
|
console.log(source_default.dim(" No environment variables detected across pinned skills"));
|
|
87396
87678
|
const gitignorePath = join45(cwd2, ".gitignore");
|
|
87397
87679
|
const gitignoreEntries = [".skills/runs/", ".skills/exports/", ".skills/tmp/"];
|
|
87398
|
-
let gitignoreContent = existsSync24(gitignorePath) ?
|
|
87680
|
+
let gitignoreContent = existsSync24(gitignorePath) ? readFileSync29(gitignorePath, "utf-8") : "";
|
|
87399
87681
|
let gitignoreUpdated = false;
|
|
87400
87682
|
const missingEntries = gitignoreEntries.filter((entry) => !gitignoreContent.includes(entry));
|
|
87401
87683
|
if (missingEntries.length > 0) {
|
|
@@ -87450,7 +87732,7 @@ async function handleImport(file2, options) {
|
|
|
87450
87732
|
process.exitCode = 1;
|
|
87451
87733
|
return;
|
|
87452
87734
|
}
|
|
87453
|
-
raw =
|
|
87735
|
+
raw = readFileSync29(file2, "utf-8");
|
|
87454
87736
|
}
|
|
87455
87737
|
} catch (err) {
|
|
87456
87738
|
const error61 = `Failed to read file: ${err.message}`;
|
|
@@ -87547,7 +87829,7 @@ var init_init = __esm(() => {
|
|
|
87547
87829
|
});
|
|
87548
87830
|
|
|
87549
87831
|
// src/lib/home-adoption.ts
|
|
87550
|
-
import { constants as
|
|
87832
|
+
import { constants as constants16, closeSync as closeSync15, fstatSync as fstatSync15, lstatSync as lstatSync27, openSync as openSync15, readSync as readSync13, existsSync as existsSync25, mkdirSync as mkdirSync15, readdirSync as readdirSync15, readFileSync as readFileSync30, rmSync as rmSync7, statSync as statSync14, writeFileSync as writeFileSync15 } from "fs";
|
|
87551
87833
|
import { homedir as homedir8 } from "os";
|
|
87552
87834
|
import { join as join46 } from "path";
|
|
87553
87835
|
function indexCanonicalCorpus(corpusRoot) {
|
|
@@ -87651,7 +87933,7 @@ function appendConflictsLedger(appDir, conflicts) {
|
|
|
87651
87933
|
let ledger = { version: 1, entries: [] };
|
|
87652
87934
|
if (existsSync25(ledgerPath)) {
|
|
87653
87935
|
try {
|
|
87654
|
-
const parsed = JSON.parse(
|
|
87936
|
+
const parsed = JSON.parse(readFileSync30(ledgerPath, "utf-8"));
|
|
87655
87937
|
if (parsed && typeof parsed === "object" && Array.isArray(parsed.entries)) {
|
|
87656
87938
|
ledger = parsed;
|
|
87657
87939
|
}
|
|
@@ -87687,7 +87969,7 @@ function adoptUnmarkedHomes(options = {}) {
|
|
|
87687
87969
|
const canonical7 = indexCanonicalCorpus(resolveCorpusRoot(options));
|
|
87688
87970
|
const markers = scan.adoptable.map((entry) => {
|
|
87689
87971
|
const root2 = codexCorpusRootForPath(entry.path);
|
|
87690
|
-
if (root2 && !roots.includes(root2) || !
|
|
87972
|
+
if (root2 && !roots.includes(root2) || !lstatSync27(entry.path).isDirectory() || existsSync25(join46(entry.path, SYNC_MARKER_FILE)) || hashSkillMarkdownFile(join46(entry.path, "SKILL.md")) !== entry.hash || canonical7.get(entry.skill) !== entry.hash)
|
|
87691
87973
|
throw new Error("Skill adoption target changed before apply");
|
|
87692
87974
|
const marker = {
|
|
87693
87975
|
managedBy: SYNC_MARKER_MANAGED_BY,
|
|
@@ -87708,7 +87990,7 @@ function adoptUnmarkedHomes(options = {}) {
|
|
|
87708
87990
|
`;
|
|
87709
87991
|
writeFileSync15(markerPath, bytes, { flag: "wx" });
|
|
87710
87992
|
assertCurrent();
|
|
87711
|
-
if (
|
|
87993
|
+
if (readFileSync30(markerPath, "utf8") !== bytes)
|
|
87712
87994
|
throw new Error("Skill adoption readback failed");
|
|
87713
87995
|
}
|
|
87714
87996
|
assertCurrent();
|
|
@@ -87719,14 +88001,14 @@ function adoptUnmarkedHomes(options = {}) {
|
|
|
87719
88001
|
function pruneOwnership(dir) {
|
|
87720
88002
|
let descriptor;
|
|
87721
88003
|
try {
|
|
87722
|
-
const directory =
|
|
88004
|
+
const directory = lstatSync27(dir);
|
|
87723
88005
|
if (!directory.isDirectory())
|
|
87724
88006
|
return;
|
|
87725
|
-
const markerPath = join46(dir, SYNC_MARKER_FILE), markerPathBefore =
|
|
88007
|
+
const markerPath = join46(dir, SYNC_MARKER_FILE), markerPathBefore = lstatSync27(markerPath);
|
|
87726
88008
|
if (!markerPathBefore.isFile())
|
|
87727
88009
|
return;
|
|
87728
|
-
descriptor =
|
|
87729
|
-
const before2 =
|
|
88010
|
+
descriptor = openSync15(markerPath, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
|
|
88011
|
+
const before2 = fstatSync15(descriptor);
|
|
87730
88012
|
if (!before2.isFile() || before2.dev !== markerPathBefore.dev || before2.ino !== markerPathBefore.ino || before2.size !== markerPathBefore.size || before2.mtimeMs !== markerPathBefore.mtimeMs || before2.ctimeMs !== markerPathBefore.ctimeMs || before2.size < 1 || before2.size > 65536)
|
|
87731
88013
|
return;
|
|
87732
88014
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
@@ -87737,7 +88019,7 @@ function pruneOwnership(dir) {
|
|
|
87737
88019
|
break;
|
|
87738
88020
|
length += count;
|
|
87739
88021
|
}
|
|
87740
|
-
const after2 =
|
|
88022
|
+
const after2 = fstatSync15(descriptor), current = lstatSync27(dir), markerPathAfter = lstatSync27(markerPath);
|
|
87741
88023
|
if (!markerPathAfter.isFile() || markerPathAfter.dev !== before2.dev || markerPathAfter.ino !== before2.ino || markerPathAfter.size !== before2.size || markerPathAfter.mtimeMs !== before2.mtimeMs || markerPathAfter.ctimeMs !== before2.ctimeMs || length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== before2.mtimeMs || after2.ctimeMs !== before2.ctimeMs || !current.isDirectory() || current.dev !== directory.dev || current.ino !== directory.ino)
|
|
87742
88024
|
return;
|
|
87743
88025
|
const text4 = bytes.subarray(0, length).toString("utf8"), marker = JSON.parse(text4);
|
|
@@ -87748,7 +88030,7 @@ function pruneOwnership(dir) {
|
|
|
87748
88030
|
return;
|
|
87749
88031
|
} finally {
|
|
87750
88032
|
if (descriptor !== undefined)
|
|
87751
|
-
|
|
88033
|
+
closeSync15(descriptor);
|
|
87752
88034
|
}
|
|
87753
88035
|
}
|
|
87754
88036
|
function pruneStrayHomes(options = {}) {
|
|
@@ -87834,7 +88116,7 @@ var init_home_adoption = __esm(() => {
|
|
|
87834
88116
|
});
|
|
87835
88117
|
|
|
87836
88118
|
// src/lib/home-census.ts
|
|
87837
|
-
import { existsSync as existsSync26, readFileSync as
|
|
88119
|
+
import { existsSync as existsSync26, readFileSync as readFileSync31, readdirSync as readdirSync16, statSync as statSync15 } from "fs";
|
|
87838
88120
|
import { homedir as homedir9 } from "os";
|
|
87839
88121
|
import { join as join47 } from "path";
|
|
87840
88122
|
function sortEntries(entries) {
|
|
@@ -87905,14 +88187,14 @@ function censusHomeDrift(options = {}) {
|
|
|
87905
88187
|
if (homeHash !== canonicalHash) {
|
|
87906
88188
|
let homeStub;
|
|
87907
88189
|
try {
|
|
87908
|
-
homeStub = isPointerSkillMd(
|
|
88190
|
+
homeStub = isPointerSkillMd(readFileSync31(skillMdPath, "utf-8"));
|
|
87909
88191
|
} catch {
|
|
87910
88192
|
homeStub = undefined;
|
|
87911
88193
|
}
|
|
87912
88194
|
let canonicalStub;
|
|
87913
88195
|
const canonicalSkillMd = join47(corpusRoot, skill, "SKILL.md");
|
|
87914
88196
|
try {
|
|
87915
|
-
canonicalStub = isPointerSkillMd(
|
|
88197
|
+
canonicalStub = isPointerSkillMd(readFileSync31(canonicalSkillMd, "utf-8"));
|
|
87916
88198
|
} catch {
|
|
87917
88199
|
canonicalStub = undefined;
|
|
87918
88200
|
}
|
|
@@ -87950,7 +88232,7 @@ var init_home_census = __esm(() => {
|
|
|
87950
88232
|
});
|
|
87951
88233
|
|
|
87952
88234
|
// src/cli/env-assignment.ts
|
|
87953
|
-
import { closeSync as
|
|
88235
|
+
import { closeSync as closeSync16, constants as constants17, fstatSync as fstatSync16, ftruncateSync as ftruncateSync2, lstatSync as lstatSync28, openSync as openSync16, readFileSync as readFileSync32, writeSync as writeSync4 } from "fs";
|
|
87954
88236
|
function serializeValue(value) {
|
|
87955
88237
|
if (controls.test(value))
|
|
87956
88238
|
throw new EnvAssignmentError("Environment values cannot contain control characters or newlines.");
|
|
@@ -88029,7 +88311,7 @@ function setEnvAssignment(path, assignment) {
|
|
|
88029
88311
|
try {
|
|
88030
88312
|
const previous = (() => {
|
|
88031
88313
|
try {
|
|
88032
|
-
return
|
|
88314
|
+
return lstatSync28(path);
|
|
88033
88315
|
} catch (error61) {
|
|
88034
88316
|
if (error61.code === "ENOENT")
|
|
88035
88317
|
return;
|
|
@@ -88038,14 +88320,14 @@ function setEnvAssignment(path, assignment) {
|
|
|
88038
88320
|
})();
|
|
88039
88321
|
if (previous && !previous.isFile())
|
|
88040
88322
|
throw new EnvAssignmentError("The project .env must be a regular file, not a symlink or special file.");
|
|
88041
|
-
descriptor =
|
|
88042
|
-
const opened =
|
|
88323
|
+
descriptor = openSync16(path, previous ? constants17.O_RDWR | constants17.O_NOFOLLOW | constants17.O_NONBLOCK : constants17.O_WRONLY | constants17.O_CREAT | constants17.O_EXCL | constants17.O_NOFOLLOW, 384);
|
|
88324
|
+
const opened = fstatSync16(descriptor);
|
|
88043
88325
|
if (!opened.isFile() || previous && (opened.ino !== previous.ino || opened.dev !== previous.dev)) {
|
|
88044
88326
|
throw new EnvAssignmentError("The project .env changed while opening it; retry with a regular file.");
|
|
88045
88327
|
}
|
|
88046
88328
|
let prepared = initial2;
|
|
88047
88329
|
if (previous) {
|
|
88048
|
-
const original =
|
|
88330
|
+
const original = readFileSync32(descriptor), text4 = original.toString("utf8");
|
|
88049
88331
|
if (!Buffer.from(text4, "utf8").equals(original))
|
|
88050
88332
|
throw new EnvAssignmentError(INVALID_LAYOUT);
|
|
88051
88333
|
prepared = prepareEnvAssignment(assignment, text4);
|
|
@@ -88053,7 +88335,7 @@ function setEnvAssignment(path, assignment) {
|
|
|
88053
88335
|
const bytes = Buffer.from(prepared.content, "utf8");
|
|
88054
88336
|
let written = 0;
|
|
88055
88337
|
while (written < bytes.length) {
|
|
88056
|
-
const count =
|
|
88338
|
+
const count = writeSync4(descriptor, bytes, written, bytes.length - written, written);
|
|
88057
88339
|
if (count === 0)
|
|
88058
88340
|
throw new Error("Incomplete file write");
|
|
88059
88341
|
written += count;
|
|
@@ -88066,7 +88348,7 @@ function setEnvAssignment(path, assignment) {
|
|
|
88066
88348
|
throw new EnvAssignmentError("Cannot safely read or write the project .env file.");
|
|
88067
88349
|
} finally {
|
|
88068
88350
|
if (descriptor !== undefined)
|
|
88069
|
-
|
|
88351
|
+
closeSync16(descriptor);
|
|
88070
88352
|
}
|
|
88071
88353
|
}
|
|
88072
88354
|
var INVALID_LAYOUT = "Cannot safely update .env with multiline or unsupported assignments. Use single-line KEY=VALUE entries or edit the file manually.", controls, EnvAssignmentError;
|
|
@@ -88132,7 +88414,7 @@ var exports_diagnostic = {};
|
|
|
88132
88414
|
__export(exports_diagnostic, {
|
|
88133
88415
|
registerDiagnostic: () => registerDiagnostic
|
|
88134
88416
|
});
|
|
88135
|
-
import { existsSync as existsSync27, readFileSync as
|
|
88417
|
+
import { existsSync as existsSync27, readFileSync as readFileSync33, readdirSync as readdirSync17, statSync as statSync16 } from "fs";
|
|
88136
88418
|
import { join as join48 } from "path";
|
|
88137
88419
|
import { execSync as execSync2 } from "child_process";
|
|
88138
88420
|
function registerDiagnostic(parent) {
|
|
@@ -88373,7 +88655,7 @@ function handleOutdated(options) {
|
|
|
88373
88655
|
let registryVersion = "unknown";
|
|
88374
88656
|
if (existsSync27(registryPkgPath))
|
|
88375
88657
|
try {
|
|
88376
|
-
registryVersion = JSON.parse(
|
|
88658
|
+
registryVersion = JSON.parse(readFileSync33(registryPkgPath, "utf-8")).version || "unknown";
|
|
88377
88659
|
} catch {}
|
|
88378
88660
|
if (installedVersion !== registryVersion)
|
|
88379
88661
|
pins.push({ skill: name, installedVersion, registryVersion });
|
|
@@ -88584,11 +88866,11 @@ var init_cloud_executions = __esm(() => {
|
|
|
88584
88866
|
// node_modules/@hasna/secrets/dist/sdk.js
|
|
88585
88867
|
import { isIP as isIP3 } from "net";
|
|
88586
88868
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
88587
|
-
import { closeSync as
|
|
88869
|
+
import { closeSync as closeSync17, fstatSync as fstatSync17, openSync as openSync17, readFileSync as readFileSync34 } from "fs";
|
|
88588
88870
|
import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
|
|
88589
88871
|
import { createRequire as createRequire2 } from "module";
|
|
88590
88872
|
import { hostname as osHostname2 } from "os";
|
|
88591
|
-
import { isAbsolute as
|
|
88873
|
+
import { isAbsolute as isAbsolute22, join as join49 } from "path";
|
|
88592
88874
|
import { createRequire as createRequire22 } from "module";
|
|
88593
88875
|
function envToken2(name) {
|
|
88594
88876
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -88612,7 +88894,7 @@ function homeDir2(env3) {
|
|
|
88612
88894
|
}
|
|
88613
88895
|
function absoluteOverride2(env3, key) {
|
|
88614
88896
|
const value = env3[key]?.trim();
|
|
88615
|
-
return value &&
|
|
88897
|
+
return value && isAbsolute22(value) ? value : null;
|
|
88616
88898
|
}
|
|
88617
88899
|
function hasnaHomeDir2(env3) {
|
|
88618
88900
|
const override = absoluteOverride2(env3, HASNA_HOME_ENV_KEY2);
|
|
@@ -88689,7 +88971,7 @@ function readAppConfigFile2(path) {
|
|
|
88689
88971
|
};
|
|
88690
88972
|
let fd = -1;
|
|
88691
88973
|
try {
|
|
88692
|
-
fd =
|
|
88974
|
+
fd = openSync17(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
|
|
88693
88975
|
} catch (error61) {
|
|
88694
88976
|
const code = error61.code;
|
|
88695
88977
|
if (code === "ENOENT" || code === "ENOTDIR")
|
|
@@ -88699,7 +88981,7 @@ function readAppConfigFile2(path) {
|
|
|
88699
88981
|
unsafe(`the path could not be opened (${code ?? "unknown error"})`);
|
|
88700
88982
|
}
|
|
88701
88983
|
try {
|
|
88702
|
-
const before2 =
|
|
88984
|
+
const before2 = fstatSync17(fd);
|
|
88703
88985
|
if (!before2.isFile())
|
|
88704
88986
|
unsafe("the path is not a regular file");
|
|
88705
88987
|
if (!configFileModeAllowed2(before2.mode)) {
|
|
@@ -88710,15 +88992,15 @@ function readAppConfigFile2(path) {
|
|
|
88710
88992
|
unsafe("the file is not owned by the current user");
|
|
88711
88993
|
if (before2.size > MAX_CREDENTIAL_FILE_BYTES2)
|
|
88712
88994
|
unsafe("the file exceeds the size limit");
|
|
88713
|
-
const bytes =
|
|
88714
|
-
const after2 =
|
|
88995
|
+
const bytes = readFileSync34(fd);
|
|
88996
|
+
const after2 = fstatSync17(fd);
|
|
88715
88997
|
if (!configFileReadsCoherent2(before2, after2)) {
|
|
88716
88998
|
unsafe("the file changed while being read");
|
|
88717
88999
|
}
|
|
88718
89000
|
return parseEnvFile2(bytes.toString("utf8"));
|
|
88719
89001
|
} finally {
|
|
88720
89002
|
if (fd !== -1)
|
|
88721
|
-
|
|
89003
|
+
closeSync17(fd);
|
|
88722
89004
|
}
|
|
88723
89005
|
}
|
|
88724
89006
|
function readCredentialFile2(path, apiKeyKeys) {
|
|
@@ -89884,7 +90166,7 @@ var init_sdk = __esm(() => {
|
|
|
89884
90166
|
});
|
|
89885
90167
|
|
|
89886
90168
|
// src/lib/execution-secrets.ts
|
|
89887
|
-
import { constants as
|
|
90169
|
+
import { constants as constants18, closeSync as closeSync18, fstatSync as fstatSync18, openSync as openSync18, readSync as readSync14, realpathSync as realpathSync14 } from "fs";
|
|
89888
90170
|
import { hostname as stationHostname } from "os";
|
|
89889
90171
|
function selectedSecretBindingsTemplate(scope, names, createClient2 = createSecretsClientFromEnv) {
|
|
89890
90172
|
let secretsAuthority;
|
|
@@ -89897,7 +90179,7 @@ function selectedSecretBindingsTemplate(scope, names, createClient2 = createSecr
|
|
|
89897
90179
|
return {
|
|
89898
90180
|
schema: "hasna.skills-secret-bindings.v1",
|
|
89899
90181
|
selection: { authority, workspaceId, profileId: scope.profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
|
|
89900
|
-
consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory:
|
|
90182
|
+
consumer: { stationId: process.env.HASNA_STATION || stationHostname(), workspaceDirectory: realpathSync14(scope.cwd) },
|
|
89901
90183
|
secretsAuthority,
|
|
89902
90184
|
bindings: Object.fromEntries(names.map((name) => [name, ""]))
|
|
89903
90185
|
};
|
|
@@ -89928,8 +90210,8 @@ function declaredSecretNames(value) {
|
|
|
89928
90210
|
function readSelectedSecretBindings(path) {
|
|
89929
90211
|
let fd;
|
|
89930
90212
|
try {
|
|
89931
|
-
fd =
|
|
89932
|
-
const stat2 =
|
|
90213
|
+
fd = openSync18(path, constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
|
|
90214
|
+
const stat2 = fstatSync18(fd);
|
|
89933
90215
|
if (!stat2.isFile() || stat2.size > 65536)
|
|
89934
90216
|
throw new Error;
|
|
89935
90217
|
const bytes = Buffer.alloc(65537);
|
|
@@ -89944,7 +90226,7 @@ function readSelectedSecretBindings(path) {
|
|
|
89944
90226
|
return refuse4("INVALID_SECRET_BINDINGS", "Secret bindings must be a regular JSON file of at most 64 KiB, containing reference names only.");
|
|
89945
90227
|
} finally {
|
|
89946
90228
|
if (fd !== undefined)
|
|
89947
|
-
|
|
90229
|
+
closeSync18(fd);
|
|
89948
90230
|
}
|
|
89949
90231
|
}
|
|
89950
90232
|
function validateSelectedSecretBindings(value, scope, names) {
|
|
@@ -89957,7 +90239,7 @@ function validateSelectedSecretBindings(value, scope, names) {
|
|
|
89957
90239
|
}
|
|
89958
90240
|
let workspaceDirectory;
|
|
89959
90241
|
try {
|
|
89960
|
-
workspaceDirectory =
|
|
90242
|
+
workspaceDirectory = realpathSync14(scope.cwd);
|
|
89961
90243
|
} catch {
|
|
89962
90244
|
return refuse4("SECRET_BINDING_CONSUMER_MISMATCH", "The execution workspace cannot be resolved.");
|
|
89963
90245
|
}
|
|
@@ -90233,9 +90515,9 @@ __export(exports_selected_run, {
|
|
|
90233
90515
|
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
90234
90516
|
executeSelectedLocal: () => executeSelectedLocal
|
|
90235
90517
|
});
|
|
90236
|
-
import { createHash as
|
|
90518
|
+
import { createHash as createHash31 } from "crypto";
|
|
90237
90519
|
import { spawn as spawn3 } from "child_process";
|
|
90238
|
-
import { mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync16, realpathSync as
|
|
90520
|
+
import { mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync16, realpathSync as realpathSync15 } from "fs";
|
|
90239
90521
|
import { dirname as dirname25, join as join50, resolve as resolve23 } from "path";
|
|
90240
90522
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
90241
90523
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
@@ -90342,7 +90624,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
90342
90624
|
const { authority: authority2, workspaceId, profileRevision, slug: slug2, version: version2, bundleDigest } = selection2;
|
|
90343
90625
|
const request2 = {
|
|
90344
90626
|
selection: { authority: authority2, workspaceId, profileId, profileRevision, slug: slug2, version: version2, bundleDigest },
|
|
90345
|
-
consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory:
|
|
90627
|
+
consumer: { stationId: process.env.HASNA_STATION || stationHostname2(), workspaceDirectory: realpathSync15(options.cwd ?? process.cwd()) }
|
|
90346
90628
|
};
|
|
90347
90629
|
const grant = await (options.resolveExecutionGrant ?? resolveExecutionGrant)(request2);
|
|
90348
90630
|
if (!grant || !grantIdentifier(grant.policyRevision) || !grantIdentifier(grant.grantId))
|
|
@@ -90359,7 +90641,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
90359
90641
|
selection: selection2,
|
|
90360
90642
|
target: "local",
|
|
90361
90643
|
runtime: runtimeName,
|
|
90362
|
-
inputDigest: `sha256:${
|
|
90644
|
+
inputDigest: `sha256:${createHash31("sha256").update(input2).digest("hex")}`,
|
|
90363
90645
|
runDirectory,
|
|
90364
90646
|
...executionGrant ? { executionGrant } : {},
|
|
90365
90647
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
@@ -94576,8 +94858,8 @@ var init_runs = __esm(() => {
|
|
|
94576
94858
|
});
|
|
94577
94859
|
|
|
94578
94860
|
// src/lib/run-state.ts
|
|
94579
|
-
import { createHash as
|
|
94580
|
-
import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as
|
|
94861
|
+
import { createHash as createHash32, randomBytes } from "crypto";
|
|
94862
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync17, readFileSync as readFileSync35, readdirSync as readdirSync18, statSync as statSync17, writeFileSync as writeFileSync17 } from "fs";
|
|
94581
94863
|
import { extname, join as join51, relative as relative8 } from "path";
|
|
94582
94864
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
94583
94865
|
const now3 = new Date;
|
|
@@ -94649,7 +94931,7 @@ function appendRunEvent(context, event, data = {}) {
|
|
|
94649
94931
|
const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
|
|
94650
94932
|
`;
|
|
94651
94933
|
const path = join51(context.runDir, "events.ndjson");
|
|
94652
|
-
const previous = existsSync28(path) ?
|
|
94934
|
+
const previous = existsSync28(path) ? readFileSync35(path, "utf-8") : "";
|
|
94653
94935
|
writeFileSync17(path, previous + line);
|
|
94654
94936
|
}
|
|
94655
94937
|
function listSkillRuns(targetDir = process.cwd(), limit = 50) {
|
|
@@ -94709,11 +94991,11 @@ function collectRunArtifacts(context) {
|
|
|
94709
94991
|
const artifacts = [];
|
|
94710
94992
|
for (const path of walkFiles(context.exportDir)) {
|
|
94711
94993
|
const stat2 = statSync17(path);
|
|
94712
|
-
const bytes =
|
|
94994
|
+
const bytes = readFileSync35(path);
|
|
94713
94995
|
artifacts.push({
|
|
94714
94996
|
path: toProjectRelative(context.targetDir, path),
|
|
94715
94997
|
mime: mimeForPath(path),
|
|
94716
|
-
sha256:
|
|
94998
|
+
sha256: createHash32("sha256").update(bytes).digest("hex"),
|
|
94717
94999
|
sizeBytes: stat2.size
|
|
94718
95000
|
});
|
|
94719
95001
|
}
|
|
@@ -94724,7 +95006,7 @@ function readRunRecord(runDir) {
|
|
|
94724
95006
|
if (!existsSync28(path))
|
|
94725
95007
|
return null;
|
|
94726
95008
|
try {
|
|
94727
|
-
return JSON.parse(
|
|
95009
|
+
return JSON.parse(readFileSync35(path, "utf-8"));
|
|
94728
95010
|
} catch {
|
|
94729
95011
|
return null;
|
|
94730
95012
|
}
|
|
@@ -98670,11 +98952,11 @@ var require_codegen = __commonJS((exports) => {
|
|
|
98670
98952
|
const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
|
|
98671
98953
|
return `${varKind} ${this.name}${rhs};` + _n;
|
|
98672
98954
|
}
|
|
98673
|
-
optimizeNames(names,
|
|
98955
|
+
optimizeNames(names, constants19) {
|
|
98674
98956
|
if (!names[this.name.str])
|
|
98675
98957
|
return;
|
|
98676
98958
|
if (this.rhs)
|
|
98677
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
98959
|
+
this.rhs = optimizeExpr(this.rhs, names, constants19);
|
|
98678
98960
|
return this;
|
|
98679
98961
|
}
|
|
98680
98962
|
get names() {
|
|
@@ -98692,10 +98974,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
98692
98974
|
render({ _n }) {
|
|
98693
98975
|
return `${this.lhs} = ${this.rhs};` + _n;
|
|
98694
98976
|
}
|
|
98695
|
-
optimizeNames(names,
|
|
98977
|
+
optimizeNames(names, constants19) {
|
|
98696
98978
|
if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
|
|
98697
98979
|
return;
|
|
98698
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
98980
|
+
this.rhs = optimizeExpr(this.rhs, names, constants19);
|
|
98699
98981
|
return this;
|
|
98700
98982
|
}
|
|
98701
98983
|
get names() {
|
|
@@ -98761,8 +99043,8 @@ var require_codegen = __commonJS((exports) => {
|
|
|
98761
99043
|
optimizeNodes() {
|
|
98762
99044
|
return `${this.code}` ? this : undefined;
|
|
98763
99045
|
}
|
|
98764
|
-
optimizeNames(names,
|
|
98765
|
-
this.code = optimizeExpr(this.code, names,
|
|
99046
|
+
optimizeNames(names, constants19) {
|
|
99047
|
+
this.code = optimizeExpr(this.code, names, constants19);
|
|
98766
99048
|
return this;
|
|
98767
99049
|
}
|
|
98768
99050
|
get names() {
|
|
@@ -98792,12 +99074,12 @@ var require_codegen = __commonJS((exports) => {
|
|
|
98792
99074
|
}
|
|
98793
99075
|
return nodes.length > 0 ? this : undefined;
|
|
98794
99076
|
}
|
|
98795
|
-
optimizeNames(names,
|
|
99077
|
+
optimizeNames(names, constants19) {
|
|
98796
99078
|
const { nodes } = this;
|
|
98797
99079
|
let i = nodes.length;
|
|
98798
99080
|
while (i--) {
|
|
98799
99081
|
const n2 = nodes[i];
|
|
98800
|
-
if (n2.optimizeNames(names,
|
|
99082
|
+
if (n2.optimizeNames(names, constants19))
|
|
98801
99083
|
continue;
|
|
98802
99084
|
subtractNames(names, n2.names);
|
|
98803
99085
|
nodes.splice(i, 1);
|
|
@@ -98854,12 +99136,12 @@ var require_codegen = __commonJS((exports) => {
|
|
|
98854
99136
|
return;
|
|
98855
99137
|
return this;
|
|
98856
99138
|
}
|
|
98857
|
-
optimizeNames(names,
|
|
99139
|
+
optimizeNames(names, constants19) {
|
|
98858
99140
|
var _a3;
|
|
98859
|
-
this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names,
|
|
98860
|
-
if (!(super.optimizeNames(names,
|
|
99141
|
+
this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants19);
|
|
99142
|
+
if (!(super.optimizeNames(names, constants19) || this.else))
|
|
98861
99143
|
return;
|
|
98862
|
-
this.condition = optimizeExpr(this.condition, names,
|
|
99144
|
+
this.condition = optimizeExpr(this.condition, names, constants19);
|
|
98863
99145
|
return this;
|
|
98864
99146
|
}
|
|
98865
99147
|
get names() {
|
|
@@ -98884,10 +99166,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
98884
99166
|
render(opts) {
|
|
98885
99167
|
return `for(${this.iteration})` + super.render(opts);
|
|
98886
99168
|
}
|
|
98887
|
-
optimizeNames(names,
|
|
98888
|
-
if (!super.optimizeNames(names,
|
|
99169
|
+
optimizeNames(names, constants19) {
|
|
99170
|
+
if (!super.optimizeNames(names, constants19))
|
|
98889
99171
|
return;
|
|
98890
|
-
this.iteration = optimizeExpr(this.iteration, names,
|
|
99172
|
+
this.iteration = optimizeExpr(this.iteration, names, constants19);
|
|
98891
99173
|
return this;
|
|
98892
99174
|
}
|
|
98893
99175
|
get names() {
|
|
@@ -98925,10 +99207,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
98925
99207
|
render(opts) {
|
|
98926
99208
|
return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
|
|
98927
99209
|
}
|
|
98928
|
-
optimizeNames(names,
|
|
98929
|
-
if (!super.optimizeNames(names,
|
|
99210
|
+
optimizeNames(names, constants19) {
|
|
99211
|
+
if (!super.optimizeNames(names, constants19))
|
|
98930
99212
|
return;
|
|
98931
|
-
this.iterable = optimizeExpr(this.iterable, names,
|
|
99213
|
+
this.iterable = optimizeExpr(this.iterable, names, constants19);
|
|
98932
99214
|
return this;
|
|
98933
99215
|
}
|
|
98934
99216
|
get names() {
|
|
@@ -98973,11 +99255,11 @@ var require_codegen = __commonJS((exports) => {
|
|
|
98973
99255
|
(_b = this.finally) === null || _b === undefined || _b.optimizeNodes();
|
|
98974
99256
|
return this;
|
|
98975
99257
|
}
|
|
98976
|
-
optimizeNames(names,
|
|
99258
|
+
optimizeNames(names, constants19) {
|
|
98977
99259
|
var _a3, _b;
|
|
98978
|
-
super.optimizeNames(names,
|
|
98979
|
-
(_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names,
|
|
98980
|
-
(_b = this.finally) === null || _b === undefined || _b.optimizeNames(names,
|
|
99260
|
+
super.optimizeNames(names, constants19);
|
|
99261
|
+
(_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants19);
|
|
99262
|
+
(_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants19);
|
|
98981
99263
|
return this;
|
|
98982
99264
|
}
|
|
98983
99265
|
get names() {
|
|
@@ -99251,7 +99533,7 @@ var require_codegen = __commonJS((exports) => {
|
|
|
99251
99533
|
function addExprNames(names, from) {
|
|
99252
99534
|
return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
|
|
99253
99535
|
}
|
|
99254
|
-
function optimizeExpr(expr, names,
|
|
99536
|
+
function optimizeExpr(expr, names, constants19) {
|
|
99255
99537
|
if (expr instanceof code_1.Name)
|
|
99256
99538
|
return replaceName(expr);
|
|
99257
99539
|
if (!canOptimize(expr))
|
|
@@ -99266,14 +99548,14 @@ var require_codegen = __commonJS((exports) => {
|
|
|
99266
99548
|
return items;
|
|
99267
99549
|
}, []));
|
|
99268
99550
|
function replaceName(n2) {
|
|
99269
|
-
const c =
|
|
99551
|
+
const c = constants19[n2.str];
|
|
99270
99552
|
if (c === undefined || names[n2.str] !== 1)
|
|
99271
99553
|
return n2;
|
|
99272
99554
|
delete names[n2.str];
|
|
99273
99555
|
return c;
|
|
99274
99556
|
}
|
|
99275
99557
|
function canOptimize(e2) {
|
|
99276
|
-
return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 &&
|
|
99558
|
+
return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants19[c.str] !== undefined);
|
|
99277
99559
|
}
|
|
99278
99560
|
}
|
|
99279
99561
|
function subtractNames(names, from) {
|
|
@@ -106749,11 +107031,11 @@ var init_remote_customer_operations = __esm(() => {
|
|
|
106749
107031
|
});
|
|
106750
107032
|
|
|
106751
107033
|
// src/lib/workspace-profile.ts
|
|
106752
|
-
import { constants as
|
|
107034
|
+
import { constants as constants19, closeSync as closeSync19, fstatSync as fstatSync19, lstatSync as lstatSync29, mkdirSync as mkdirSync18, mkdtempSync as mkdtempSync5, openSync as openSync19, readFileSync as readFileSync36, renameSync as renameSync11, rmSync as rmSync8, writeFileSync as writeFileSync18 } from "fs";
|
|
106753
107035
|
import { dirname as dirname26, join as join52 } from "path";
|
|
106754
107036
|
function stat2(path) {
|
|
106755
107037
|
try {
|
|
106756
|
-
return
|
|
107038
|
+
return lstatSync29(path);
|
|
106757
107039
|
} catch (error61) {
|
|
106758
107040
|
if (error61.code === "ENOENT")
|
|
106759
107041
|
return null;
|
|
@@ -106763,14 +107045,14 @@ function stat2(path) {
|
|
|
106763
107045
|
function safeText(file2) {
|
|
106764
107046
|
if (stat2(file2) === null)
|
|
106765
107047
|
return null;
|
|
106766
|
-
const fd =
|
|
107048
|
+
const fd = openSync19(file2, constants19.O_RDONLY | constants19.O_NOFOLLOW | constants19.O_NONBLOCK);
|
|
106767
107049
|
try {
|
|
106768
|
-
const s =
|
|
107050
|
+
const s = fstatSync19(fd);
|
|
106769
107051
|
if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
|
|
106770
107052
|
return fail4("The selected profile must use bounded owner-only regular files.");
|
|
106771
|
-
return
|
|
107053
|
+
return readFileSync36(fd, "utf8");
|
|
106772
107054
|
} finally {
|
|
106773
|
-
|
|
107055
|
+
closeSync19(fd);
|
|
106774
107056
|
}
|
|
106775
107057
|
}
|
|
106776
107058
|
function checkIdentityMetadata(file2, identity6) {
|
|
@@ -107117,8 +107399,8 @@ var init_recurring_customer = __esm(() => {
|
|
|
107117
107399
|
});
|
|
107118
107400
|
|
|
107119
107401
|
// src/lib/recurring-recovery.ts
|
|
107120
|
-
import { constants as
|
|
107121
|
-
import { dirname as dirname27, isAbsolute as
|
|
107402
|
+
import { constants as constants20, closeSync as closeSync20, fsyncSync as fsyncSync7, fstatSync as fstatSync20, lstatSync as lstatSync30, mkdirSync as mkdirSync19, openSync as openSync20, readSync as readSync15, realpathSync as realpathSync16, renameSync as renameSync12, unlinkSync as unlinkSync8, writeFileSync as writeFileSync19 } from "fs";
|
|
107403
|
+
import { dirname as dirname27, isAbsolute as isAbsolute23, join as join53, resolve as resolve24 } from "path";
|
|
107122
107404
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
107123
107405
|
|
|
107124
107406
|
class RecoveryOwner {
|
|
@@ -107126,10 +107408,10 @@ class RecoveryOwner {
|
|
|
107126
107408
|
parents = [];
|
|
107127
107409
|
constructor(directory) {
|
|
107128
107410
|
this.directory = directory;
|
|
107129
|
-
if (!
|
|
107411
|
+
if (!isAbsolute23(directory) || resolve24(directory) !== directory || realpathSync16(directory) !== directory)
|
|
107130
107412
|
invalid6();
|
|
107131
107413
|
for (let path = directory;; path = dirname27(path)) {
|
|
107132
|
-
const stat3 =
|
|
107414
|
+
const stat3 = lstatSync30(path);
|
|
107133
107415
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
107134
107416
|
invalid6();
|
|
107135
107417
|
this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
|
|
@@ -107139,22 +107421,22 @@ class RecoveryOwner {
|
|
|
107139
107421
|
this.assert();
|
|
107140
107422
|
}
|
|
107141
107423
|
assert() {
|
|
107142
|
-
if (
|
|
107424
|
+
if (realpathSync16(this.directory) !== this.directory)
|
|
107143
107425
|
invalid6();
|
|
107144
107426
|
for (const prior of this.parents) {
|
|
107145
|
-
const now3 =
|
|
107427
|
+
const now3 = lstatSync30(prior.path);
|
|
107146
107428
|
if (!now3.isDirectory() || now3.isSymbolicLink() || now3.dev !== prior.dev || now3.ino !== prior.ino)
|
|
107147
107429
|
invalid6();
|
|
107148
107430
|
}
|
|
107149
|
-
const own2 =
|
|
107431
|
+
const own2 = lstatSync30(this.directory);
|
|
107150
107432
|
if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
107151
107433
|
invalid6();
|
|
107152
107434
|
}
|
|
107153
107435
|
read(name) {
|
|
107154
107436
|
this.assert();
|
|
107155
|
-
const fd =
|
|
107437
|
+
const fd = openSync20(join53(this.directory, name), constants20.O_RDONLY | constants20.O_NOFOLLOW | constants20.O_NONBLOCK);
|
|
107156
107438
|
try {
|
|
107157
|
-
const before2 =
|
|
107439
|
+
const before2 = fstatSync20(fd);
|
|
107158
107440
|
if (!before2.isFile() || before2.nlink !== 1 || (before2.mode & 4095) !== 384 || before2.size < 1 || before2.size > 8192 || process.getuid && before2.uid !== process.getuid())
|
|
107159
107441
|
invalid6();
|
|
107160
107442
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
@@ -107165,36 +107447,36 @@ class RecoveryOwner {
|
|
|
107165
107447
|
break;
|
|
107166
107448
|
size2 += n2;
|
|
107167
107449
|
}
|
|
107168
|
-
const after2 =
|
|
107450
|
+
const after2 = fstatSync20(fd), path = lstatSync30(join53(this.directory, name));
|
|
107169
107451
|
if (size2 !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || path.dev !== before2.dev || path.ino !== before2.ino || !path.isFile() || path.isSymbolicLink())
|
|
107170
107452
|
invalid6();
|
|
107171
107453
|
this.assert();
|
|
107172
107454
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
|
|
107173
107455
|
} finally {
|
|
107174
|
-
|
|
107456
|
+
closeSync20(fd);
|
|
107175
107457
|
}
|
|
107176
107458
|
}
|
|
107177
107459
|
write(name, value) {
|
|
107178
107460
|
this.assert();
|
|
107179
107461
|
const bytes = canonicalJson2(value, 8192) + `
|
|
107180
107462
|
`;
|
|
107181
|
-
const fd =
|
|
107463
|
+
const fd = openSync20(join53(this.directory, name), constants20.O_WRONLY | constants20.O_CREAT | constants20.O_EXCL | constants20.O_NOFOLLOW, 384);
|
|
107182
107464
|
try {
|
|
107183
107465
|
writeFileSync19(fd, bytes);
|
|
107184
|
-
|
|
107466
|
+
fsyncSync7(fd);
|
|
107185
107467
|
} finally {
|
|
107186
|
-
|
|
107468
|
+
closeSync20(fd);
|
|
107187
107469
|
}
|
|
107188
107470
|
this.assert();
|
|
107189
107471
|
this.sync();
|
|
107190
107472
|
}
|
|
107191
107473
|
sync() {
|
|
107192
107474
|
this.assert();
|
|
107193
|
-
const fd =
|
|
107475
|
+
const fd = openSync20(this.directory, constants20.O_RDONLY | constants20.O_NOFOLLOW);
|
|
107194
107476
|
try {
|
|
107195
|
-
|
|
107477
|
+
fsyncSync7(fd);
|
|
107196
107478
|
} finally {
|
|
107197
|
-
|
|
107479
|
+
closeSync20(fd);
|
|
107198
107480
|
}
|
|
107199
107481
|
}
|
|
107200
107482
|
saveState(state, expected) {
|
|
@@ -107212,20 +107494,20 @@ class RecoveryOwner {
|
|
|
107212
107494
|
this.assert();
|
|
107213
107495
|
let fd;
|
|
107214
107496
|
try {
|
|
107215
|
-
fd =
|
|
107497
|
+
fd = openSync20(join53(this.directory, "operation.lock"), constants20.O_WRONLY | constants20.O_CREAT | constants20.O_EXCL | constants20.O_NOFOLLOW, 384);
|
|
107216
107498
|
} catch {
|
|
107217
107499
|
throw new RecurringCustomerError("RECURRING_RECOVERY_BUSY", "Recovery is locked. Confirm the original process has stopped before explicitly reconciling the retained lock; no request was retried.");
|
|
107218
107500
|
}
|
|
107219
|
-
const owner2 =
|
|
107501
|
+
const owner2 = fstatSync20(fd);
|
|
107220
107502
|
try {
|
|
107221
107503
|
writeFileSync19(fd, JSON.stringify({ pid: process.pid }));
|
|
107222
|
-
|
|
107504
|
+
fsyncSync7(fd);
|
|
107223
107505
|
this.sync();
|
|
107224
107506
|
return await action();
|
|
107225
107507
|
} finally {
|
|
107226
|
-
|
|
107508
|
+
closeSync20(fd);
|
|
107227
107509
|
this.assert();
|
|
107228
|
-
const now3 =
|
|
107510
|
+
const now3 = lstatSync30(join53(this.directory, "operation.lock"));
|
|
107229
107511
|
if (owner2.dev !== now3.dev || owner2.ino !== now3.ino || !now3.isFile() || now3.isSymbolicLink())
|
|
107230
107512
|
invalid6();
|
|
107231
107513
|
unlinkSync8(join53(this.directory, "operation.lock"));
|
|
@@ -107261,7 +107543,7 @@ function base2(customer, organizationId) {
|
|
|
107261
107543
|
};
|
|
107262
107544
|
}
|
|
107263
107545
|
function create3(directory, intent) {
|
|
107264
|
-
if (!
|
|
107546
|
+
if (!isAbsolute23(directory) || resolve24(directory) !== directory || realpathSync16(dirname27(directory)) !== dirname27(directory))
|
|
107265
107547
|
invalid6();
|
|
107266
107548
|
mkdirSync19(directory, { mode: 448 });
|
|
107267
107549
|
const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
|
|
@@ -107424,7 +107706,7 @@ var init_recurring_recovery = __esm(() => {
|
|
|
107424
107706
|
});
|
|
107425
107707
|
|
|
107426
107708
|
// src/lib/recurring-surface.ts
|
|
107427
|
-
import { isAbsolute as
|
|
107709
|
+
import { isAbsolute as isAbsolute24 } from "path";
|
|
107428
107710
|
function recurringMcpSchema(action) {
|
|
107429
107711
|
return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
|
|
107430
107712
|
}
|
|
@@ -107529,7 +107811,7 @@ var init_recurring_surface = __esm(() => {
|
|
|
107529
107811
|
uuid12 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
|
|
107530
107812
|
context = { userId: uuid12.optional(), membershipId: uuid12.optional() };
|
|
107531
107813
|
page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
|
|
107532
|
-
directory = exports_external.string().max(4096).refine(
|
|
107814
|
+
directory = exports_external.string().max(4096).refine(isAbsolute24, "Use an absolute recovery directory");
|
|
107533
107815
|
email4 = exports_external.string().trim().toLowerCase().email().max(254);
|
|
107534
107816
|
code = exports_external.string().regex(/^\d{6}$/);
|
|
107535
107817
|
recurringSurfaceSchemas = {
|
|
@@ -109646,7 +109928,7 @@ var init_resource_meta_tools = __esm(() => {
|
|
|
109646
109928
|
});
|
|
109647
109929
|
|
|
109648
109930
|
// src/lib/scheduler.ts
|
|
109649
|
-
import { existsSync as existsSync31, readFileSync as
|
|
109931
|
+
import { existsSync as existsSync31, readFileSync as readFileSync37, writeFileSync as writeFileSync20, mkdirSync as mkdirSync21 } from "fs";
|
|
109650
109932
|
import { join as join56 } from "path";
|
|
109651
109933
|
function getSchedulesPath(targetDir = process.cwd()) {
|
|
109652
109934
|
return join56(targetDir, ".skills", "schedules.json");
|
|
@@ -109655,7 +109937,7 @@ function loadSchedules(targetDir = process.cwd()) {
|
|
|
109655
109937
|
const path = getSchedulesPath(targetDir);
|
|
109656
109938
|
if (existsSync31(path)) {
|
|
109657
109939
|
try {
|
|
109658
|
-
return JSON.parse(
|
|
109940
|
+
return JSON.parse(readFileSync37(path, "utf-8"));
|
|
109659
109941
|
} catch {}
|
|
109660
109942
|
}
|
|
109661
109943
|
return { version: 1, schedules: [] };
|
|
@@ -109961,11 +110243,11 @@ var init_schedule_tools = __esm(() => {
|
|
|
109961
110243
|
});
|
|
109962
110244
|
|
|
109963
110245
|
// src/lib/native-storage.ts
|
|
109964
|
-
import { createHash as
|
|
110246
|
+
import { createHash as createHash33, createHmac as createHmac3 } from "crypto";
|
|
109965
110247
|
import {
|
|
109966
110248
|
existsSync as existsSync32,
|
|
109967
110249
|
mkdirSync as mkdirSync22,
|
|
109968
|
-
readFileSync as
|
|
110250
|
+
readFileSync as readFileSync38,
|
|
109969
110251
|
readdirSync as readdirSync20,
|
|
109970
110252
|
statSync as statSync19,
|
|
109971
110253
|
writeFileSync as writeFileSync21
|
|
@@ -110033,12 +110315,12 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
110033
110315
|
const files = [];
|
|
110034
110316
|
if (existsSync32(projectStateDir)) {
|
|
110035
110317
|
for (const filePath of walkFiles2(projectStateDir)) {
|
|
110036
|
-
const bytes =
|
|
110318
|
+
const bytes = readFileSync38(filePath);
|
|
110037
110319
|
const relativePath = toPosix(relative9(targetDir, filePath));
|
|
110038
110320
|
files.push({
|
|
110039
110321
|
path: relativePath,
|
|
110040
110322
|
sizeBytes: bytes.byteLength,
|
|
110041
|
-
sha256:
|
|
110323
|
+
sha256: createHash33("sha256").update(bytes).digest("hex"),
|
|
110042
110324
|
...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
|
|
110043
110325
|
});
|
|
110044
110326
|
}
|
|
@@ -110330,20 +110612,20 @@ var init_private_publication_customer = __esm(() => {
|
|
|
110330
110612
|
});
|
|
110331
110613
|
|
|
110332
110614
|
// src/lib/private-publication-recovery.ts
|
|
110333
|
-
import { constants as
|
|
110334
|
-
import { dirname as dirname30, isAbsolute as
|
|
110615
|
+
import { constants as constants21, closeSync as closeSync21, fsyncSync as fsyncSync8, fstatSync as fstatSync21, lstatSync as lstatSync31, mkdirSync as mkdirSync23, openSync as openSync21, readSync as readSync16, realpathSync as realpathSync17, renameSync as renameSync13, unlinkSync as unlinkSync9, writeFileSync as writeFileSync22 } from "fs";
|
|
110616
|
+
import { dirname as dirname30, isAbsolute as isAbsolute25, join as join58, resolve as resolve25 } from "path";
|
|
110335
110617
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
110336
110618
|
function safeDirectory(directory2) {
|
|
110337
|
-
if (!
|
|
110619
|
+
if (!isAbsolute25(directory2) || directory2 !== resolve25(directory2) || realpathSync17(directory2) !== directory2)
|
|
110338
110620
|
return fail5();
|
|
110339
110621
|
for (let path = directory2;; path = dirname30(path)) {
|
|
110340
|
-
const stat3 =
|
|
110622
|
+
const stat3 = lstatSync31(path);
|
|
110341
110623
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
110342
110624
|
return fail5();
|
|
110343
110625
|
if (path === dirname30(path))
|
|
110344
110626
|
break;
|
|
110345
110627
|
}
|
|
110346
|
-
const own2 =
|
|
110628
|
+
const own2 = lstatSync31(directory2);
|
|
110347
110629
|
if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
110348
110630
|
return fail5();
|
|
110349
110631
|
return { dev: own2.dev, ino: own2.ino };
|
|
@@ -110355,9 +110637,9 @@ function unchangedDirectory(directory2, identity6) {
|
|
|
110355
110637
|
}
|
|
110356
110638
|
function readOwned(directory2, name, max2) {
|
|
110357
110639
|
const identity6 = safeDirectory(directory2), file2 = join58(directory2, name);
|
|
110358
|
-
const fd =
|
|
110640
|
+
const fd = openSync21(file2, constants21.O_RDONLY | constants21.O_NOFOLLOW);
|
|
110359
110641
|
try {
|
|
110360
|
-
const stat3 =
|
|
110642
|
+
const stat3 = fstatSync21(fd);
|
|
110361
110643
|
if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max2 || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
|
|
110362
110644
|
return fail5();
|
|
110363
110645
|
const buffer = Buffer.alloc(Math.min(max2, stat3.size) + 1);
|
|
@@ -110368,22 +110650,22 @@ function readOwned(directory2, name, max2) {
|
|
|
110368
110650
|
break;
|
|
110369
110651
|
length += count;
|
|
110370
110652
|
}
|
|
110371
|
-
const bytes = buffer.subarray(0, length), after2 =
|
|
110653
|
+
const bytes = buffer.subarray(0, length), after2 = fstatSync21(fd);
|
|
110372
110654
|
unchangedDirectory(directory2, identity6);
|
|
110373
110655
|
if (bytes.length !== stat3.size || stat3.size !== after2.size || stat3.mtimeMs !== after2.mtimeMs || stat3.ctimeMs !== after2.ctimeMs)
|
|
110374
110656
|
return fail5();
|
|
110375
110657
|
return bytes;
|
|
110376
110658
|
} finally {
|
|
110377
|
-
|
|
110659
|
+
closeSync21(fd);
|
|
110378
110660
|
}
|
|
110379
110661
|
}
|
|
110380
110662
|
function writeOwned(directory2, name, bytes) {
|
|
110381
|
-
const fd =
|
|
110663
|
+
const fd = openSync21(join58(directory2, name), constants21.O_WRONLY | constants21.O_CREAT | constants21.O_EXCL | constants21.O_NOFOLLOW, 384);
|
|
110382
110664
|
try {
|
|
110383
110665
|
writeFileSync22(fd, bytes);
|
|
110384
|
-
|
|
110666
|
+
fsyncSync8(fd);
|
|
110385
110667
|
} finally {
|
|
110386
|
-
|
|
110668
|
+
closeSync21(fd);
|
|
110387
110669
|
}
|
|
110388
110670
|
}
|
|
110389
110671
|
function save2(directory2, value) {
|
|
@@ -110392,11 +110674,11 @@ function save2(directory2, value) {
|
|
|
110392
110674
|
`);
|
|
110393
110675
|
unchangedDirectory(directory2, identity6);
|
|
110394
110676
|
renameSync13(join58(directory2, temporary), join58(directory2, "receipt.json"));
|
|
110395
|
-
const fd =
|
|
110677
|
+
const fd = openSync21(directory2, constants21.O_RDONLY | constants21.O_NOFOLLOW);
|
|
110396
110678
|
try {
|
|
110397
|
-
|
|
110679
|
+
fsyncSync8(fd);
|
|
110398
110680
|
} finally {
|
|
110399
|
-
|
|
110681
|
+
closeSync21(fd);
|
|
110400
110682
|
}
|
|
110401
110683
|
}
|
|
110402
110684
|
function bind2(client2, receipt) {
|
|
@@ -110407,20 +110689,20 @@ async function locked(directory2, action) {
|
|
|
110407
110689
|
const identity6 = safeDirectory(directory2), file2 = join58(directory2, "operation.lock");
|
|
110408
110690
|
let fd;
|
|
110409
110691
|
try {
|
|
110410
|
-
fd =
|
|
110692
|
+
fd = openSync21(file2, constants21.O_WRONLY | constants21.O_CREAT | constants21.O_EXCL | constants21.O_NOFOLLOW, 384);
|
|
110411
110693
|
} catch {
|
|
110412
110694
|
throw new PrivatePublicationError("PUBLICATION_RECOVERY_BUSY", "Another operation holds this recovery directory. If it crashed, confirm that process has stopped before explicitly removing operation.lock and resuming.");
|
|
110413
110695
|
}
|
|
110414
|
-
const lock =
|
|
110696
|
+
const lock = fstatSync21(fd);
|
|
110415
110697
|
try {
|
|
110416
110698
|
writeFileSync22(fd, JSON.stringify({ pid: process.pid }) + `
|
|
110417
110699
|
`);
|
|
110418
|
-
|
|
110700
|
+
fsyncSync8(fd);
|
|
110419
110701
|
return await action();
|
|
110420
110702
|
} finally {
|
|
110421
|
-
|
|
110703
|
+
closeSync21(fd);
|
|
110422
110704
|
unchangedDirectory(directory2, identity6);
|
|
110423
|
-
const now3 =
|
|
110705
|
+
const now3 = lstatSync31(file2);
|
|
110424
110706
|
if (now3.dev !== lock.dev || now3.ino !== lock.ino || !now3.isFile() || now3.isSymbolicLink())
|
|
110425
110707
|
fail5();
|
|
110426
110708
|
unlinkSync9(file2);
|
|
@@ -110472,15 +110754,15 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
|
|
|
110472
110754
|
phase: "prepared",
|
|
110473
110755
|
intent: null
|
|
110474
110756
|
};
|
|
110475
|
-
if (!
|
|
110757
|
+
if (!isAbsolute25(recoveryDirectory) || resolve25(recoveryDirectory) !== recoveryDirectory || realpathSync17(dirname30(recoveryDirectory)) !== dirname30(recoveryDirectory))
|
|
110476
110758
|
return fail5();
|
|
110477
110759
|
mkdirSync23(recoveryDirectory, { mode: 448 });
|
|
110478
110760
|
safeDirectory(recoveryDirectory);
|
|
110479
|
-
const parent =
|
|
110761
|
+
const parent = openSync21(dirname30(recoveryDirectory), constants21.O_RDONLY | constants21.O_NOFOLLOW);
|
|
110480
110762
|
try {
|
|
110481
|
-
|
|
110763
|
+
fsyncSync8(parent);
|
|
110482
110764
|
} finally {
|
|
110483
|
-
|
|
110765
|
+
closeSync21(parent);
|
|
110484
110766
|
}
|
|
110485
110767
|
writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
|
|
110486
110768
|
save2(recoveryDirectory, receipt);
|
|
@@ -110573,10 +110855,10 @@ var init_private_publication_recovery = __esm(() => {
|
|
|
110573
110855
|
});
|
|
110574
110856
|
|
|
110575
110857
|
// src/mcp/private-publication-tools.ts
|
|
110576
|
-
import { isAbsolute as
|
|
110858
|
+
import { isAbsolute as isAbsolute26 } from "path";
|
|
110577
110859
|
function registerPrivatePublicationTools(server) {
|
|
110578
110860
|
const uuid9 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
|
|
110579
|
-
const directory2 = exports_external.string().max(4096).refine(
|
|
110861
|
+
const directory2 = exports_external.string().max(4096).refine(isAbsolute26, "Use an absolute local directory");
|
|
110580
110862
|
const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
|
|
110581
110863
|
const description = "Manage a private source publication using fresh workspace-bound verification and a host-local recovery directory. Publishing requires explicit UUID current-version comparison and upload consent. Resume reuses immutable saved bytes and intent; an uncertain PUT is finalized for server verification, never uploaded twice. Sessions and signed URLs are not returned or persisted. Private execution is unavailable. Host request history may contain the supplied verification code.";
|
|
110582
110864
|
const handler = (action) => async (value) => {
|
|
@@ -110918,6 +111200,7 @@ async function startMcpStdio() {
|
|
|
110918
111200
|
}
|
|
110919
111201
|
var args;
|
|
110920
111202
|
var init_mcp2 = __esm(() => {
|
|
111203
|
+
init_launch_cwd_apply();
|
|
110921
111204
|
init_stdio2();
|
|
110922
111205
|
init_package();
|
|
110923
111206
|
init_fleet_credentials();
|
|
@@ -110938,7 +111221,7 @@ var exports_runtime_mcp = {};
|
|
|
110938
111221
|
__export(exports_runtime_mcp, {
|
|
110939
111222
|
handleMcp: () => handleMcp
|
|
110940
111223
|
});
|
|
110941
|
-
import { existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as
|
|
111224
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync24, readFileSync as readFileSync39, writeFileSync as writeFileSync23 } from "fs";
|
|
110942
111225
|
import { homedir as homedir10 } from "os";
|
|
110943
111226
|
import { dirname as dirname31, join as join59 } from "path";
|
|
110944
111227
|
async function handleMcp(options) {
|
|
@@ -111049,7 +111332,7 @@ function registerCodexMcp(command) {
|
|
|
111049
111332
|
const config2 = `[mcp_servers.${MCP_SERVER_NAME}]
|
|
111050
111333
|
command = ${JSON.stringify(command)}`;
|
|
111051
111334
|
try {
|
|
111052
|
-
const current = existsSync33(path) ?
|
|
111335
|
+
const current = existsSync33(path) ? readFileSync39(path, "utf-8") : "";
|
|
111053
111336
|
writeTextFile(path, upsertTomlSection(current, `[mcp_servers.${MCP_SERVER_NAME}]`, `command = ${JSON.stringify(command)}`));
|
|
111054
111337
|
return { agent: "codex", success: true, path, config: config2 };
|
|
111055
111338
|
} catch (err) {
|
|
@@ -111101,7 +111384,7 @@ function registerJsonMcpServer(agent, path, containerKey, server2) {
|
|
|
111101
111384
|
function readJsonObject2(path) {
|
|
111102
111385
|
if (!existsSync33(path))
|
|
111103
111386
|
return {};
|
|
111104
|
-
const raw =
|
|
111387
|
+
const raw = readFileSync39(path, "utf-8").trim();
|
|
111105
111388
|
if (!raw)
|
|
111106
111389
|
return {};
|
|
111107
111390
|
const parsed = JSON.parse(raw);
|
|
@@ -111220,7 +111503,7 @@ var init_remote_account2 = __esm(() => {
|
|
|
111220
111503
|
});
|
|
111221
111504
|
|
|
111222
111505
|
// src/cli/commands/reviewed-runtime-lock.ts
|
|
111223
|
-
import { createHash as
|
|
111506
|
+
import { createHash as createHash34 } from "crypto";
|
|
111224
111507
|
function row(value) {
|
|
111225
111508
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
111226
111509
|
throw new Error("REVIEWED_LOCK_SHAPE_INVALID");
|
|
@@ -111271,10 +111554,10 @@ async function metadata(name, context2) {
|
|
|
111271
111554
|
throw new Error("REVIEWED_LOCK_METADATA_INVALID");
|
|
111272
111555
|
}
|
|
111273
111556
|
}
|
|
111274
|
-
async function validateReviewedRuntimeLock(bytes,
|
|
111275
|
-
if (!/^[a-f0-9]{64}$/.test(
|
|
111557
|
+
async function validateReviewedRuntimeLock(bytes, sha2563, context2) {
|
|
111558
|
+
if (!/^[a-f0-9]{64}$/.test(sha2563))
|
|
111276
111559
|
throw new Error("REVIEWED_LOCK_SHA256_INVALID");
|
|
111277
|
-
if (bytes.byteLength > MAX_LOCK_BYTES ||
|
|
111560
|
+
if (bytes.byteLength > MAX_LOCK_BYTES || createHash34("sha256").update(bytes).digest("hex") !== sha2563)
|
|
111278
111561
|
throw new Error("REVIEWED_LOCK_HASH_MISMATCH");
|
|
111279
111562
|
if (!Number.isSafeInteger(context2.minReleaseAge) || context2.minReleaseAge < 1)
|
|
111280
111563
|
throw new Error("REVIEWED_LOCK_RELEASE_AGE_REQUIRED");
|
|
@@ -111351,39 +111634,76 @@ var init_reviewed_runtime_lock = __esm(() => {
|
|
|
111351
111634
|
});
|
|
111352
111635
|
|
|
111353
111636
|
// src/cli/commands/runtime-copyfile.ts
|
|
111354
|
-
import { createHash as
|
|
111637
|
+
import { createHash as createHash35, randomUUID as randomUUID10 } from "crypto";
|
|
111355
111638
|
import { Readable } from "stream";
|
|
111356
111639
|
import { createGunzip as createGunzip2 } from "zlib";
|
|
111357
111640
|
import {
|
|
111358
111641
|
chmodSync as chmodSync4,
|
|
111359
111642
|
copyFileSync,
|
|
111360
111643
|
existsSync as existsSync34,
|
|
111361
|
-
lstatSync as
|
|
111644
|
+
lstatSync as lstatSync32,
|
|
111362
111645
|
mkdirSync as mkdirSync25,
|
|
111363
|
-
readFileSync as
|
|
111646
|
+
readFileSync as readFileSync40,
|
|
111364
111647
|
readdirSync as readdirSync21,
|
|
111365
|
-
readlinkSync as
|
|
111366
|
-
realpathSync as
|
|
111648
|
+
readlinkSync as readlinkSync7,
|
|
111649
|
+
realpathSync as realpathSync18,
|
|
111367
111650
|
renameSync as renameSync14,
|
|
111368
|
-
symlinkSync,
|
|
111369
111651
|
writeFileSync as writeFileSync24
|
|
111370
111652
|
} from "fs";
|
|
111371
|
-
import { basename as basename15, delimiter as delimiter2, dirname as dirname32, isAbsolute as
|
|
111653
|
+
import { basename as basename15, delimiter as delimiter2, dirname as dirname32, isAbsolute as isAbsolute27, join as join60, relative as relative10, resolve as resolve26, sep as sep12 } from "path";
|
|
111654
|
+
function oldLauncherState(item) {
|
|
111655
|
+
if (item.oldShape === "pinned")
|
|
111656
|
+
return { shape: "pinned", runtime: item.oldRuntime, cwd: item.oldCwd, target: item.oldTarget, sha256: item.oldSha256 };
|
|
111657
|
+
return { shape: "symlink", linkTarget: item.oldLinkTarget, target: item.oldTarget };
|
|
111658
|
+
}
|
|
111659
|
+
function newLauncherState(item) {
|
|
111660
|
+
if (item.newShape === "pinned")
|
|
111661
|
+
return { shape: "pinned", runtime: item.newRuntime, cwd: item.newCwd, target: item.newTarget, sha256: item.newSha256 };
|
|
111662
|
+
return { shape: "symlink", linkTarget: item.newTarget, target: item.newTarget };
|
|
111663
|
+
}
|
|
111664
|
+
function assertLauncherRecordShapes(item) {
|
|
111665
|
+
const hex3 = /^[a-f0-9]{64}$/;
|
|
111666
|
+
for (const side of ["old", "new"]) {
|
|
111667
|
+
const shape = item[`${side}Shape`], runtime = item[`${side}Runtime`], cwd2 = item[`${side}Cwd`], sha6 = item[`${side}Sha256`];
|
|
111668
|
+
if (shape === undefined) {
|
|
111669
|
+
if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined)
|
|
111670
|
+
throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
|
|
111671
|
+
continue;
|
|
111672
|
+
}
|
|
111673
|
+
if (shape === "symlink") {
|
|
111674
|
+
if (runtime !== undefined || cwd2 !== undefined || sha6 !== undefined)
|
|
111675
|
+
throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
|
|
111676
|
+
continue;
|
|
111677
|
+
}
|
|
111678
|
+
if (shape !== "pinned" || typeof runtime !== "string" || !isAbsolute27(runtime) || typeof cwd2 !== "string" || !isAbsolute27(cwd2) || typeof sha6 !== "string" || !hex3.test(sha6)) {
|
|
111679
|
+
throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
|
|
111680
|
+
}
|
|
111681
|
+
const target = side === "old" ? item.oldTarget : item.newTarget;
|
|
111682
|
+
if (side === "old" && item.oldLinkTarget !== item.oldTarget)
|
|
111683
|
+
throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
|
|
111684
|
+
if (pinnedLauncherState(runtime, cwd2, target).sha256 !== sha6)
|
|
111685
|
+
throw new Error("RECEIPT_LAUNCHER_SHAPE_INVALID");
|
|
111686
|
+
}
|
|
111687
|
+
}
|
|
111688
|
+
function pinnedRecordFields(runtime, cwd2, target) {
|
|
111689
|
+
const state = pinnedLauncherState(runtime, cwd2, target);
|
|
111690
|
+
return { newShape: "pinned", newRuntime: state.runtime, newCwd: state.cwd, newSha256: state.sha256 };
|
|
111691
|
+
}
|
|
111372
111692
|
function object10(value, code2) {
|
|
111373
111693
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
111374
111694
|
throw new Error(code2);
|
|
111375
111695
|
return value;
|
|
111376
111696
|
}
|
|
111377
111697
|
function hash5(bytes) {
|
|
111378
|
-
return
|
|
111698
|
+
return createHash35("sha256").update(bytes).digest("hex");
|
|
111379
111699
|
}
|
|
111380
111700
|
function isWithin(parent, child) {
|
|
111381
111701
|
const rel = relative10(parent, child);
|
|
111382
|
-
return rel === "" || !rel.startsWith(`..${sep12}`) && rel !== ".." && !
|
|
111702
|
+
return rel === "" || !rel.startsWith(`..${sep12}`) && rel !== ".." && !isAbsolute27(rel);
|
|
111383
111703
|
}
|
|
111384
111704
|
function entryExists(path) {
|
|
111385
111705
|
try {
|
|
111386
|
-
|
|
111706
|
+
lstatSync32(path);
|
|
111387
111707
|
return true;
|
|
111388
111708
|
} catch {
|
|
111389
111709
|
return false;
|
|
@@ -111395,7 +111715,7 @@ function assertNoSymlinkAncestors(path) {
|
|
|
111395
111715
|
let current = sep12;
|
|
111396
111716
|
for (const part of parts) {
|
|
111397
111717
|
current = join60(current, part);
|
|
111398
|
-
const stat3 =
|
|
111718
|
+
const stat3 = lstatSync32(current);
|
|
111399
111719
|
if (stat3.isSymbolicLink())
|
|
111400
111720
|
throw new Error("PATH_ANCESTOR_SYMLINK_UNSUPPORTED");
|
|
111401
111721
|
if (!stat3.isDirectory())
|
|
@@ -111428,7 +111748,7 @@ function packageBins(pkg) {
|
|
|
111428
111748
|
const entries = typeof raw === "string" ? [[PACKAGE_NAME.slice(PACKAGE_NAME.lastIndexOf("/") + 1), raw]] : raw && typeof raw === "object" && !Array.isArray(raw) ? Object.entries(raw) : [];
|
|
111429
111749
|
const output2 = {};
|
|
111430
111750
|
for (const [name, value] of entries) {
|
|
111431
|
-
if (!/^[a-zA-Z0-9._-]+$/.test(name) || typeof value !== "string" || !value ||
|
|
111751
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(name) || typeof value !== "string" || !value || isAbsolute27(value)) {
|
|
111432
111752
|
throw new Error("PACKAGE_BIN_INVALID");
|
|
111433
111753
|
}
|
|
111434
111754
|
const normalized = value.replaceAll("\\", "/");
|
|
@@ -111443,7 +111763,7 @@ function packageBins(pkg) {
|
|
|
111443
111763
|
function readPackage(path) {
|
|
111444
111764
|
let data;
|
|
111445
111765
|
try {
|
|
111446
|
-
data = object10(JSON.parse(
|
|
111766
|
+
data = object10(JSON.parse(readFileSync40(path, "utf8")), "PACKAGE_JSON_INVALID");
|
|
111447
111767
|
} catch {
|
|
111448
111768
|
throw new Error("PACKAGE_JSON_INVALID");
|
|
111449
111769
|
}
|
|
@@ -111453,10 +111773,10 @@ function readPackage(path) {
|
|
|
111453
111773
|
return { data, version: data.version, bins: packageBins(data) };
|
|
111454
111774
|
}
|
|
111455
111775
|
function resolveRuntimeLayout(homeInput, pathInput) {
|
|
111456
|
-
const home =
|
|
111776
|
+
const home = realpathSync18(homeInput);
|
|
111457
111777
|
const runtimeRoot = join60(home, ".hasna", "skills", "runtime");
|
|
111458
111778
|
assertNoSymlinkAncestors(runtimeRoot);
|
|
111459
|
-
const runtimeRootStat =
|
|
111779
|
+
const runtimeRootStat = lstatSync32(runtimeRoot);
|
|
111460
111780
|
if (!runtimeRootStat.isDirectory() || runtimeRootStat.isSymbolicLink() || (runtimeRootStat.mode & 63) !== 0) {
|
|
111461
111781
|
throw new Error("RUNTIME_ROOT_NOT_PRIVATE");
|
|
111462
111782
|
}
|
|
@@ -111465,10 +111785,18 @@ function resolveRuntimeLayout(homeInput, pathInput) {
|
|
|
111465
111785
|
throw new Error("ACTIVE_SKILLS_LAUNCHER_NOT_FOUND");
|
|
111466
111786
|
const launcherPath = resolve26(selectedLauncher);
|
|
111467
111787
|
assertNoSymlinkAncestors(dirname32(launcherPath));
|
|
111468
|
-
const
|
|
111469
|
-
if (
|
|
111788
|
+
const activeLauncher = inspectLauncher(launcherPath);
|
|
111789
|
+
if (activeLauncher.kind === "foreign")
|
|
111470
111790
|
throw new Error("ACTIVE_SKILLS_LAUNCHER_NOT_MANAGED_LINK");
|
|
111471
|
-
const activeBinary =
|
|
111791
|
+
const activeBinary = activeLauncher.target;
|
|
111792
|
+
let activePhysical;
|
|
111793
|
+
try {
|
|
111794
|
+
activePhysical = realpathSync18(activeBinary);
|
|
111795
|
+
} catch {
|
|
111796
|
+
throw new Error("ACTIVE_RUNTIME_ENTRYPOINT_MISMATCH");
|
|
111797
|
+
}
|
|
111798
|
+
if (activePhysical !== activeBinary)
|
|
111799
|
+
throw new Error("ACTIVE_RUNTIME_ENTRYPOINT_MISMATCH");
|
|
111472
111800
|
const currentPackageRoot = dirname32(dirname32(activeBinary));
|
|
111473
111801
|
assertNoSymlinkAncestors(currentPackageRoot);
|
|
111474
111802
|
if (!isWithin(runtimeRoot, currentPackageRoot))
|
|
@@ -111493,27 +111821,28 @@ function resolveRuntimeLayout(homeInput, pathInput) {
|
|
|
111493
111821
|
if (!existsSync34(path))
|
|
111494
111822
|
continue;
|
|
111495
111823
|
assertNoSymlinkAncestors(dir);
|
|
111496
|
-
let
|
|
111824
|
+
let launcher;
|
|
111497
111825
|
try {
|
|
111498
|
-
|
|
111499
|
-
} catch {
|
|
111826
|
+
launcher = inspectLauncher(path);
|
|
111827
|
+
} catch (error61) {
|
|
111828
|
+
if (error61 instanceof Error && error61.message === "LAUNCHER_TARGET_UNREADABLE")
|
|
111829
|
+
throw error61;
|
|
111500
111830
|
continue;
|
|
111501
111831
|
}
|
|
111502
|
-
if (
|
|
111832
|
+
if (launcher.kind === "foreign")
|
|
111503
111833
|
continue;
|
|
111504
|
-
|
|
111505
|
-
try {
|
|
111506
|
-
actual = realpathSync17(path);
|
|
111507
|
-
} catch {
|
|
111508
|
-
throw new Error("LAUNCHER_TARGET_UNREADABLE");
|
|
111509
|
-
}
|
|
111834
|
+
const actual = launcher.target;
|
|
111510
111835
|
if (actual !== join60(currentPackageRoot, target))
|
|
111511
111836
|
continue;
|
|
111512
|
-
const oldLinkTarget = readlinkSync6(path);
|
|
111513
|
-
if (resolve26(dirname32(path), oldLinkTarget) !== actual)
|
|
111514
|
-
throw new Error("LAUNCHER_SYMLINK_CHAIN_UNSUPPORTED");
|
|
111515
111837
|
const newTarget = join60(runtimeRoot, "__target__", "node_modules", "@hasna", "skills", target);
|
|
111516
|
-
|
|
111838
|
+
const backupPath = `${path}.skills-prev-${randomUUID10()}`;
|
|
111839
|
+
if (launcher.kind === "symlink") {
|
|
111840
|
+
if (resolve26(dirname32(path), launcher.linkTarget) !== actual)
|
|
111841
|
+
throw new Error("LAUNCHER_SYMLINK_CHAIN_UNSUPPORTED");
|
|
111842
|
+
launchers.push({ path, oldTarget: actual, oldLinkTarget: launcher.linkTarget, newTarget, backupPath, oldShape: "symlink" });
|
|
111843
|
+
} else {
|
|
111844
|
+
launchers.push({ path, oldTarget: actual, oldLinkTarget: actual, newTarget, backupPath, oldShape: "pinned", oldRuntime: launcher.runtime, oldCwd: launcher.cwd, oldSha256: launcher.sha256 });
|
|
111845
|
+
}
|
|
111517
111846
|
}
|
|
111518
111847
|
}
|
|
111519
111848
|
if (!launchers.some((item) => item.path === launcherPath))
|
|
@@ -111526,7 +111855,7 @@ function verifyIntegrity(bytes, integrity) {
|
|
|
111526
111855
|
const match = /^sha512-([A-Za-z0-9+/]+={0,2})$/.exec(integrity);
|
|
111527
111856
|
if (!match)
|
|
111528
111857
|
throw new Error("REGISTRY_INTEGRITY_UNSUPPORTED");
|
|
111529
|
-
const actual =
|
|
111858
|
+
const actual = createHash35("sha512").update(bytes).digest("base64");
|
|
111530
111859
|
if (actual !== match[1])
|
|
111531
111860
|
throw new Error("TARBALL_INTEGRITY_MISMATCH");
|
|
111532
111861
|
}
|
|
@@ -111671,7 +112000,7 @@ async function downloadPackage(version2, stagingRoot, registryOrigin, fetcher) {
|
|
|
111671
112000
|
const extracted = readTree(extractedPackage, false);
|
|
111672
112001
|
const tarballPath = join60(stagingRoot, "verified-package.tgz");
|
|
111673
112002
|
writeFileSync24(tarballPath, bytes, { flag: "wx", mode: 384 });
|
|
111674
|
-
if (!
|
|
112003
|
+
if (!readFileSync40(tarballPath).equals(Buffer.from(bytes)))
|
|
111675
112004
|
throw new Error("TARBALL_READBACK_MISMATCH");
|
|
111676
112005
|
return {
|
|
111677
112006
|
tarballPath,
|
|
@@ -111713,26 +112042,26 @@ async function readBodyCapped(response, limit, errorCode) {
|
|
|
111713
112042
|
return bytes;
|
|
111714
112043
|
}
|
|
111715
112044
|
function readTree(root2, includeModes, excludeNpmDependencies = false) {
|
|
111716
|
-
const base3 =
|
|
112045
|
+
const base3 = realpathSync18(root2);
|
|
111717
112046
|
const entries = [];
|
|
111718
112047
|
const walk2 = (dir, prefix = "") => {
|
|
111719
112048
|
for (const item of readdirSync21(dir).sort()) {
|
|
111720
112049
|
const path = join60(dir, item);
|
|
111721
112050
|
const rel = prefix ? `${prefix}/${item}` : item;
|
|
111722
|
-
const stat3 =
|
|
112051
|
+
const stat3 = lstatSync32(path);
|
|
111723
112052
|
if (excludeNpmDependencies && !prefix && item === "node_modules") {
|
|
111724
112053
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
111725
112054
|
throw new Error("INSTALLED_DEPENDENCY_DIRECTORY_UNSAFE");
|
|
111726
112055
|
continue;
|
|
111727
112056
|
}
|
|
111728
112057
|
if (stat3.isSymbolicLink()) {
|
|
111729
|
-
const link2 =
|
|
112058
|
+
const link2 = readlinkSync7(path);
|
|
111730
112059
|
const resolved = resolve26(dirname32(path), link2);
|
|
111731
112060
|
if (!isWithin(base3, resolved))
|
|
111732
112061
|
throw new Error("TREE_SYMLINK_ESCAPES_ROOT");
|
|
111733
112062
|
let physicalTarget2;
|
|
111734
112063
|
try {
|
|
111735
|
-
physicalTarget2 =
|
|
112064
|
+
physicalTarget2 = realpathSync18(path);
|
|
111736
112065
|
} catch {
|
|
111737
112066
|
throw new Error("TREE_SYMLINK_TARGET_MISSING");
|
|
111738
112067
|
}
|
|
@@ -111745,7 +112074,7 @@ function readTree(root2, includeModes, excludeNpmDependencies = false) {
|
|
|
111745
112074
|
} else if (stat3.isFile()) {
|
|
111746
112075
|
if (stat3.nlink !== 1)
|
|
111747
112076
|
throw new Error("TREE_HARDLINK_UNSUPPORTED");
|
|
111748
|
-
const bytes =
|
|
112077
|
+
const bytes = readFileSync40(path);
|
|
111749
112078
|
entries.push({ path: rel, kind: "file", sha256: hash5(bytes), ...includeModes ? { mode: stat3.mode & 511 } : {} });
|
|
111750
112079
|
} else
|
|
111751
112080
|
throw new Error("TREE_ENTRY_TYPE_UNSUPPORTED");
|
|
@@ -111755,14 +112084,14 @@ function readTree(root2, includeModes, excludeNpmDependencies = false) {
|
|
|
111755
112084
|
return { entries, digest: hash5(new TextEncoder().encode(JSON.stringify(entries))) };
|
|
111756
112085
|
}
|
|
111757
112086
|
function normalizeModes(root2) {
|
|
111758
|
-
const rootStat =
|
|
112087
|
+
const rootStat = lstatSync32(root2);
|
|
111759
112088
|
if (!rootStat.isDirectory() || rootStat.isSymbolicLink())
|
|
111760
112089
|
throw new Error("RUNTIME_ENTRY_TYPE_UNSUPPORTED");
|
|
111761
112090
|
chmodSync4(root2, rootStat.mode & 493);
|
|
111762
112091
|
const walk2 = (dir) => {
|
|
111763
112092
|
for (const item of readdirSync21(dir)) {
|
|
111764
112093
|
const path = join60(dir, item);
|
|
111765
|
-
const stat3 =
|
|
112094
|
+
const stat3 = lstatSync32(path);
|
|
111766
112095
|
if (stat3.isSymbolicLink())
|
|
111767
112096
|
continue;
|
|
111768
112097
|
if (stat3.isDirectory()) {
|
|
@@ -111781,7 +112110,7 @@ function writeJsonPrivate(path, value) {
|
|
|
111781
112110
|
`);
|
|
111782
112111
|
writeFileSync24(path, bytes, { flag: "wx", mode: 384 });
|
|
111783
112112
|
chmodSync4(path, 384);
|
|
111784
|
-
if (!
|
|
112113
|
+
if (!readFileSync40(path).equals(bytes))
|
|
111785
112114
|
throw new Error("PRIVATE_JSON_READBACK_MISMATCH");
|
|
111786
112115
|
}
|
|
111787
112116
|
function writePreimageManifest(stage, configs, launchers) {
|
|
@@ -111791,13 +112120,13 @@ function writePreimageManifest(stage, configs, launchers) {
|
|
|
111791
112120
|
`);
|
|
111792
112121
|
writeFileSync24(path, bytes, { flag: "wx", mode: 256 });
|
|
111793
112122
|
chmodSync4(path, 256);
|
|
111794
|
-
if (!
|
|
112123
|
+
if (!readFileSync40(path).equals(bytes))
|
|
111795
112124
|
throw new Error("PREIMAGE_MANIFEST_READBACK_MISMATCH");
|
|
111796
112125
|
return hash5(bytes);
|
|
111797
112126
|
}
|
|
111798
112127
|
function verifyPreimageManifest(runtimePath, receipt, home) {
|
|
111799
112128
|
const path = join60(runtimePath, "preimage", "manifest.json");
|
|
111800
|
-
const bytes =
|
|
112129
|
+
const bytes = readFileSync40(path);
|
|
111801
112130
|
if (hash5(bytes) !== receipt.preimageSha256)
|
|
111802
112131
|
throw new Error("PREIMAGE_MANIFEST_DRIFT");
|
|
111803
112132
|
const manifest = object10(JSON.parse(bytes.toString("utf8")), "PREIMAGE_MANIFEST_INVALID");
|
|
@@ -111812,8 +112141,8 @@ function verifyPreimageManifest(runtimePath, receipt, home) {
|
|
|
111812
112141
|
throw new Error("PREIMAGE_CONFIG_BINDING_INVALID");
|
|
111813
112142
|
if (config2.present) {
|
|
111814
112143
|
const backup = join60(runtimePath, "preimage", "configs", relativePath);
|
|
111815
|
-
const stat3 =
|
|
111816
|
-
const saved =
|
|
112144
|
+
const stat3 = lstatSync32(backup);
|
|
112145
|
+
const saved = readFileSync40(backup);
|
|
111817
112146
|
if (!stat3.isFile() || stat3.isSymbolicLink() || hash5(saved) !== config2.sha256 || saved.byteLength !== config2.byteSize)
|
|
111818
112147
|
throw new Error("PREIMAGE_CONFIG_DRIFT");
|
|
111819
112148
|
}
|
|
@@ -111826,15 +112155,15 @@ function captureConfigPreimages(home, stage) {
|
|
|
111826
112155
|
const sourcePath = join60(home, relativePath);
|
|
111827
112156
|
if (!entryExists(sourcePath))
|
|
111828
112157
|
return { sourcePath, relativePath, present: false };
|
|
111829
|
-
const stat3 =
|
|
112158
|
+
const stat3 = lstatSync32(sourcePath);
|
|
111830
112159
|
if (!stat3.isFile() || stat3.isSymbolicLink())
|
|
111831
112160
|
throw new Error("CONFIG_PREIMAGE_NOT_REGULAR_FILE");
|
|
111832
|
-
const bytes =
|
|
112161
|
+
const bytes = readFileSync40(sourcePath);
|
|
111833
112162
|
const backupPath = join60(root2, relativePath);
|
|
111834
112163
|
mkdirSync25(dirname32(backupPath), { recursive: true, mode: 448 });
|
|
111835
112164
|
writeFileSync24(backupPath, bytes, { flag: "wx", mode: 384 });
|
|
111836
112165
|
chmodSync4(backupPath, 384);
|
|
111837
|
-
const readback =
|
|
112166
|
+
const readback = readFileSync40(backupPath);
|
|
111838
112167
|
if (!readback.equals(bytes))
|
|
111839
112168
|
throw new Error("CONFIG_PREIMAGE_READBACK_MISMATCH");
|
|
111840
112169
|
return { sourcePath, relativePath, present: true, sha256: hash5(bytes), byteSize: bytes.byteLength };
|
|
@@ -111846,8 +112175,8 @@ function assertConfigUnchanged(configs) {
|
|
|
111846
112175
|
if (present !== config2.present)
|
|
111847
112176
|
throw new Error("CONFIG_DRIFT_DURING_UPDATE");
|
|
111848
112177
|
if (present) {
|
|
111849
|
-
const stat3 =
|
|
111850
|
-
if (!stat3.isFile() || stat3.isSymbolicLink() || hash5(
|
|
112178
|
+
const stat3 = lstatSync32(config2.sourcePath);
|
|
112179
|
+
if (!stat3.isFile() || stat3.isSymbolicLink() || hash5(readFileSync40(config2.sourcePath)) !== config2.sha256) {
|
|
111851
112180
|
throw new Error("CONFIG_DRIFT_DURING_UPDATE");
|
|
111852
112181
|
}
|
|
111853
112182
|
}
|
|
@@ -111910,7 +112239,7 @@ ignore-scripts=true
|
|
|
111910
112239
|
const capabilityNpmrc = join60(staging, "npm-capability.npmrc");
|
|
111911
112240
|
if (policy && !existsSync34(capabilityNpmrc))
|
|
111912
112241
|
writeFileSync24(capabilityNpmrc, baseConfig, { mode: 384, flag: "wx" });
|
|
111913
|
-
if (policy &&
|
|
112242
|
+
if (policy && readFileSync40(capabilityNpmrc, "utf8") !== baseConfig)
|
|
111914
112243
|
throw new Error("NPM_ISOLATED_CONFIG_DRIFT");
|
|
111915
112244
|
const npmVersion = policy ? await npmReleaseAgeCapability(cwd2, { ...env3, NPM_CONFIG_USERCONFIG: capabilityNpmrc }) : undefined;
|
|
111916
112245
|
const config2 = baseConfig + (policy ? `min-release-age=${policy.minReleaseAge}
|
|
@@ -111918,7 +112247,7 @@ ${policy.minReleaseAgeExclude.map((pattern) => `min-release-age-exclude[]=${patt
|
|
|
111918
112247
|
`).join("")}` : "");
|
|
111919
112248
|
if (!existsSync34(userNpmrc))
|
|
111920
112249
|
writeFileSync24(userNpmrc, config2, { mode: 384, flag: "wx" });
|
|
111921
|
-
if (
|
|
112250
|
+
if (readFileSync40(userNpmrc, "utf8") !== config2 || readFileSync40(globalNpmrc, "utf8") !== baseConfig)
|
|
111922
112251
|
throw new Error("NPM_ISOLATED_CONFIG_DRIFT");
|
|
111923
112252
|
const proc = Bun.spawn(["npm", ...args2, "--registry", `${REGISTRY_ORIGIN}/`, "--ignore-scripts", "--no-audit", "--no-fund"], {
|
|
111924
112253
|
cwd: cwd2,
|
|
@@ -111941,18 +112270,26 @@ function comparePackageTrees(expectedRoot, installedRoot) {
|
|
|
111941
112270
|
throw new Error("INSTALLED_PACKAGE_BYTES_MISMATCH");
|
|
111942
112271
|
return expected.digest;
|
|
111943
112272
|
}
|
|
111944
|
-
function
|
|
111945
|
-
const
|
|
111946
|
-
if (!
|
|
112273
|
+
function replaceLauncher(item) {
|
|
112274
|
+
const oldState = oldLauncherState(item), newState = newLauncherState(item);
|
|
112275
|
+
if (!launcherIs(item.path, oldState) || entryExists(item.backupPath))
|
|
111947
112276
|
throw new Error("LAUNCHER_PREIMAGE_DRIFT");
|
|
111948
|
-
const temp = `${path}.skills-next-${randomUUID10()}`;
|
|
111949
|
-
|
|
111950
|
-
|
|
112277
|
+
const temp = `${item.path}.skills-next-${randomUUID10()}`;
|
|
112278
|
+
try {
|
|
112279
|
+
materializeLauncher(item.backupPath, oldState);
|
|
112280
|
+
} catch {
|
|
111951
112281
|
throw new Error("LAUNCHER_BACKUP_READBACK_MISMATCH");
|
|
111952
|
-
|
|
111953
|
-
if (
|
|
112282
|
+
}
|
|
112283
|
+
if (!launcherIs(item.backupPath, oldState))
|
|
112284
|
+
throw new Error("LAUNCHER_BACKUP_READBACK_MISMATCH");
|
|
112285
|
+
try {
|
|
112286
|
+
materializeLauncher(temp, newState);
|
|
112287
|
+
} catch {
|
|
111954
112288
|
throw new Error("LAUNCHER_NEW_LINK_READBACK_MISMATCH");
|
|
111955
|
-
|
|
112289
|
+
}
|
|
112290
|
+
if (!launcherIs(temp, newState))
|
|
112291
|
+
throw new Error("LAUNCHER_NEW_LINK_READBACK_MISMATCH");
|
|
112292
|
+
renameSync14(temp, item.path);
|
|
111956
112293
|
}
|
|
111957
112294
|
function atomicJson(path, value) {
|
|
111958
112295
|
const temp = `${path}.next-${randomUUID10()}`;
|
|
@@ -111961,12 +112298,12 @@ function atomicJson(path, value) {
|
|
|
111961
112298
|
writeFileSync24(temp, bytes, { flag: "wx", mode: 384 });
|
|
111962
112299
|
chmodSync4(temp, 384);
|
|
111963
112300
|
renameSync14(temp, path);
|
|
111964
|
-
if (!
|
|
112301
|
+
if (!readFileSync40(path).equals(bytes))
|
|
111965
112302
|
throw new Error("RECEIPT_READBACK_MISMATCH");
|
|
111966
112303
|
}
|
|
111967
112304
|
function persistReceipt(path, value) {
|
|
111968
112305
|
if (entryExists(path)) {
|
|
111969
|
-
const priorBytes =
|
|
112306
|
+
const priorBytes = readFileSync40(path);
|
|
111970
112307
|
const prior = object10(JSON.parse(priorBytes.toString("utf8")), "RECEIPT_INVALID");
|
|
111971
112308
|
if (prior.id !== value.id || prior.schema !== "skills.copyfile-runtime-receipt.v1" || typeof prior.state !== "string" || !/^[a-z-]{1,32}$/.test(prior.state))
|
|
111972
112309
|
throw new Error("RECEIPT_ID_DRIFT");
|
|
@@ -111977,20 +112314,20 @@ function persistReceipt(path, value) {
|
|
|
111977
112314
|
const historyRoot = join60(dirname32(path), "receipt-history");
|
|
111978
112315
|
if (!entryExists(historyRoot))
|
|
111979
112316
|
mkdirSync25(historyRoot, { mode: 448 });
|
|
111980
|
-
const historyStat =
|
|
112317
|
+
const historyStat = lstatSync32(historyRoot);
|
|
111981
112318
|
if (!historyStat.isDirectory() || historyStat.isSymbolicLink() || (historyStat.mode & 63) !== 0)
|
|
111982
112319
|
throw new Error("RECEIPT_HISTORY_NOT_PRIVATE");
|
|
111983
112320
|
const historyPath = join60(historyRoot, `${value.id}-${String(prior.state)}-${randomUUID10()}.json`);
|
|
111984
112321
|
writeFileSync24(historyPath, priorBytes, { flag: "wx", mode: 256 });
|
|
111985
112322
|
chmodSync4(historyPath, 256);
|
|
111986
|
-
if (!
|
|
112323
|
+
if (!readFileSync40(historyPath).equals(priorBytes))
|
|
111987
112324
|
throw new Error("RECEIPT_HISTORY_READBACK_MISMATCH");
|
|
111988
112325
|
}
|
|
111989
112326
|
atomicJson(path, value);
|
|
111990
112327
|
}
|
|
111991
112328
|
function persistAliasReceipt(path, value) {
|
|
111992
112329
|
if (entryExists(path)) {
|
|
111993
|
-
const priorBytes =
|
|
112330
|
+
const priorBytes = readFileSync40(path);
|
|
111994
112331
|
const prior = object10(JSON.parse(priorBytes.toString("utf8")), "ALIAS_RECEIPT_INVALID");
|
|
111995
112332
|
if (prior.schema !== value.schema || prior.id !== value.id || typeof prior.state !== "string")
|
|
111996
112333
|
throw new Error("ALIAS_RECEIPT_DRIFT");
|
|
@@ -112001,13 +112338,13 @@ function persistAliasReceipt(path, value) {
|
|
|
112001
112338
|
const history = join60(dirname32(path), "history");
|
|
112002
112339
|
if (!entryExists(history))
|
|
112003
112340
|
mkdirSync25(history, { mode: 448 });
|
|
112004
|
-
const historyStat =
|
|
112341
|
+
const historyStat = lstatSync32(history);
|
|
112005
112342
|
if (!historyStat.isDirectory() || historyStat.isSymbolicLink() || (historyStat.mode & 63) !== 0)
|
|
112006
112343
|
throw new Error("ALIAS_RECEIPT_HISTORY_UNSAFE");
|
|
112007
112344
|
const saved = join60(history, `${value.id}-${String(prior.state)}-${randomUUID10()}.json`);
|
|
112008
112345
|
writeFileSync24(saved, priorBytes, { flag: "wx", mode: 256 });
|
|
112009
112346
|
chmodSync4(saved, 256);
|
|
112010
|
-
if (!
|
|
112347
|
+
if (!readFileSync40(saved).equals(priorBytes))
|
|
112011
112348
|
throw new Error("ALIAS_RECEIPT_HISTORY_READBACK_MISMATCH");
|
|
112012
112349
|
}
|
|
112013
112350
|
atomicJson(path, value);
|
|
@@ -112015,7 +112352,7 @@ function persistAliasReceipt(path, value) {
|
|
|
112015
112352
|
function assertOwnedSafePath(path, home, requireWritable = false) {
|
|
112016
112353
|
assertNoSymlinkAncestors(path);
|
|
112017
112354
|
for (let current = path;; current = dirname32(current)) {
|
|
112018
|
-
const stat3 =
|
|
112355
|
+
const stat3 = lstatSync32(current);
|
|
112019
112356
|
if (!stat3.isDirectory() || ![0, process.getuid?.() ?? -1].includes(stat3.uid) || stat3.mode & 18)
|
|
112020
112357
|
throw new Error("ALIAS_PATH_UNSAFE");
|
|
112021
112358
|
if (current === path && requireWritable && (stat3.uid !== (process.getuid?.() ?? -1) || (stat3.mode & 128) === 0))
|
|
@@ -112028,8 +112365,8 @@ function activeAliasRuntime(home, pathValue) {
|
|
|
112028
112365
|
const layout = resolveRuntimeLayout(home, pathValue);
|
|
112029
112366
|
const runtimePath = dirname32(dirname32(dirname32(layout.currentPackageRoot)));
|
|
112030
112367
|
const receiptPath = join60(runtimePath, "rollout-receipt.json");
|
|
112031
|
-
const rollout = object10(JSON.parse(
|
|
112032
|
-
if (rollout.schema !== "skills.copyfile-runtime-receipt.v1" || rollout.state !== "switched" || rollout.targetPackageRoot !== layout.currentPackageRoot || rollout.targetVersion !== layout.currentVersion || rollout.runtimeRoot !== layout.runtimeRoot || rollout.package !== PACKAGE_NAME || hash5(
|
|
112368
|
+
const rollout = object10(JSON.parse(readFileSync40(receiptPath, "utf8")), "ROLLOUT_RECEIPT_INVALID");
|
|
112369
|
+
if (rollout.schema !== "skills.copyfile-runtime-receipt.v1" || rollout.state !== "switched" || rollout.targetPackageRoot !== layout.currentPackageRoot || rollout.targetVersion !== layout.currentVersion || rollout.runtimeRoot !== layout.runtimeRoot || rollout.package !== PACKAGE_NAME || hash5(readFileSync40(join60(runtimePath, "verified-package.tgz"))) !== rollout.tarballSha256 || readTree(join60(runtimePath, "node_modules"), true).digest !== rollout.runtimeTreeSha256) {
|
|
112033
112370
|
throw new Error("ACTIVE_RUNTIME_RECEIPT_DRIFT");
|
|
112034
112371
|
}
|
|
112035
112372
|
verifyPreimageManifest(runtimePath, rollout, home);
|
|
@@ -112063,9 +112400,9 @@ function inspectAliasPackageChain(home, aliasPath, oldLinkTarget, oldTarget, bin
|
|
|
112063
112400
|
assertOwnedSafePath(dirname32(packageLinkPath), home);
|
|
112064
112401
|
let stat3, packageLinkTarget, resolved;
|
|
112065
112402
|
try {
|
|
112066
|
-
stat3 =
|
|
112067
|
-
packageLinkTarget =
|
|
112068
|
-
resolved =
|
|
112403
|
+
stat3 = lstatSync32(packageLinkPath);
|
|
112404
|
+
packageLinkTarget = readlinkSync7(packageLinkPath);
|
|
112405
|
+
resolved = realpathSync18(packageLinkPath);
|
|
112069
112406
|
} catch {
|
|
112070
112407
|
throw new Error("ALIAS_LINK_CHAIN_UNSUPPORTED");
|
|
112071
112408
|
}
|
|
@@ -112086,22 +112423,24 @@ function validateAliasSource(home, name, actual) {
|
|
|
112086
112423
|
}
|
|
112087
112424
|
assertOwnedSafePath(packageRoot, home);
|
|
112088
112425
|
const manifestPath = join60(packageRoot, "package.json");
|
|
112089
|
-
const manifestStat =
|
|
112426
|
+
const manifestStat = lstatSync32(manifestPath), binaryStat = lstatSync32(actual);
|
|
112090
112427
|
if (!manifestStat.isFile() || manifestStat.isSymbolicLink() || !binaryStat.isFile() || binaryStat.isSymbolicLink() || ![0, process.getuid?.() ?? -1].includes(manifestStat.uid) || ![0, process.getuid?.() ?? -1].includes(binaryStat.uid) || manifestStat.mode & 18)
|
|
112091
112428
|
throw new Error("ALIAS_SOURCE_UNSAFE");
|
|
112092
112429
|
const pkg = readPackage(manifestPath);
|
|
112093
112430
|
if (!pkg.bins[name] || actual !== join60(packageRoot, pkg.bins[name]))
|
|
112094
112431
|
throw new Error("ALIAS_SOURCE_BIN_MISMATCH");
|
|
112095
|
-
return { version: pkg.version, packageRoot, binarySha256: hash5(
|
|
112432
|
+
return { version: pkg.version, packageRoot, binarySha256: hash5(readFileSync40(actual)) };
|
|
112096
112433
|
}
|
|
112097
112434
|
function adoptCopyfileAliases(options = {}) {
|
|
112098
|
-
const home =
|
|
112435
|
+
const home = realpathSync18(resolve26(options.homeDir ?? process.env.HOME ?? ""));
|
|
112099
112436
|
const pathValue = options.pathValue ?? process.env.PATH ?? "";
|
|
112100
112437
|
const { layout, rollout } = activeAliasRuntime(home, pathValue);
|
|
112438
|
+
const currentRuntime = dirname32(dirname32(dirname32(layout.currentPackageRoot)));
|
|
112439
|
+
const launcherRuntime = pinnedLauncherRuntime();
|
|
112440
|
+
pinnedLauncherState(launcherRuntime, currentRuntime, join60(layout.currentPackageRoot, layout.bin.skills ?? "bin/index.js"));
|
|
112101
112441
|
const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
|
|
112102
112442
|
const id2 = randomUUID10();
|
|
112103
112443
|
const aliases = [];
|
|
112104
|
-
const currentRuntime = dirname32(dirname32(dirname32(layout.currentPackageRoot)));
|
|
112105
112444
|
const receiptDir = join60(currentRuntime, "alias-adoptions");
|
|
112106
112445
|
const receiptPath = join60(receiptDir, `${id2}.json`);
|
|
112107
112446
|
let receipt;
|
|
@@ -112117,16 +112456,19 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
112117
112456
|
if (!entryExists(path))
|
|
112118
112457
|
continue;
|
|
112119
112458
|
assertOwnedSafePath(dir, home, true);
|
|
112120
|
-
const stat3 =
|
|
112121
|
-
if (
|
|
112459
|
+
const stat3 = lstatSync32(path);
|
|
112460
|
+
if (stat3.uid !== (process.getuid?.() ?? -1))
|
|
112122
112461
|
throw new Error("ALIAS_LINK_NOT_OWNED");
|
|
112123
|
-
|
|
112124
|
-
let actual;
|
|
112462
|
+
let launcher;
|
|
112125
112463
|
try {
|
|
112126
|
-
|
|
112464
|
+
launcher = inspectLauncher(path);
|
|
112127
112465
|
} catch {
|
|
112128
112466
|
throw new Error("ALIAS_LINK_CHAIN_UNSUPPORTED");
|
|
112129
112467
|
}
|
|
112468
|
+
if (launcher.kind === "foreign")
|
|
112469
|
+
throw new Error("ALIAS_LINK_NOT_OWNED");
|
|
112470
|
+
const actual = launcher.target;
|
|
112471
|
+
const oldLinkTarget = launcher.kind === "symlink" ? launcher.linkTarget : actual;
|
|
112130
112472
|
const newTarget = join60(layout.currentPackageRoot, target);
|
|
112131
112473
|
if (actual === newTarget)
|
|
112132
112474
|
continue;
|
|
@@ -112135,13 +112477,25 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
112135
112477
|
const backupPath = `${path}.skills-alias-prev-${id2}`;
|
|
112136
112478
|
if (entryExists(backupPath))
|
|
112137
112479
|
throw new Error("ALIAS_BACKUP_COLLISION");
|
|
112138
|
-
|
|
112480
|
+
const oldFields = launcher.kind === "symlink" ? { oldShape: "symlink" } : { oldShape: "pinned", oldRuntime: launcher.runtime, oldCwd: launcher.cwd, oldSha256: launcher.sha256 };
|
|
112481
|
+
aliases.push({
|
|
112482
|
+
path,
|
|
112483
|
+
oldTarget: actual,
|
|
112484
|
+
oldLinkTarget,
|
|
112485
|
+
oldVersion: source.version,
|
|
112486
|
+
oldBinarySha256: source.binarySha256,
|
|
112487
|
+
newTarget,
|
|
112488
|
+
backupPath,
|
|
112489
|
+
...oldFields,
|
|
112490
|
+
...pinnedRecordFields(launcherRuntime, currentRuntime, newTarget),
|
|
112491
|
+
...chain ? { chain } : {}
|
|
112492
|
+
});
|
|
112139
112493
|
}
|
|
112140
112494
|
}
|
|
112141
112495
|
if (!aliases.length)
|
|
112142
112496
|
return { adopted: true, version: layout.currentVersion, aliasCount: 0 };
|
|
112143
112497
|
mkdirSync25(receiptDir, { recursive: true, mode: 448 });
|
|
112144
|
-
const receiptDirStat =
|
|
112498
|
+
const receiptDirStat = lstatSync32(receiptDir);
|
|
112145
112499
|
if (!receiptDirStat.isDirectory() || receiptDirStat.isSymbolicLink() || receiptDirStat.mode & 63)
|
|
112146
112500
|
throw new Error("ALIAS_RECEIPT_DIRECTORY_UNSAFE");
|
|
112147
112501
|
receipt = {
|
|
@@ -112157,7 +112511,7 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
112157
112511
|
};
|
|
112158
112512
|
writeJsonPrivate(receiptPath, receipt);
|
|
112159
112513
|
for (const item of aliases) {
|
|
112160
|
-
if (
|
|
112514
|
+
if (!launcherIs(item.path, oldLauncherState(item)))
|
|
112161
112515
|
throw new Error("ALIAS_CHANGED_BEFORE_SWITCH");
|
|
112162
112516
|
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename15(item.path)], item.chain, true);
|
|
112163
112517
|
const source = validateAliasSource(home, basename15(item.path), item.oldTarget);
|
|
@@ -112166,15 +112520,15 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
112166
112520
|
receipt.state = "switching";
|
|
112167
112521
|
receipt.switchedAliases = [...receipt.switchedAliases, item.path];
|
|
112168
112522
|
persistAliasReceipt(receiptPath, receipt);
|
|
112169
|
-
|
|
112170
|
-
if (
|
|
112523
|
+
replaceLauncher(item);
|
|
112524
|
+
if (!launcherIs(item.path, newLauncherState(item)) || !launcherIs(item.backupPath, oldLauncherState(item)))
|
|
112171
112525
|
throw new Error("ALIAS_SWITCH_READBACK_MISMATCH");
|
|
112172
112526
|
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename15(item.path)], item.chain, true);
|
|
112173
112527
|
options.onAliasSwitched?.(item.path);
|
|
112174
112528
|
}
|
|
112175
112529
|
for (const item of aliases) {
|
|
112176
112530
|
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename15(item.path)], item.chain, true);
|
|
112177
|
-
if (
|
|
112531
|
+
if (!launcherIs(item.backupPath, oldLauncherState(item)))
|
|
112178
112532
|
throw new Error("ALIAS_BACKUP_DRIFT");
|
|
112179
112533
|
}
|
|
112180
112534
|
receipt.state = "switched";
|
|
@@ -112188,28 +112542,28 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
112188
112542
|
if (!entryExists(item.backupPath)) {
|
|
112189
112543
|
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename15(item.path)], item.chain, true);
|
|
112190
112544
|
const source2 = validateAliasSource(home, basename15(item.path), item.oldTarget);
|
|
112191
|
-
if (!entryExists(item.path) ||
|
|
112545
|
+
if (!entryExists(item.path) || !launcherIs(item.path, oldLauncherState(item)) || source2.version !== item.oldVersion || source2.binarySha256 !== item.oldBinarySha256)
|
|
112192
112546
|
failed = true;
|
|
112193
112547
|
continue;
|
|
112194
112548
|
}
|
|
112195
|
-
if (
|
|
112549
|
+
if (!launcherIs(item.backupPath, oldLauncherState(item)))
|
|
112196
112550
|
throw new Error("ALIAS_BACKUP_DRIFT");
|
|
112197
112551
|
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, layout.bin[basename15(item.path)], item.chain, true);
|
|
112198
112552
|
const source = validateAliasSource(home, basename15(item.path), item.oldTarget);
|
|
112199
112553
|
if (source.version !== item.oldVersion || source.binarySha256 !== item.oldBinarySha256)
|
|
112200
112554
|
throw new Error("ALIAS_SOURCE_DRIFT");
|
|
112201
|
-
if (
|
|
112555
|
+
if (launcherIs(item.path, oldLauncherState(item)))
|
|
112202
112556
|
continue;
|
|
112203
|
-
if (
|
|
112557
|
+
if (launcherTarget(item.path) !== item.newTarget)
|
|
112204
112558
|
throw new Error("ALIAS_CHANGED_DURING_ROLLBACK");
|
|
112205
112559
|
const after2 = `${item.path}.skills-alias-after-${id2}`;
|
|
112206
112560
|
if (entryExists(after2))
|
|
112207
112561
|
throw new Error("ALIAS_AFTER_COLLISION");
|
|
112208
|
-
|
|
112562
|
+
materializeLauncher(after2, newLauncherState(item));
|
|
112209
112563
|
const temp = `${item.path}.skills-alias-rollback-${randomUUID10()}`;
|
|
112210
|
-
|
|
112564
|
+
materializeLauncher(temp, oldLauncherState(item));
|
|
112211
112565
|
renameSync14(temp, item.path);
|
|
112212
|
-
if (
|
|
112566
|
+
if (!launcherIs(item.path, oldLauncherState(item)))
|
|
112213
112567
|
throw new Error("ALIAS_ROLLBACK_READBACK_MISMATCH");
|
|
112214
112568
|
receipt.rollbackCompletedAliases = [...receipt.rollbackCompletedAliases, item.path];
|
|
112215
112569
|
persistAliasReceipt(receiptPath, receipt);
|
|
@@ -112233,7 +112587,7 @@ function adoptCopyfileAliases(options = {}) {
|
|
|
112233
112587
|
function rollbackCopyfileAliases(receiptId, options = {}) {
|
|
112234
112588
|
if (!/^[0-9a-f-]{36}$/.test(receiptId))
|
|
112235
112589
|
throw new Error("ALIAS_RECEIPT_ID_INVALID");
|
|
112236
|
-
const home =
|
|
112590
|
+
const home = realpathSync18(resolve26(options.homeDir ?? process.env.HOME ?? ""));
|
|
112237
112591
|
const pathValue = options.pathValue ?? process.env.PATH ?? "";
|
|
112238
112592
|
const { layout, rollout } = activeAliasRuntime(home, pathValue);
|
|
112239
112593
|
const runtimePath = dirname32(dirname32(dirname32(layout.currentPackageRoot)));
|
|
@@ -112243,7 +112597,7 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
|
|
|
112243
112597
|
const locked2 = activeAliasRuntime(home, pathValue);
|
|
112244
112598
|
if (locked2.layout.currentPackageRoot !== layout.currentPackageRoot || locked2.rollout.id !== rollout.id)
|
|
112245
112599
|
throw new Error("ACTIVE_RUNTIME_CHANGED_BEFORE_ALIAS_ROLLBACK");
|
|
112246
|
-
const receipt = object10(JSON.parse(
|
|
112600
|
+
const receipt = object10(JSON.parse(readFileSync40(receiptPath, "utf8")), "ALIAS_RECEIPT_INVALID");
|
|
112247
112601
|
if (receipt.schema !== "skills.copyfile-alias-adoption.v1" || receipt.id !== receiptId || !["switched", "switching", "rollback-required"].includes(receipt.state) || receipt.targetPackageRoot !== layout.currentPackageRoot || receipt.targetVersion !== layout.currentVersion || receipt.rolloutReceiptId !== rollout.id || !Array.isArray(receipt.aliases))
|
|
112248
112602
|
throw new Error("ALIAS_RECEIPT_BINDING_INVALID");
|
|
112249
112603
|
const seen = new Set;
|
|
@@ -112253,20 +112607,25 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
|
|
|
112253
112607
|
throw new Error("ALIAS_RECEIPT_LAUNCHER_INVALID");
|
|
112254
112608
|
}
|
|
112255
112609
|
inspectAliasPackageChain(home, item.path, item.oldLinkTarget, item.oldTarget, target, item.chain, true);
|
|
112610
|
+
assertLauncherRecordShapes(item);
|
|
112256
112611
|
seen.add(item.path);
|
|
112257
112612
|
assertOwnedSafePath(dirname32(item.path), home, true);
|
|
112258
112613
|
const source = validateAliasSource(home, name, item.oldTarget);
|
|
112259
112614
|
if (source.version !== item.oldVersion || source.binarySha256 !== item.oldBinarySha256)
|
|
112260
112615
|
throw new Error("ALIAS_PREIMAGE_DRIFT");
|
|
112261
|
-
const stat3 =
|
|
112262
|
-
if (
|
|
112616
|
+
const stat3 = lstatSync32(item.path);
|
|
112617
|
+
if (stat3.uid !== (process.getuid?.() ?? -1))
|
|
112263
112618
|
throw new Error("ALIAS_LINK_DRIFT");
|
|
112264
|
-
|
|
112265
|
-
|
|
112619
|
+
let current;
|
|
112620
|
+
try {
|
|
112621
|
+
current = launcherTarget(item.path);
|
|
112622
|
+
} catch {
|
|
112623
|
+
throw new Error("ALIAS_LINK_DRIFT");
|
|
112624
|
+
}
|
|
112625
|
+
if (!launcherIs(item.path, newLauncherState(item)) && !launcherIs(item.path, oldLauncherState(item)))
|
|
112266
112626
|
throw new Error("ALIAS_TARGET_DRIFT");
|
|
112267
112627
|
if (entryExists(item.backupPath)) {
|
|
112268
|
-
|
|
112269
|
-
if (!backup.isSymbolicLink() || readlinkSync6(item.backupPath) !== item.oldLinkTarget || realpathSync17(item.backupPath) !== item.oldTarget)
|
|
112628
|
+
if (!launcherIs(item.backupPath, oldLauncherState(item)))
|
|
112270
112629
|
throw new Error("ALIAS_PREIMAGE_DRIFT");
|
|
112271
112630
|
} else if (current !== item.oldTarget) {
|
|
112272
112631
|
throw new Error("ALIAS_BACKUP_MISSING_FOR_SWITCH");
|
|
@@ -112274,23 +112633,25 @@ function rollbackCopyfileAliases(receiptId, options = {}) {
|
|
|
112274
112633
|
}
|
|
112275
112634
|
let restored = 0;
|
|
112276
112635
|
for (const item of [...receipt.aliases].reverse()) {
|
|
112277
|
-
if (
|
|
112636
|
+
if (launcherIs(item.path, oldLauncherState(item)))
|
|
112278
112637
|
continue;
|
|
112279
112638
|
receipt.state = "rollback-required";
|
|
112280
112639
|
persistAliasReceipt(receiptPath, receipt);
|
|
112281
112640
|
const after2 = `${item.path}.skills-alias-after-${receiptId}`;
|
|
112282
112641
|
if (!entryExists(after2)) {
|
|
112283
|
-
|
|
112284
|
-
|
|
112642
|
+
try {
|
|
112643
|
+
materializeLauncher(after2, newLauncherState(item));
|
|
112644
|
+
} catch {
|
|
112285
112645
|
throw new Error("ALIAS_AFTER_READBACK_MISMATCH");
|
|
112286
|
-
|
|
112646
|
+
}
|
|
112647
|
+
} else if (!launcherIs(after2, newLauncherState(item)))
|
|
112287
112648
|
throw new Error("ALIAS_AFTER_DRIFT");
|
|
112288
|
-
if (
|
|
112649
|
+
if (launcherTarget(item.path) !== item.newTarget)
|
|
112289
112650
|
throw new Error("ALIAS_TARGET_DRIFT");
|
|
112290
112651
|
const temp = `${item.path}.skills-alias-rollback-${randomUUID10()}`;
|
|
112291
|
-
|
|
112652
|
+
materializeLauncher(temp, oldLauncherState(item));
|
|
112292
112653
|
renameSync14(temp, item.path);
|
|
112293
|
-
if (
|
|
112654
|
+
if (!launcherIs(item.path, oldLauncherState(item)))
|
|
112294
112655
|
throw new Error("ALIAS_ROLLBACK_READBACK_MISMATCH");
|
|
112295
112656
|
receipt.rollbackCompletedAliases = [...new Set([...receipt.rollbackCompletedAliases, item.path])];
|
|
112296
112657
|
persistAliasReceipt(receiptPath, receipt);
|
|
@@ -112318,13 +112679,13 @@ async function updateCopyfileRuntime(version2, options = {}) {
|
|
|
112318
112679
|
throw new Error("REVIEWED_LOCK_INPUT_PAIR_REQUIRED");
|
|
112319
112680
|
if (!policy)
|
|
112320
112681
|
throw new Error("REVIEWED_LOCK_RELEASE_AGE_REQUIRED");
|
|
112321
|
-
if (!
|
|
112682
|
+
if (!isAbsolute27(options.reviewedLock))
|
|
112322
112683
|
throw new Error("REVIEWED_LOCK_ABSOLUTE_PATH_REQUIRED");
|
|
112323
112684
|
assertNoSymlinkAncestors(dirname32(options.reviewedLock));
|
|
112324
|
-
const stat3 =
|
|
112685
|
+
const stat3 = lstatSync32(options.reviewedLock);
|
|
112325
112686
|
if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.nlink !== 1 || stat3.uid !== process.getuid?.() || stat3.mode & 63 || stat3.size > 8 * 1024 * 1024)
|
|
112326
112687
|
throw new Error("REVIEWED_LOCK_FILE_UNSAFE");
|
|
112327
|
-
reviewedLockBytes =
|
|
112688
|
+
reviewedLockBytes = readFileSync40(options.reviewedLock);
|
|
112328
112689
|
if (!/^[a-f0-9]{64}$/.test(options.reviewedLockSha256))
|
|
112329
112690
|
throw new Error("REVIEWED_LOCK_SHA256_INVALID");
|
|
112330
112691
|
if (hash5(reviewedLockBytes) !== options.reviewedLockSha256)
|
|
@@ -112342,14 +112703,18 @@ async function updateCopyfileRuntime(version2, options = {}) {
|
|
|
112342
112703
|
throw new Error("REGISTRY_ORIGIN_INVALID");
|
|
112343
112704
|
if (origin.username || origin.password || origin.search || origin.hash)
|
|
112344
112705
|
throw new Error("REGISTRY_ORIGIN_INVALID");
|
|
112345
|
-
const runtimeRootStat =
|
|
112706
|
+
const runtimeRootStat = lstatSync32(layout.runtimeRoot);
|
|
112346
112707
|
if ((runtimeRootStat.mode & 63) !== 0)
|
|
112347
112708
|
throw new Error("RUNTIME_ROOT_NOT_PRIVATE");
|
|
112348
112709
|
const id2 = randomUUID10();
|
|
112349
|
-
const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
|
|
112350
112710
|
const stagePath = join60(layout.runtimeRoot, `.stage-${version2}-${id2}`);
|
|
112351
112711
|
const finalPath = join60(layout.runtimeRoot, `${version2}-copyfile`);
|
|
112352
|
-
const
|
|
112712
|
+
const launcherRuntime = pinnedLauncherRuntime();
|
|
112713
|
+
const launchers = layout.launchers.map((item) => {
|
|
112714
|
+
const newTarget = join60(finalPath, "node_modules", "@hasna", "skills", layout.bin[basename15(item.path)]);
|
|
112715
|
+
return { ...item, newTarget, ...pinnedRecordFields(launcherRuntime, finalPath, newTarget) };
|
|
112716
|
+
});
|
|
112717
|
+
const releaseLock = acquireRuntimeLock(layout.runtimeRoot);
|
|
112353
112718
|
let switched = [];
|
|
112354
112719
|
let moved = false;
|
|
112355
112720
|
try {
|
|
@@ -112372,13 +112737,13 @@ async function updateCopyfileRuntime(version2, options = {}) {
|
|
|
112372
112737
|
await validateReviewedRuntimeLock(reviewedLockBytes, options.reviewedLockSha256, {
|
|
112373
112738
|
version: version2,
|
|
112374
112739
|
archiveIntegrity: artifact.integrity,
|
|
112375
|
-
packageManifest: object10(JSON.parse(
|
|
112740
|
+
packageManifest: object10(JSON.parse(readFileSync40(join60(stagePath, "verified-archive", "package", "package.json"), "utf8")), "PACKAGE_MANIFEST_INVALID"),
|
|
112376
112741
|
registryOrigin: REGISTRY_ORIGIN,
|
|
112377
112742
|
...policy,
|
|
112378
112743
|
fetcher
|
|
112379
112744
|
});
|
|
112380
112745
|
writeFileSync24(join60(stagePackage, "package-lock.json"), reviewedLockBytes, { mode: 384, flag: "wx" });
|
|
112381
|
-
if (!
|
|
112746
|
+
if (!readFileSync40(join60(stagePackage, "package-lock.json")).equals(reviewedLockBytes))
|
|
112382
112747
|
throw new Error("REVIEWED_LOCK_COPY_MISMATCH");
|
|
112383
112748
|
} else {
|
|
112384
112749
|
npmVersion = await runNpm(["install", "--package-lock-only", "--prefix", stagePackage], stagePackage, home, stagePath, policy);
|
|
@@ -112387,14 +112752,14 @@ async function updateCopyfileRuntime(version2, options = {}) {
|
|
|
112387
112752
|
if (!reviewedLockBytes && npmVersion !== ciNpmVersion)
|
|
112388
112753
|
throw new Error("NPM_VERSION_DRIFT_DURING_UPDATE");
|
|
112389
112754
|
npmVersion = ciNpmVersion;
|
|
112390
|
-
const lockBytes =
|
|
112755
|
+
const lockBytes = readFileSync40(join60(stagePackage, "package-lock.json"));
|
|
112391
112756
|
if (reviewedLockBytes) {
|
|
112392
112757
|
if (!lockBytes.equals(reviewedLockBytes))
|
|
112393
112758
|
throw new Error("REVIEWED_LOCK_DRIFT_DURING_INSTALL");
|
|
112394
112759
|
const treeNpmVersion = await runNpm(["sbom", "--sbom-format=cyclonedx", "--package-lock-only=false", "--omit=dev", "--prefix", stagePackage], stagePackage, home, stagePath, policy);
|
|
112395
112760
|
if (treeNpmVersion !== npmVersion)
|
|
112396
112761
|
throw new Error("NPM_VERSION_DRIFT_DURING_UPDATE");
|
|
112397
|
-
if (!
|
|
112762
|
+
if (!readFileSync40(join60(stagePackage, "package-lock.json")).equals(reviewedLockBytes))
|
|
112398
112763
|
throw new Error("REVIEWED_LOCK_DRIFT_DURING_INSTALL");
|
|
112399
112764
|
}
|
|
112400
112765
|
const installedPackage = join60(stagePackage, "node_modules", "@hasna", "skills");
|
|
@@ -112458,17 +112823,17 @@ async function updateCopyfileRuntime(version2, options = {}) {
|
|
|
112458
112823
|
moved = true;
|
|
112459
112824
|
const finalReceiptBytes = Buffer.from(`${JSON.stringify(receipt, null, 2)}
|
|
112460
112825
|
`);
|
|
112461
|
-
if (!
|
|
112826
|
+
if (!readFileSync40(join60(finalPath, "rollout-receipt.json")).equals(finalReceiptBytes))
|
|
112462
112827
|
throw new Error("RECEIPT_MOVE_READBACK_MISMATCH");
|
|
112463
112828
|
assertConfigUnchanged(configPreimages);
|
|
112464
112829
|
for (const item of launchers) {
|
|
112465
|
-
if (
|
|
112830
|
+
if (launcherTarget(item.path) !== item.oldTarget)
|
|
112466
112831
|
throw new Error("LAUNCHER_DRIFT_BEFORE_SWITCH");
|
|
112467
112832
|
receipt.state = "switching";
|
|
112468
112833
|
receipt.switchedLaunchers = [...receipt.switchedLaunchers, item.path];
|
|
112469
112834
|
persistReceipt(join60(finalPath, "rollout-receipt.json"), receipt);
|
|
112470
|
-
|
|
112471
|
-
if (
|
|
112835
|
+
replaceLauncher(item);
|
|
112836
|
+
if (!launcherIs(item.path, newLauncherState(item)) || !launcherIs(item.backupPath, oldLauncherState(item))) {
|
|
112472
112837
|
throw new Error("LAUNCHER_SWITCH_READBACK_MISMATCH");
|
|
112473
112838
|
}
|
|
112474
112839
|
switched.push(item.path);
|
|
@@ -112482,17 +112847,16 @@ async function updateCopyfileRuntime(version2, options = {}) {
|
|
|
112482
112847
|
let rollbackFailed = false;
|
|
112483
112848
|
for (const item of [...launchers].reverse()) {
|
|
112484
112849
|
try {
|
|
112485
|
-
|
|
112486
|
-
if (currentTarget === item.oldTarget && readlinkSync6(item.path) === item.oldLinkTarget)
|
|
112850
|
+
if (launcherIs(item.path, oldLauncherState(item)))
|
|
112487
112851
|
continue;
|
|
112488
|
-
if (
|
|
112852
|
+
if (launcherTarget(item.path) !== item.newTarget)
|
|
112489
112853
|
throw new Error("LAUNCHER_CHANGED_DURING_ROLLBACK");
|
|
112490
112854
|
const temp = `${item.path}.skills-rollback-${id2}`;
|
|
112491
112855
|
const afterPath = `${item.path}.skills-after-${id2}`;
|
|
112492
112856
|
if (entryExists(afterPath))
|
|
112493
112857
|
throw new Error("ROLLBACK_PRESERVATION_PATH_EXISTS");
|
|
112494
|
-
|
|
112495
|
-
|
|
112858
|
+
materializeLauncher(afterPath, newLauncherState(item));
|
|
112859
|
+
materializeLauncher(temp, oldLauncherState(item));
|
|
112496
112860
|
renameSync14(temp, item.path);
|
|
112497
112861
|
} catch {
|
|
112498
112862
|
rollbackFailed = true;
|
|
@@ -112500,7 +112864,7 @@ async function updateCopyfileRuntime(version2, options = {}) {
|
|
|
112500
112864
|
}
|
|
112501
112865
|
try {
|
|
112502
112866
|
const receiptPath = join60(finalPath, "rollout-receipt.json");
|
|
112503
|
-
const receipt = JSON.parse(
|
|
112867
|
+
const receipt = JSON.parse(readFileSync40(receiptPath, "utf8"));
|
|
112504
112868
|
receipt.state = rollbackFailed ? "rollback-required" : "rolled-back";
|
|
112505
112869
|
persistReceipt(receiptPath, receipt);
|
|
112506
112870
|
} catch {
|
|
@@ -112519,9 +112883,9 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
|
|
|
112519
112883
|
const home = resolve26(options.homeDir ?? process.env.HOME ?? "");
|
|
112520
112884
|
if (!home || !existsSync34(home))
|
|
112521
112885
|
throw new Error("HOME_NOT_FOUND");
|
|
112522
|
-
const runtimeRoot = join60(
|
|
112886
|
+
const runtimeRoot = join60(realpathSync18(home), ".hasna", "skills", "runtime");
|
|
112523
112887
|
assertNoSymlinkAncestors(runtimeRoot);
|
|
112524
|
-
const rootStat =
|
|
112888
|
+
const rootStat = lstatSync32(runtimeRoot);
|
|
112525
112889
|
if (!rootStat.isDirectory() || rootStat.isSymbolicLink() || (rootStat.mode & 63) !== 0)
|
|
112526
112890
|
throw new Error("RUNTIME_ROOT_NOT_PRIVATE");
|
|
112527
112891
|
const releaseLock = acquireRuntimeLock(runtimeRoot);
|
|
@@ -112533,7 +112897,7 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
|
|
|
112533
112897
|
if (!existsSync34(receipt2))
|
|
112534
112898
|
return false;
|
|
112535
112899
|
try {
|
|
112536
|
-
return JSON.parse(
|
|
112900
|
+
return JSON.parse(readFileSync40(receipt2, "utf8")).id === receiptId;
|
|
112537
112901
|
} catch {
|
|
112538
112902
|
return false;
|
|
112539
112903
|
}
|
|
@@ -112541,7 +112905,7 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
|
|
|
112541
112905
|
if (matches2.length !== 1)
|
|
112542
112906
|
throw new Error("RECEIPT_NOT_FOUND_OR_AMBIGUOUS");
|
|
112543
112907
|
const receiptPath = join60(runtimeRoot, matches2[0], "rollout-receipt.json");
|
|
112544
|
-
const receipt = object10(JSON.parse(
|
|
112908
|
+
const receipt = object10(JSON.parse(readFileSync40(receiptPath, "utf8")), "RECEIPT_INVALID");
|
|
112545
112909
|
if (receipt.schema !== "skills.copyfile-runtime-receipt.v1" || !["switched", "switching", "rollback-required"].includes(receipt.state) || receipt.runtimeRoot !== runtimeRoot) {
|
|
112546
112910
|
throw new Error("RECEIPT_STATE_INVALID");
|
|
112547
112911
|
}
|
|
@@ -112562,43 +112926,40 @@ function rollbackCopyfileRuntime(receiptId, options = {}) {
|
|
|
112562
112926
|
const seen = new Set;
|
|
112563
112927
|
for (const item of receipt.launchers) {
|
|
112564
112928
|
const bin = oldBins[basename15(item.path)];
|
|
112565
|
-
if (!bin || !
|
|
112929
|
+
if (!bin || !isAbsolute27(item.path) || seen.has(item.path) || item.oldTarget !== join60(receipt.currentPackageRoot, bin) || item.newTarget !== join60(receipt.targetPackageRoot, bin) || !/^.+\.skills-prev-[0-9a-f-]{36}$/.test(item.backupPath) || !item.backupPath.startsWith(`${item.path}.skills-prev-`) || typeof item.oldLinkTarget !== "string" || resolve26(dirname32(item.path), item.oldLinkTarget) !== item.oldTarget)
|
|
112566
112930
|
throw new Error("RECEIPT_LAUNCHER_BINDING_INVALID");
|
|
112567
112931
|
assertNoSymlinkAncestors(dirname32(item.path));
|
|
112932
|
+
assertLauncherRecordShapes(item);
|
|
112568
112933
|
seen.add(item.path);
|
|
112569
|
-
const
|
|
112570
|
-
|
|
112934
|
+
const oldState = oldLauncherState(item), newState = newLauncherState(item);
|
|
112935
|
+
let activeTarget;
|
|
112936
|
+
try {
|
|
112937
|
+
activeTarget = launcherTarget(item.path);
|
|
112938
|
+
} catch {
|
|
112571
112939
|
throw new Error("LAUNCHER_DRIFT_ROLLBACK_REFUSED");
|
|
112572
|
-
|
|
112573
|
-
if (
|
|
112940
|
+
}
|
|
112941
|
+
if (!launcherIs(item.path, newState) && !launcherIs(item.path, oldState))
|
|
112574
112942
|
throw new Error("LAUNCHER_DRIFT_ROLLBACK_REFUSED");
|
|
112575
112943
|
const hasBackup = entryExists(item.backupPath);
|
|
112576
112944
|
if (activeTarget === item.newTarget && !hasBackup)
|
|
112577
112945
|
throw new Error("LAUNCHER_PREIMAGE_DRIFT_ROLLBACK_REFUSED");
|
|
112578
|
-
if (hasBackup)
|
|
112579
|
-
|
|
112580
|
-
if (!backup.isSymbolicLink() || readlinkSync6(item.backupPath) !== item.oldLinkTarget || realpathSync17(item.backupPath) !== item.oldTarget)
|
|
112581
|
-
throw new Error("LAUNCHER_PREIMAGE_DRIFT_ROLLBACK_REFUSED");
|
|
112582
|
-
}
|
|
112946
|
+
if (hasBackup && !launcherIs(item.backupPath, oldState))
|
|
112947
|
+
throw new Error("LAUNCHER_PREIMAGE_DRIFT_ROLLBACK_REFUSED");
|
|
112583
112948
|
const afterPath = `${item.path}.skills-after-${receiptId}`;
|
|
112584
|
-
if (entryExists(afterPath))
|
|
112585
|
-
|
|
112586
|
-
if (!after2.isSymbolicLink() || realpathSync17(afterPath) !== item.newTarget)
|
|
112587
|
-
throw new Error("ROLLBACK_PRESERVATION_DRIFT");
|
|
112588
|
-
}
|
|
112949
|
+
if (entryExists(afterPath) && !launcherIs(afterPath, newState))
|
|
112950
|
+
throw new Error("ROLLBACK_PRESERVATION_DRIFT");
|
|
112589
112951
|
switched.push(item);
|
|
112590
112952
|
}
|
|
112591
112953
|
for (const item of switched.reverse()) {
|
|
112592
|
-
|
|
112593
|
-
if (activeTarget === item.oldTarget && readlinkSync6(item.path) === item.oldLinkTarget)
|
|
112954
|
+
if (launcherIs(item.path, oldLauncherState(item)))
|
|
112594
112955
|
continue;
|
|
112595
112956
|
receipt.state = "rollback-required";
|
|
112596
112957
|
persistReceipt(receiptPath, receipt);
|
|
112597
112958
|
const afterPath = `${item.path}.skills-after-${receiptId}`;
|
|
112598
112959
|
if (!entryExists(afterPath))
|
|
112599
|
-
|
|
112960
|
+
materializeLauncher(afterPath, newLauncherState(item));
|
|
112600
112961
|
const temp = `${item.path}.skills-rollback-${receiptId}-${randomUUID10()}`;
|
|
112601
|
-
|
|
112962
|
+
materializeLauncher(temp, oldLauncherState(item));
|
|
112602
112963
|
renameSync14(temp, item.path);
|
|
112603
112964
|
receipt.rollbackCompletedLaunchers = [...new Set([...receipt.rollbackCompletedLaunchers, item.path])];
|
|
112604
112965
|
persistReceipt(receiptPath, receipt);
|
|
@@ -112614,6 +112975,7 @@ var PACKAGE_NAME = "@hasna/skills", REGISTRY_ORIGIN = "https://registry.npmjs.or
|
|
|
112614
112975
|
var init_runtime_copyfile = __esm(() => {
|
|
112615
112976
|
init_skill_contract();
|
|
112616
112977
|
init_reviewed_runtime_lock();
|
|
112978
|
+
init_runtime_launcher();
|
|
112617
112979
|
STABLE_SEMVER_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
112618
112980
|
MAX_TARBALL_BYTES = 100 * 1024 * 1024;
|
|
112619
112981
|
MAX_TARBALL_EXPANDED_BYTES = 256 * 1024 * 1024;
|
|
@@ -112628,11 +112990,12 @@ var init_runtime_copyfile = __esm(() => {
|
|
|
112628
112990
|
// src/cli/commands/runtime.ts
|
|
112629
112991
|
var exports_runtime = {};
|
|
112630
112992
|
__export(exports_runtime, {
|
|
112993
|
+
selectedSkillsCommand: () => selectedSkillsCommand,
|
|
112631
112994
|
registerRuntime: () => registerRuntime
|
|
112632
112995
|
});
|
|
112633
|
-
import { createHash as
|
|
112634
|
-
import { lstatSync as
|
|
112635
|
-
import { basename as basename16, isAbsolute as
|
|
112996
|
+
import { createHash as createHash36, randomUUID as randomUUID11 } from "crypto";
|
|
112997
|
+
import { lstatSync as lstatSync33, mkdirSync as mkdirSync26, readFileSync as readFileSync41, writeFileSync as writeFileSync25 } from "fs";
|
|
112998
|
+
import { basename as basename16, isAbsolute as isAbsolute28, join as join61 } from "path";
|
|
112636
112999
|
import { createInterface } from "readline";
|
|
112637
113000
|
function registerRuntime(parent) {
|
|
112638
113001
|
parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill; use -- to end Skills options").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--target <target>", "Execution target: local or cloud").option("--secret-bindings <path>", "Reviewed, exact-selection local execution vault bindings (JSON file)").option("--secret-bindings-template", "Print a scoped bindings template without resolving secrets or running the skill", false).option("--input <json>", "Structured cloud execution input").option("--skill-version <version>", "Exact selected skill version").option("--selection-profile <id>", "Selected Skills profile").option("--session <id>", "Pinned Skills session").option("--cached", "Use the explicit verified selected cache", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options, command) => {
|
|
@@ -112671,7 +113034,7 @@ function registerRuntime(parent) {
|
|
|
112671
113034
|
if (!expected)
|
|
112672
113035
|
throw new Error("Cloud artifact not found");
|
|
112673
113036
|
const bytes = await client2.download(id2, name);
|
|
112674
|
-
if (bytes.length !== expected.byteSize ||
|
|
113037
|
+
if (bytes.length !== expected.byteSize || createHash36("sha256").update(bytes).digest("hex") !== expected.sha256)
|
|
112675
113038
|
throw new Error("Cloud artifact integrity verification failed");
|
|
112676
113039
|
writeFileSync25(options.output, bytes, { flag: "wx", mode: 384 });
|
|
112677
113040
|
console.log(JSON.stringify({ path: options.output, sha256: expected.sha256, byteSize: bytes.length }));
|
|
@@ -112831,20 +113194,29 @@ Updating ${name}...
|
|
|
112831
113194
|
async function readUpdatedVersion(bunExecutable) {
|
|
112832
113195
|
const output2 = await readUpdateCommand([bunExecutable, "pm", "bin", "-g"]);
|
|
112833
113196
|
const globalBin = output2.replace(/\r?\n$/, "");
|
|
112834
|
-
if (!globalBin || !
|
|
113197
|
+
if (!globalBin || !isAbsolute28(globalBin) || /[\r\n\0]/.test(globalBin))
|
|
112835
113198
|
throw new Error("Update bin discovery failed");
|
|
112836
113199
|
const installed = Bun.which("skills", { PATH: globalBin, cwd: globalBin });
|
|
112837
113200
|
const selected = Bun.which("skills");
|
|
112838
113201
|
if (!installed || !selected)
|
|
112839
113202
|
throw new Error("Updated command is unavailable");
|
|
112840
|
-
const
|
|
112841
|
-
if (selectedPath !== realpathSync18(installed))
|
|
112842
|
-
throw new Error("Updated command is shadowed on PATH");
|
|
112843
|
-
const version2 = (await readUpdateCommand([selectedPath, "--version"])).trim();
|
|
113203
|
+
const version2 = (await readUpdateCommand([selectedSkillsCommand(selected, installed), "--version"])).trim();
|
|
112844
113204
|
if (!new RegExp(SEMVER_PATTERN).test(version2))
|
|
112845
113205
|
throw new Error("Update version verification failed");
|
|
112846
113206
|
return version2;
|
|
112847
113207
|
}
|
|
113208
|
+
function selectedSkillsCommand(selected, installed) {
|
|
113209
|
+
let chosen, expected;
|
|
113210
|
+
try {
|
|
113211
|
+
chosen = resolveLauncherCommand(selected);
|
|
113212
|
+
expected = resolveLauncherCommand(installed);
|
|
113213
|
+
} catch {
|
|
113214
|
+
throw new Error("Updated command is unavailable");
|
|
113215
|
+
}
|
|
113216
|
+
if (chosen.entry !== expected.entry)
|
|
113217
|
+
throw new Error("Updated command is shadowed on PATH");
|
|
113218
|
+
return chosen.pinned ? chosen.physical : chosen.entry;
|
|
113219
|
+
}
|
|
112848
113220
|
async function readUpdateCommand(command) {
|
|
112849
113221
|
const proc = Bun.spawn(command, { stdout: "pipe" });
|
|
112850
113222
|
try {
|
|
@@ -113153,10 +113525,10 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
|
|
|
113153
113525
|
try {
|
|
113154
113526
|
parsePollingOptions(options);
|
|
113155
113527
|
inputFiles = (options.file ?? []).map((path) => {
|
|
113156
|
-
const info =
|
|
113528
|
+
const info = lstatSync33(path);
|
|
113157
113529
|
if (!info.isFile() || info.size > 20 * 1024 * 1024)
|
|
113158
113530
|
throw new Error("Input must be a regular file no larger than 20 MiB");
|
|
113159
|
-
return { name: basename16(path), bytes: new Uint8Array(
|
|
113531
|
+
return { name: basename16(path), bytes: new Uint8Array(readFileSync41(path)) };
|
|
113160
113532
|
});
|
|
113161
113533
|
describeRemoteFiles(inputFiles);
|
|
113162
113534
|
client2 = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
|
|
@@ -113583,7 +113955,7 @@ function ensureSafeExportParent(root2, relativePath) {
|
|
|
113583
113955
|
if (part)
|
|
113584
113956
|
parent = join61(parent, part);
|
|
113585
113957
|
try {
|
|
113586
|
-
if (!
|
|
113958
|
+
if (!lstatSync33(parent).isDirectory() || lstatSync33(parent).isSymbolicLink())
|
|
113587
113959
|
throw new Error("Unsafe artifact directory");
|
|
113588
113960
|
} catch (error61) {
|
|
113589
113961
|
if (error61.code !== "ENOENT")
|
|
@@ -113793,6 +114165,7 @@ var init_runtime = __esm(() => {
|
|
|
113793
114165
|
init_remote_account2();
|
|
113794
114166
|
init_remote_files();
|
|
113795
114167
|
init_runtime_copyfile();
|
|
114168
|
+
init_runtime_launcher();
|
|
113796
114169
|
});
|
|
113797
114170
|
|
|
113798
114171
|
// src/cli/commands/customer-verification.ts
|
|
@@ -113876,12 +114249,12 @@ var exports_recurring = {};
|
|
|
113876
114249
|
__export(exports_recurring, {
|
|
113877
114250
|
registerRecurringCommands: () => registerRecurringCommands
|
|
113878
114251
|
});
|
|
113879
|
-
import { constants as
|
|
114252
|
+
import { constants as constants22, closeSync as closeSync23, fstatSync as fstatSync23, lstatSync as lstatSync34, openSync as openSync23, readSync as readSync17 } from "fs";
|
|
113880
114253
|
import { createInterface as createInterface2 } from "readline";
|
|
113881
114254
|
function readRequest(path) {
|
|
113882
|
-
const fd =
|
|
114255
|
+
const fd = openSync23(path, constants22.O_RDONLY | constants22.O_NOFOLLOW | constants22.O_NONBLOCK);
|
|
113883
114256
|
try {
|
|
113884
|
-
const before2 =
|
|
114257
|
+
const before2 = fstatSync23(fd);
|
|
113885
114258
|
if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
|
|
113886
114259
|
throw new RecurringInputError;
|
|
113887
114260
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
@@ -113892,14 +114265,14 @@ function readRequest(path) {
|
|
|
113892
114265
|
break;
|
|
113893
114266
|
length += n2;
|
|
113894
114267
|
}
|
|
113895
|
-
const after2 =
|
|
114268
|
+
const after2 = fstatSync23(fd), current = lstatSync34(path);
|
|
113896
114269
|
if (length !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || current.dev !== before2.dev || current.ino !== before2.ino || !current.isFile() || current.isSymbolicLink())
|
|
113897
114270
|
throw new RecurringInputError;
|
|
113898
114271
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
|
|
113899
114272
|
} catch {
|
|
113900
114273
|
throw new RecurringInputError;
|
|
113901
114274
|
} finally {
|
|
113902
|
-
|
|
114275
|
+
closeSync23(fd);
|
|
113903
114276
|
}
|
|
113904
114277
|
}
|
|
113905
114278
|
async function acceptAtTerminal(draft) {
|
|
@@ -114325,22 +114698,22 @@ var init_portable_snapshot_filter = __esm(() => {
|
|
|
114325
114698
|
});
|
|
114326
114699
|
|
|
114327
114700
|
// src/lib/station-snapshot.ts
|
|
114328
|
-
import { createHash as
|
|
114701
|
+
import { createHash as createHash37 } from "crypto";
|
|
114329
114702
|
import {
|
|
114330
114703
|
copyFileSync as copyFileSync2,
|
|
114331
114704
|
mkdirSync as mkdirSync27,
|
|
114332
|
-
readFileSync as
|
|
114705
|
+
readFileSync as readFileSync42,
|
|
114333
114706
|
statSync as statSync21,
|
|
114334
114707
|
writeFileSync as writeFileSync26
|
|
114335
114708
|
} from "fs";
|
|
114336
|
-
import { dirname as dirname34, isAbsolute as
|
|
114709
|
+
import { dirname as dirname34, isAbsolute as isAbsolute29, relative as relative11, resolve as resolve27, sep as sep14 } from "path";
|
|
114337
114710
|
function validateStationId(stationId) {
|
|
114338
114711
|
if (!/^[a-z0-9-]+$/.test(stationId)) {
|
|
114339
114712
|
throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
|
|
114340
114713
|
}
|
|
114341
114714
|
}
|
|
114342
114715
|
function sha256File(filePath) {
|
|
114343
|
-
return
|
|
114716
|
+
return createHash37("sha256").update(readFileSync42(filePath)).digest("hex");
|
|
114344
114717
|
}
|
|
114345
114718
|
function scanHome(definition, homesRoot) {
|
|
114346
114719
|
const homePath = homePathFor(definition, homesRoot);
|
|
@@ -114439,7 +114812,7 @@ function writeStationSnapshot(options) {
|
|
|
114439
114812
|
for (const plan of plans) {
|
|
114440
114813
|
const destination = resolve27(repoRoot, plan.destination);
|
|
114441
114814
|
const destinationRelative = relative11(repoRoot, destination);
|
|
114442
|
-
if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep14) ||
|
|
114815
|
+
if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep14) || isAbsolute29(destinationRelative)) {
|
|
114443
114816
|
throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
|
|
114444
114817
|
}
|
|
114445
114818
|
let existingDigest = null;
|
|
@@ -114959,11 +115332,37 @@ var init_codex_native_config = () => {};
|
|
|
114959
115332
|
|
|
114960
115333
|
// src/lib/codex-hook-trust-identity.ts
|
|
114961
115334
|
import { realpathSync as realpathSync19 } from "fs";
|
|
114962
|
-
import { dirname as dirname35, isAbsolute as
|
|
115335
|
+
import { dirname as dirname35, isAbsolute as isAbsolute30, join as join64 } from "path";
|
|
114963
115336
|
import { isDeepStrictEqual as isDeepStrictEqual15 } from "util";
|
|
115337
|
+
function skillsCommandTarget(command) {
|
|
115338
|
+
const physical = realpathSync19(command);
|
|
115339
|
+
let resolved;
|
|
115340
|
+
try {
|
|
115341
|
+
resolved = resolveLauncherCommand(physical);
|
|
115342
|
+
} catch {
|
|
115343
|
+
need5(false, "SKILLS_LAUNCHER_UNVERIFIED");
|
|
115344
|
+
}
|
|
115345
|
+
if (!resolved.pinned)
|
|
115346
|
+
return { entry: resolved.physical };
|
|
115347
|
+
const launcher = snapshot(resolved.physical, false);
|
|
115348
|
+
need5(launcher.sha256 === resolved.pinned.sha256, "SKILLS_LAUNCHER_UNVERIFIED");
|
|
115349
|
+
try {
|
|
115350
|
+
assertPinnedLauncherRuntimeSafe(resolved.pinned.runtime);
|
|
115351
|
+
} catch {
|
|
115352
|
+
need5(false, "SKILLS_LAUNCHER_UNVERIFIED");
|
|
115353
|
+
}
|
|
115354
|
+
return { entry: resolved.entry, launcher };
|
|
115355
|
+
}
|
|
115356
|
+
function skillsCommandEntry(command) {
|
|
115357
|
+
try {
|
|
115358
|
+
return resolveLauncherCommand(command).entry;
|
|
115359
|
+
} catch {
|
|
115360
|
+
need5(false, "SKILLS_COMMAND_CHANGED");
|
|
115361
|
+
}
|
|
115362
|
+
}
|
|
114964
115363
|
function inspectRecordedSkillsCli(command, expected) {
|
|
114965
|
-
need5(
|
|
114966
|
-
const
|
|
115364
|
+
need5(isAbsolute30(command) && !command.includes("\x00"), "RECONCILE_RECORDED_COMMAND_REQUIRED");
|
|
115365
|
+
const target = skillsCommandTarget(command), resolved = target.entry;
|
|
114967
115366
|
const cli = snapshot(resolved, false, { readOnlyPackage: true });
|
|
114968
115367
|
const manifest = snapshot(join64(dirname35(dirname35(resolved)), "package.json"), false, { readOnlyPackage: true });
|
|
114969
115368
|
const pkg = JSON.parse(manifest.text);
|
|
@@ -114972,7 +115371,9 @@ function inspectRecordedSkillsCli(command, expected) {
|
|
|
114972
115371
|
const receipt = { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 };
|
|
114973
115372
|
need5(isDeepStrictEqual15(receipt, expected), "RECONCILE_SKILLS_BINDING_CHANGED");
|
|
114974
115373
|
return { receipt, recheck() {
|
|
114975
|
-
need5(
|
|
115374
|
+
need5(skillsCommandEntry(command) === resolved, "SKILLS_COMMAND_CHANGED");
|
|
115375
|
+
if (target.launcher)
|
|
115376
|
+
unchanged2(target.launcher);
|
|
114976
115377
|
unchanged2(cli);
|
|
114977
115378
|
unchanged2(manifest);
|
|
114978
115379
|
} };
|
|
@@ -114980,9 +115381,11 @@ function inspectRecordedSkillsCli(command, expected) {
|
|
|
114980
115381
|
function bindSkillsCli(command, reviewed) {
|
|
114981
115382
|
const normal = Bun.which("skills", { PATH: process.env.PATH });
|
|
114982
115383
|
need5(normal, "SKILLS_COMMAND_UNAVAILABLE");
|
|
114983
|
-
const
|
|
114984
|
-
const bound =
|
|
114985
|
-
need5(bound
|
|
115384
|
+
const normalTarget = skillsCommandTarget(normal), resolved = normalTarget.entry;
|
|
115385
|
+
const bound = isAbsolute30(command) ? command : command === "skills" ? normal : undefined;
|
|
115386
|
+
need5(bound, "SKILLS_COMMAND_MISMATCH");
|
|
115387
|
+
const boundTarget = skillsCommandTarget(bound);
|
|
115388
|
+
need5(boundTarget.entry === resolved, "SKILLS_COMMAND_MISMATCH");
|
|
114986
115389
|
const entrypoint = reviewed?.path ?? process.argv[1];
|
|
114987
115390
|
need5(entrypoint && realpathSync19(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
|
|
114988
115391
|
const cli = snapshot(resolved, false, { readOnlyPackage: true });
|
|
@@ -114995,7 +115398,10 @@ function bindSkillsCli(command, reviewed) {
|
|
|
114995
115398
|
return {
|
|
114996
115399
|
receipt: { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 },
|
|
114997
115400
|
recheck() {
|
|
114998
|
-
need5(Bun.which("skills", { PATH: process.env.PATH }) === normal &&
|
|
115401
|
+
need5(Bun.which("skills", { PATH: process.env.PATH }) === normal && skillsCommandEntry(normal) === resolved && skillsCommandEntry(bound) === resolved && realpathSync19(entrypoint) === resolved, "SKILLS_COMMAND_CHANGED");
|
|
115402
|
+
for (const launcher of [normalTarget.launcher, boundTarget.launcher])
|
|
115403
|
+
if (launcher)
|
|
115404
|
+
unchanged2(launcher);
|
|
114999
115405
|
unchanged2(cli);
|
|
115000
115406
|
unchanged2(manifest);
|
|
115001
115407
|
}
|
|
@@ -115003,6 +115409,7 @@ function bindSkillsCli(command, reviewed) {
|
|
|
115003
115409
|
}
|
|
115004
115410
|
var init_codex_hook_trust_identity = __esm(() => {
|
|
115005
115411
|
init_codex_hook_trust_files();
|
|
115412
|
+
init_runtime_launcher();
|
|
115006
115413
|
});
|
|
115007
115414
|
|
|
115008
115415
|
// src/lib/codex-hook-policy-recovery.ts
|
|
@@ -115029,23 +115436,23 @@ var init_codex_hook_policy_recovery = __esm(() => {
|
|
|
115029
115436
|
});
|
|
115030
115437
|
|
|
115031
115438
|
// src/lib/agent-codex-trust.ts
|
|
115032
|
-
import { lstatSync as
|
|
115033
|
-
import { createHash as
|
|
115439
|
+
import { lstatSync as lstatSync35, mkdirSync as mkdirSync28, readdirSync as readdirSync23, readFileSync as readFileSync43, realpathSync as realpathSync20, statSync as statSync22 } from "fs";
|
|
115440
|
+
import { createHash as createHash38, randomUUID as randomUUID12 } from "crypto";
|
|
115034
115441
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
115035
|
-
import { dirname as dirname36, isAbsolute as
|
|
115442
|
+
import { dirname as dirname36, isAbsolute as isAbsolute31, join as join65, resolve as resolve28 } from "path";
|
|
115036
115443
|
import { homedir as homedir12 } from "os";
|
|
115037
115444
|
import { isDeepStrictEqual as isDeepStrictEqual17 } from "util";
|
|
115038
115445
|
function verifyReleaseArtifact(proof, skillsCli) {
|
|
115039
|
-
need5(
|
|
115446
|
+
need5(isAbsolute31(proof.packageTarPath) && !proof.packageTarPath.includes("\x00"), "RECONCILE_RELEASE_PROVENANCE_PATH");
|
|
115040
115447
|
const tarPath = realpathSync20(proof.packageTarPath);
|
|
115041
115448
|
need5(statSync22(tarPath).isFile(), "RECONCILE_RELEASE_PROVENANCE_PATH");
|
|
115042
|
-
const tarBytes =
|
|
115043
|
-
need5(tarBytes.byteLength === proof.packageTarBytes &&
|
|
115449
|
+
const tarBytes = readFileSync43(tarPath);
|
|
115450
|
+
need5(tarBytes.byteLength === proof.packageTarBytes && createHash38("sha256").update(tarBytes).digest("hex") === proof.packageTarSha256, "RECONCILE_RELEASE_ARTIFACT_CHANGED");
|
|
115044
115451
|
const packageRoot = dirname36(dirname36(realpathSync20(skillsCli.receipt.path)));
|
|
115045
|
-
const manifest =
|
|
115046
|
-
need5(
|
|
115047
|
-
need5(
|
|
115048
|
-
const members2 = [["package/package.json", manifest], ["package/bin/index.js",
|
|
115452
|
+
const manifest = readFileSync43(join65(packageRoot, "package.json"));
|
|
115453
|
+
need5(createHash38("sha256").update(manifest).digest("hex") === skillsCli.receipt.manifestSha256 && skillsCli.receipt.manifestSha256 === proof.manifestSha256, "RECONCILE_RELEASE_MANIFEST_CHANGED");
|
|
115454
|
+
need5(createHash38("sha256").update(readFileSync43(skillsCli.receipt.path)).digest("hex") === proof.executableSha256 && skillsCli.receipt.sha256 === proof.executableSha256, "RECONCILE_RELEASE_EXECUTABLE_CHANGED");
|
|
115455
|
+
const members2 = [["package/package.json", manifest], ["package/bin/index.js", readFileSync43(skillsCli.receipt.path)]];
|
|
115049
115456
|
for (const [member, expected] of members2) {
|
|
115050
115457
|
let actual;
|
|
115051
115458
|
try {
|
|
@@ -115062,10 +115469,10 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
|
|
|
115062
115469
|
const home = resolve28(options.home ?? homedir12()), dataDir3 = resolve28(options.dataDir ?? getDataDirReadOnly());
|
|
115063
115470
|
const parent = resolve28(join65(dataDir3, "native-hook-trust")), journal = resolve28(options.journal);
|
|
115064
115471
|
need5(journal.startsWith(parent + "/") && /^[a-f0-9-]{36}$/.test(journal.slice(parent.length + 1)), "RECONCILE_JOURNAL_PATH");
|
|
115065
|
-
const dir =
|
|
115472
|
+
const dir = lstatSync35(journal, { throwIfNoEntry: false });
|
|
115066
115473
|
need5(!!dir && dir.isDirectory() && !dir.isSymbolicLink() && dir.uid === process.getuid() && (dir.mode & 511) === 448, "UNSAFE_JOURNAL");
|
|
115067
|
-
need5(!
|
|
115068
|
-
need5(
|
|
115474
|
+
need5(!lstatSync35(join65(journal, "receipt.json"), { throwIfNoEntry: false }), "RECONCILE_ALREADY_COMPLETE");
|
|
115475
|
+
need5(lstatSync35(join65(journal, "stopped.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_JOURNAL_INCOMPLETE");
|
|
115069
115476
|
const stoppedFile = snapshot(join65(journal, "stopped.json"), true);
|
|
115070
115477
|
const intentFile = snapshot(join65(journal, "intent.json"), true), intent = JSON.parse(intentFile.text);
|
|
115071
115478
|
const configBefore = snapshot(join65(journal, "config.before.toml"), true), hooksBefore = snapshot(join65(journal, "hooks.before.json"), true), policyBefore = snapshot(join65(journal, "policy.before.json"), true);
|
|
@@ -115095,7 +115502,7 @@ async function reconcileCodexNativeHooks(options, connect = connectCodexHookRpc)
|
|
|
115095
115502
|
if (supersededBinding || recovery) {
|
|
115096
115503
|
need5(Array.isArray(intent.nativeHooks) && intent.nativeHooks.length > 0, "RECONCILE_NATIVE_INVENTORY_REQUIRED");
|
|
115097
115504
|
const proof = options.releaseProof;
|
|
115098
|
-
need5(!!proof &&
|
|
115505
|
+
need5(!!proof && isAbsolute31(proof.packageTarPath) && /^[a-f0-9]{64}$/.test(proof.packageTarSha256) && Number.isInteger(proof.packageTarBytes) && proof.packageTarBytes > 0 && /^[a-f0-9]{64}$/.test(proof.manifestSha256) && /^[a-f0-9]{64}$/.test(proof.executableSha256), "RECONCILE_RELEASE_PROVENANCE_REQUIRED");
|
|
115099
115506
|
}
|
|
115100
115507
|
const currentConfig = snapshot(intent.configPath, true);
|
|
115101
115508
|
const policy = parseManagedSkillPolicy(policyCurrent.text), binding = policy.bridge;
|
|
@@ -115240,7 +115647,7 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
|
|
|
115240
115647
|
const binding = policy.bridge, alias = binding.rootAliases?.find((item) => item.agent === "codex");
|
|
115241
115648
|
const skillsCli = bindSkillsCli(binding.commands.codex, options.reviewedSkillsCli);
|
|
115242
115649
|
const physicalRoot = alias?.target ?? join65(home, ".codex"), hooksPath = join65(physicalRoot, "hooks.json"), configPath = join65(physicalRoot, "config.toml");
|
|
115243
|
-
need5(options.codexHome === undefined ||
|
|
115650
|
+
need5(options.codexHome === undefined || isAbsolute31(options.codexHome) && [join65(home, ".codex"), physicalRoot].includes(options.codexHome), "NATIVE_HOME_NOT_ADMITTED");
|
|
115244
115651
|
const codexHome = options.codexHome === undefined ? undefined : physicalRoot;
|
|
115245
115652
|
const nativeConfigPath = join65(codexHome ?? join65(home, ".codex"), "config.toml");
|
|
115246
115653
|
const hooksFile = snapshot(hooksPath), configFile = snapshot(configPath, true), original = structure3(configFile.text);
|
|
@@ -115296,14 +115703,14 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
|
|
|
115296
115703
|
if (options.apply)
|
|
115297
115704
|
need5(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
|
|
115298
115705
|
const parent = join65(dataDir3, "native-hook-trust");
|
|
115299
|
-
const st =
|
|
115706
|
+
const st = lstatSync35(parent, { throwIfNoEntry: false });
|
|
115300
115707
|
if (st) {
|
|
115301
115708
|
need5(st.isDirectory() && !st.isSymbolicLink() && st.uid === process.getuid() && (st.mode & 511) === 448, "UNSAFE_JOURNAL");
|
|
115302
115709
|
const priorJournals = readdirSync23(parent);
|
|
115303
115710
|
need5(priorJournals.length < 1000, "JOURNAL_BOUND");
|
|
115304
115711
|
for (const name of priorJournals) {
|
|
115305
115712
|
need5(/^[a-f0-9-]{36}$/.test(name), "UNSAFE_JOURNAL");
|
|
115306
|
-
need5(
|
|
115713
|
+
need5(lstatSync35(join65(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
|
|
115307
115714
|
}
|
|
115308
115715
|
}
|
|
115309
115716
|
if (!options.apply || !planned.length)
|
|
@@ -115362,7 +115769,7 @@ async function enrollCodexNativeHooksUnlocked(options, connect) {
|
|
|
115362
115769
|
}
|
|
115363
115770
|
}
|
|
115364
115771
|
var json2 = (value) => JSON.stringify(value, null, 2) + `
|
|
115365
|
-
`, structure3 = (text4) => JSON.parse(JSON.stringify(Bun.TOML.parse(text4))), eventNames, makePlanDigest = (value) =>
|
|
115772
|
+
`, structure3 = (text4) => JSON.parse(JSON.stringify(Bun.TOML.parse(text4))), eventNames, makePlanDigest = (value) => createHash38("sha256").update(json2(value)).digest("hex"), safeNativeHook = (hook) => ({ key: hook.key, eventName: hook.eventName, handlerType: hook.handlerType, command: hook.command, matcher: hook.matcher, timeoutSec: hook.timeoutSec, async: hook.async, statusMessage: hook.statusMessage, additionalContextLimit: hook.additionalContextLimit, sourcePath: hook.sourcePath, source: hook.source, pluginId: hook.pluginId, isManaged: hook.isManaged, currentHash: hook.currentHash, enabled: hook.enabled, trustStatus: hook.trustStatus }), withoutCodexCommand = (value) => {
|
|
115366
115773
|
const copy = structuredClone(value);
|
|
115367
115774
|
if (copy?.bridge?.commands && Object.hasOwn(copy.bridge.commands, "codex"))
|
|
115368
115775
|
copy.bridge.commands.codex = "<reviewed-codex-binding>";
|
|
@@ -115386,8 +115793,8 @@ var init_agent_codex_trust = __esm(() => {
|
|
|
115386
115793
|
});
|
|
115387
115794
|
|
|
115388
115795
|
// src/lib/codex-native-trust.ts
|
|
115389
|
-
import { createHash as
|
|
115390
|
-
import { readFileSync as
|
|
115796
|
+
import { createHash as createHash39 } from "crypto";
|
|
115797
|
+
import { readFileSync as readFileSync44 } from "fs";
|
|
115391
115798
|
import { join as join66, resolve as resolve29 } from "path";
|
|
115392
115799
|
function refuse5(detail) {
|
|
115393
115800
|
throw new Error(`NATIVE_SKILL_POLICY_TRUST_REFUSED: ${detail}`);
|
|
@@ -115445,7 +115852,7 @@ function applyCodexNativeTrust(plan, expectedPolicySha256) {
|
|
|
115445
115852
|
const backupPath = result2.backups[0];
|
|
115446
115853
|
if (result2.backups.length !== 1 || typeof backupPath !== "string")
|
|
115447
115854
|
throw new Error("NATIVE_SKILL_POLICY_TRUST_WRITE_UNVERIFIED: the pre-change backup was not recorded");
|
|
115448
|
-
const backupSha256 = sha6(
|
|
115855
|
+
const backupSha256 = sha6(readFileSync44(backupPath));
|
|
115449
115856
|
if (backupSha256 !== plan.policySha256Before)
|
|
115450
115857
|
throw new Error(`NATIVE_SKILL_POLICY_TRUST_WRITE_UNVERIFIED: the backup at ${backupPath} does not read back as the pre-change policy`);
|
|
115451
115858
|
receipt.backup = { path: backupPath, sha256: backupSha256, verified: true };
|
|
@@ -115459,7 +115866,7 @@ function applyCodexNativeTrust(plan, expectedPolicySha256) {
|
|
|
115459
115866
|
receipt.readback = { policySha256: sha6(readback.text), digests, verified: true };
|
|
115460
115867
|
return receipt;
|
|
115461
115868
|
}
|
|
115462
|
-
var CODEX_NATIVE_TRUST_PLAN_SCHEMA = "skills.codex-native-trust-plan/v1", CODEX_NATIVE_TRUST_RECEIPT_SCHEMA = "skills.codex-native-trust-receipt/v1", PLATFORM_KEY2, HEX_DIGEST2, MAX_DIGESTS = 16, sha6 = (data) =>
|
|
115869
|
+
var CODEX_NATIVE_TRUST_PLAN_SCHEMA = "skills.codex-native-trust-plan/v1", CODEX_NATIVE_TRUST_RECEIPT_SCHEMA = "skills.codex-native-trust-receipt/v1", PLATFORM_KEY2, HEX_DIGEST2, MAX_DIGESTS = 16, sha6 = (data) => createHash39("sha256").update(data).digest("hex");
|
|
115463
115870
|
var init_codex_native_trust = __esm(() => {
|
|
115464
115871
|
init_config();
|
|
115465
115872
|
init_managed_policy();
|
|
@@ -115583,15 +115990,43 @@ var init_hook_diagnostics = __esm(() => {
|
|
|
115583
115990
|
]);
|
|
115584
115991
|
});
|
|
115585
115992
|
|
|
115993
|
+
// src/lib/self-spawn.ts
|
|
115994
|
+
import { realpathSync as realpathSync21 } from "fs";
|
|
115995
|
+
import { dirname as dirname37, isAbsolute as isAbsolute32, sep as sep15 } from "path";
|
|
115996
|
+
function selfSpawnRoot(entry) {
|
|
115997
|
+
const index = entry.indexOf(INSTALLED_PACKAGE);
|
|
115998
|
+
const root2 = index > 0 ? entry.slice(0, index) : dirname37(entry);
|
|
115999
|
+
try {
|
|
116000
|
+
return realpathSync21(root2);
|
|
116001
|
+
} catch {
|
|
116002
|
+
return root2;
|
|
116003
|
+
}
|
|
116004
|
+
}
|
|
116005
|
+
function selfSpawnCommand(args2, options = {}) {
|
|
116006
|
+
const runtime = options.runtime ?? process.execPath;
|
|
116007
|
+
const entry = options.entry ?? process.argv[1];
|
|
116008
|
+
if (!runtime || !isAbsolute32(runtime) || !entry || !isAbsolute32(entry))
|
|
116009
|
+
throw new Error("SKILLS_SELF_SPAWN_ENTRY_UNRESOLVED");
|
|
116010
|
+
const root2 = selfSpawnRoot(entry);
|
|
116011
|
+
const env3 = pinnedLauncherEnvironment(options.env ?? process.env);
|
|
116012
|
+
env3[LAUNCH_CWD_VARIABLE] = options.callerCwd ?? process.cwd();
|
|
116013
|
+
return { command: [runtime, ...PINNED_LAUNCHER_BUN_FLAGS, `--cwd=${root2}`, entry, ...args2], cwd: root2, env: env3 };
|
|
116014
|
+
}
|
|
116015
|
+
var INSTALLED_PACKAGE;
|
|
116016
|
+
var init_self_spawn = __esm(() => {
|
|
116017
|
+
init_runtime_launcher();
|
|
116018
|
+
INSTALLED_PACKAGE = `${sep15}node_modules${sep15}@hasna${sep15}skills${sep15}`;
|
|
116019
|
+
});
|
|
116020
|
+
|
|
115586
116021
|
// src/cli/commands/agent-integration.ts
|
|
115587
116022
|
var exports_agent_integration = {};
|
|
115588
116023
|
__export(exports_agent_integration, {
|
|
115589
116024
|
registerAgentIntegration: () => registerAgentIntegration
|
|
115590
116025
|
});
|
|
115591
|
-
import { existsSync as existsSync36, lstatSync as
|
|
115592
|
-
import { createHash as
|
|
116026
|
+
import { existsSync as existsSync36, lstatSync as lstatSync36, readFileSync as readFileSync45, readSync as readSync18, writeFileSync as writeFileSync27 } from "fs";
|
|
116027
|
+
import { createHash as createHash40 } from "crypto";
|
|
115593
116028
|
import { homedir as homedir13 } from "os";
|
|
115594
|
-
import { isAbsolute as
|
|
116029
|
+
import { isAbsolute as isAbsolute33 } from "path";
|
|
115595
116030
|
function pinnedHookProfile(input3, configuredProfile) {
|
|
115596
116031
|
try {
|
|
115597
116032
|
const parsed = parseSkillContextInput(JSON.stringify(input3));
|
|
@@ -115612,10 +116047,11 @@ async function contextForHook(input3, profileId, cached2, deadline) {
|
|
|
115612
116047
|
const remaining = deadline - Date.now();
|
|
115613
116048
|
if (remaining <= 0)
|
|
115614
116049
|
throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "context");
|
|
115615
|
-
const args2 = [
|
|
116050
|
+
const args2 = ["context", "--stdin", "--json", "--selection-profile", profileId];
|
|
115616
116051
|
if (cached2)
|
|
115617
116052
|
args2.push("--cached", "--auto-reconcile-safe");
|
|
115618
|
-
const
|
|
116053
|
+
const self2 = selfSpawnCommand(args2);
|
|
116054
|
+
const child = Bun.spawn(self2.command, { cwd: self2.cwd, stdin: new Blob([JSON.stringify(input3)]), stdout: "pipe", stderr: "pipe", env: { ...self2.env, NO_COLOR: "1" } });
|
|
115619
116055
|
let timedOut = false;
|
|
115620
116056
|
const timer = setTimeout(() => {
|
|
115621
116057
|
timedOut = true;
|
|
@@ -115686,7 +116122,7 @@ function registerAgentIntegration(parent) {
|
|
|
115686
116122
|
});
|
|
115687
116123
|
hook.command("native-catalog").requiredOption("--cwd <path>", "Absolute project directory observed by native Codex skills/list").requiredOption("--output <file>", "New private file for the projected native catalog").option("--codex-command <path>", "Installed Codex executable used by the native client", "codex").option("--json", "Output bounded capture metadata as JSON", false).description("Capture a reviewed Codex native skill catalog for exact hook enrollment").action(async (options) => {
|
|
115688
116124
|
try {
|
|
115689
|
-
if (!
|
|
116125
|
+
if (!isAbsolute33(options.cwd) || !isAbsolute33(options.output))
|
|
115690
116126
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_ABSOLUTE_PATH_REQUIRED");
|
|
115691
116127
|
if (existsSync36(options.output))
|
|
115692
116128
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
|
|
@@ -115705,8 +116141,8 @@ function registerAgentIntegration(parent) {
|
|
|
115705
116141
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_OUTPUT_EXISTS");
|
|
115706
116142
|
throw error61;
|
|
115707
116143
|
}
|
|
115708
|
-
const written =
|
|
115709
|
-
if (!written.isFile() || written.isSymbolicLink() || (written.mode & 63) !== 0 ||
|
|
116144
|
+
const written = lstatSync36(options.output);
|
|
116145
|
+
if (!written.isFile() || written.isSymbolicLink() || (written.mode & 63) !== 0 || readFileSync45(options.output, "utf8") !== bytes)
|
|
115710
116146
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_READBACK_FAILED");
|
|
115711
116147
|
const receipt = {
|
|
115712
116148
|
version: catalog.version,
|
|
@@ -115714,7 +116150,7 @@ function registerAgentIntegration(parent) {
|
|
|
115714
116150
|
skillCount: catalog.skills.length,
|
|
115715
116151
|
output: options.output,
|
|
115716
116152
|
bytes: Buffer.byteLength(bytes),
|
|
115717
|
-
sha256:
|
|
116153
|
+
sha256: createHash40("sha256").update(bytes).digest("hex")
|
|
115718
116154
|
};
|
|
115719
116155
|
await writeCliOutput(options.json ? JSON.stringify(receipt) : `Captured ${receipt.skillCount} native Codex skill(s) in ${receipt.output}.`);
|
|
115720
116156
|
} catch (error61) {
|
|
@@ -115762,8 +116198,8 @@ function registerAgentIntegration(parent) {
|
|
|
115762
116198
|
});
|
|
115763
116199
|
hook.command("install").option("--agent <agent>", `Agent to configure: ${INTEGRATION_AGENTS.join(", ")}, all`, "all").option("--command <path>", "Skills executable used by the hook (preserves existing binding; new agents use skills)").option("--selection-profile <id>", "Selection profile (preserves existing binding; new agents use default)").option("--include-vendor", "Retained for compatibility; vendor system skills are always inventoried and disabled", false).option("--discovery-inputs <file>", "Advanced reviewed active plugin roots and source hashes for unsupported registrations").option("--codex-skill-denials <file>", "Explicit reviewed remote skill denials: array of exact name, path and document sha256; requires fresh catalog and discovery inputs").option("--codex-native-catalog <file>", "Reviewed supported Codex skill and installed-plugin receipt for exact qualified-name disables").option("--reviewed-cache-alias <path>", "Exact skill-containing vendor cache alias reviewed for this hook plan").option("--allow-root-aliases", "Allow home .claude/.codex aliases to existing directories within this home", false).option("--apply", "Apply the plan, preserving prior configuration in private backups", false).option("--json", "Output a receipt as JSON", false).description("Plan or install one Skills CLI bridge plus native prompt hooks").action(async (options) => {
|
|
115764
116200
|
try {
|
|
115765
|
-
const discoveryInputs = options.discoveryInputs ? JSON.parse(
|
|
115766
|
-
const plan = planAgentIntegration({ projectDir: process.cwd(), agents: agents(options.agent), command: options.command, profileId: options.selectionProfile, includeVendor: options.includeVendor, discoveryInputs, allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, codexSkillDenials: options.codexSkillDenials ? JSON.parse(
|
|
116201
|
+
const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync45(options.discoveryInputs, "utf8")) : undefined;
|
|
116202
|
+
const plan = planAgentIntegration({ projectDir: process.cwd(), agents: agents(options.agent), command: options.command, profileId: options.selectionProfile, includeVendor: options.includeVendor, discoveryInputs, allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, codexSkillDenials: options.codexSkillDenials ? JSON.parse(readFileSync45(options.codexSkillDenials, "utf8")) : undefined, codexNativeCatalog: options.codexNativeCatalog ? JSON.parse(readFileSync45(options.codexNativeCatalog, "utf8")) : undefined });
|
|
115767
116203
|
const result2 = options.apply ? applyAgentIntegration(plan) : { changed: [], backups: [] };
|
|
115768
116204
|
const receipt = { codexPluginSkillReview: plan.codexPluginSkillReview, codexPluginSkills: plan.changes.filter((change) => change.path.endsWith("agent-policy.json")).map((change) => JSON.parse(change.after).bridge?.codexPluginSkills ?? []).flat(), applied: options.apply, planned: plan.changes.map((change) => change.path), ...result2, rootAliases: plan.rootAliases ?? [], discovery: plan.discoveryAfter, nativeSkills: plan.nativeSkills.map((entry) => ({ agent: entry.agent, path: entry.path, managed: entry.managed, vendor: entry.vendor, system: entry.system === true, bridge: entry.bridge === true })), requiresNativeRetirement: plan.nativeSkills.some((entry) => !entry.bridge && !entry.system) };
|
|
115769
116205
|
if (options.json)
|
|
@@ -115822,7 +116258,7 @@ function registerAgentIntegration(parent) {
|
|
|
115822
116258
|
try {
|
|
115823
116259
|
if (agents(options.agent).length !== 1)
|
|
115824
116260
|
throw new Error("A hook invocation requires one agent");
|
|
115825
|
-
const inputBytes =
|
|
116261
|
+
const inputBytes = readFileSync45(0), inputText = inputBytes.toString("utf8");
|
|
115826
116262
|
if (inputText.length > 1024 * 1024)
|
|
115827
116263
|
throw new Error("Hook input is too large");
|
|
115828
116264
|
let input3 = JSON.parse(inputText);
|
|
@@ -115835,12 +116271,12 @@ function registerAgentIntegration(parent) {
|
|
|
115835
116271
|
input3.hook_event_name = event;
|
|
115836
116272
|
const projects = [process.cwd()];
|
|
115837
116273
|
if (input3.cwd !== undefined) {
|
|
115838
|
-
if (typeof input3.cwd !== "string" || !
|
|
116274
|
+
if (typeof input3.cwd !== "string" || !isAbsolute33(input3.cwd) || input3.cwd.includes("\x00"))
|
|
115839
116275
|
throw new Error("Invalid native hook working directory");
|
|
115840
116276
|
projects.push(input3.cwd);
|
|
115841
116277
|
}
|
|
115842
116278
|
if (options.agent === "cursor") {
|
|
115843
|
-
if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !
|
|
116279
|
+
if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !isAbsolute33(path) || path.includes("\x00")))
|
|
115844
116280
|
throw new Error("Invalid Cursor workspace roots");
|
|
115845
116281
|
projects.push(...input3.workspace_roots);
|
|
115846
116282
|
input3.cwd ??= input3.workspace_roots[0] ?? process.cwd();
|
|
@@ -115872,7 +116308,8 @@ function registerAgentIntegration(parent) {
|
|
|
115872
116308
|
const remaining = deadline - Date.now() - 2000;
|
|
115873
116309
|
if (remaining <= 0)
|
|
115874
116310
|
throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "sync");
|
|
115875
|
-
const
|
|
116311
|
+
const self2 = selfSpawnCommand(["sync", "--selection-profile", selectionProfile, "--no-station-report", "--json"]);
|
|
116312
|
+
const refresh = Bun.spawn(self2.command, { cwd: self2.cwd, stdin: "ignore", stdout: "pipe", stderr: "pipe", env: { ...self2.env, NO_COLOR: "1" } });
|
|
115876
116313
|
let timedOut = false;
|
|
115877
116314
|
const timer = setTimeout(() => {
|
|
115878
116315
|
timedOut = true;
|
|
@@ -115937,7 +116374,7 @@ function registerAgentIntegration(parent) {
|
|
|
115937
116374
|
try {
|
|
115938
116375
|
if (options.agent && !INTEGRATION_AGENTS.includes(options.agent))
|
|
115939
116376
|
throw new Error(`Unsupported migration agent: ${options.agent}`);
|
|
115940
|
-
const discoveryInputs = options.discoveryInputs ? JSON.parse(
|
|
116377
|
+
const discoveryInputs = options.discoveryInputs ? JSON.parse(readFileSync45(options.discoveryInputs, "utf8")) : undefined;
|
|
115941
116378
|
if (options.targetManifest && (options.includeUnmanaged || options.includeVendor))
|
|
115942
116379
|
throw new Error("--target-manifest cannot be combined with broad native migration selectors");
|
|
115943
116380
|
const targetManifest = options.targetManifest ? readNativeMigrationTargetManifest(options.targetManifest) : undefined;
|
|
@@ -115974,6 +116411,7 @@ var init_agent_integration2 = __esm(() => {
|
|
|
115974
116411
|
init_codex_settings_witness();
|
|
115975
116412
|
init_claude_marketplace_registry();
|
|
115976
116413
|
init_codex_native_skill_catalog();
|
|
116414
|
+
init_self_spawn();
|
|
115977
116415
|
RECOVERABLE_CONTEXT_CACHE_ERRORS = new Set(["CACHED_PROFILE_EXPIRED", "CACHED_PROFILE_MISSING", "CACHED_BUNDLE_MISSING"]);
|
|
115978
116416
|
});
|
|
115979
116417
|
|
|
@@ -116112,11 +116550,11 @@ var exports_profiles = {};
|
|
|
116112
116550
|
__export(exports_profiles, {
|
|
116113
116551
|
registerProfiles: () => registerProfiles
|
|
116114
116552
|
});
|
|
116115
|
-
import { closeSync as
|
|
116553
|
+
import { closeSync as closeSync25, constants as constants23, fstatSync as fstatSync25, openSync as openSync25, readSync as readSync19, writeFileSync as writeFileSync28 } from "fs";
|
|
116116
116554
|
function readProfileInput(path) {
|
|
116117
|
-
const fd =
|
|
116555
|
+
const fd = openSync25(path, constants23.O_RDONLY | constants23.O_NONBLOCK);
|
|
116118
116556
|
try {
|
|
116119
|
-
const stat3 =
|
|
116557
|
+
const stat3 = fstatSync25(fd);
|
|
116120
116558
|
if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
|
|
116121
116559
|
throw new Error("Profile input exceeds the size limit or is not a regular file");
|
|
116122
116560
|
const bytes = Buffer.alloc(MAX_PROFILE_DOCUMENT_BYTES + 1);
|
|
@@ -116131,7 +116569,7 @@ function readProfileInput(path) {
|
|
|
116131
116569
|
throw new Error("Profile input exceeds the size limit");
|
|
116132
116570
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
|
|
116133
116571
|
} finally {
|
|
116134
|
-
|
|
116572
|
+
closeSync25(fd);
|
|
116135
116573
|
}
|
|
116136
116574
|
}
|
|
116137
116575
|
function registerProfiles(parent) {
|
|
@@ -116182,17 +116620,17 @@ __export(exports_grants, {
|
|
|
116182
116620
|
registerGrants: () => registerGrants
|
|
116183
116621
|
});
|
|
116184
116622
|
import {
|
|
116185
|
-
constants as
|
|
116186
|
-
closeSync as
|
|
116187
|
-
fstatSync as
|
|
116188
|
-
openSync as
|
|
116623
|
+
constants as constants24,
|
|
116624
|
+
closeSync as closeSync26,
|
|
116625
|
+
fstatSync as fstatSync26,
|
|
116626
|
+
openSync as openSync26,
|
|
116189
116627
|
readSync as readSync20,
|
|
116190
116628
|
writeFileSync as writeFileSync29
|
|
116191
116629
|
} from "fs";
|
|
116192
116630
|
function readInput(path) {
|
|
116193
|
-
const fd =
|
|
116631
|
+
const fd = openSync26(path, constants24.O_RDONLY | constants24.O_NONBLOCK);
|
|
116194
116632
|
try {
|
|
116195
|
-
const stat3 =
|
|
116633
|
+
const stat3 = fstatSync26(fd);
|
|
116196
116634
|
if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
|
|
116197
116635
|
throw new Error("Grant input must be a regular file within the policy size limit.");
|
|
116198
116636
|
const bytes = Buffer.alloc(MAX_EXECUTION_GRANT_BYTES + 1);
|
|
@@ -116211,7 +116649,7 @@ function readInput(path) {
|
|
|
116211
116649
|
throw new Error("Grant input must be a JSON document containing a grants array.");
|
|
116212
116650
|
}
|
|
116213
116651
|
} finally {
|
|
116214
|
-
|
|
116652
|
+
closeSync26(fd);
|
|
116215
116653
|
}
|
|
116216
116654
|
}
|
|
116217
116655
|
function registerGrants(parent) {
|
|
@@ -116247,16 +116685,16 @@ var init_grants = __esm(() => {
|
|
|
116247
116685
|
});
|
|
116248
116686
|
|
|
116249
116687
|
// src/lib/station-hydrate.ts
|
|
116250
|
-
import { createHash as
|
|
116688
|
+
import { createHash as createHash41 } from "crypto";
|
|
116251
116689
|
import {
|
|
116252
116690
|
copyFileSync as copyFileSync3,
|
|
116253
116691
|
mkdirSync as mkdirSync29,
|
|
116254
116692
|
readdirSync as readdirSync24,
|
|
116255
|
-
readFileSync as
|
|
116693
|
+
readFileSync as readFileSync46,
|
|
116256
116694
|
statSync as statSync23,
|
|
116257
116695
|
writeFileSync as writeFileSync30
|
|
116258
116696
|
} from "fs";
|
|
116259
|
-
import { dirname as
|
|
116697
|
+
import { dirname as dirname38, join as join67, resolve as resolve30, sep as sep16 } from "path";
|
|
116260
116698
|
function fail6(code2, message, detail = []) {
|
|
116261
116699
|
throw new StationSnapshotError(code2, message, detail);
|
|
116262
116700
|
}
|
|
@@ -116268,7 +116706,7 @@ function readSnapshotManifest(repoRoot, stationId) {
|
|
|
116268
116706
|
const manifestPath = join67(snapshotRoot, "sync-manifest.json");
|
|
116269
116707
|
let manifest;
|
|
116270
116708
|
try {
|
|
116271
|
-
manifest = JSON.parse(
|
|
116709
|
+
manifest = JSON.parse(readFileSync46(manifestPath, "utf8"));
|
|
116272
116710
|
} catch (error61) {
|
|
116273
116711
|
fail6("MANIFEST_UNREADABLE", `cannot read snapshot manifest: ${manifestPath}: ${error61.message}`);
|
|
116274
116712
|
}
|
|
@@ -116306,7 +116744,7 @@ function planStationHydration(stationId, repoRoot) {
|
|
|
116306
116744
|
const identRoot = join67(agentRoot, identEntry.name);
|
|
116307
116745
|
const entries = walkEntries(identRoot);
|
|
116308
116746
|
for (const entry of entries) {
|
|
116309
|
-
const relativeParts = [identEntry.name, ...entry.relativePath.split(
|
|
116747
|
+
const relativeParts = [identEntry.name, ...entry.relativePath.split(sep16)];
|
|
116310
116748
|
if (entry.kind === "symlink") {
|
|
116311
116749
|
symlinks.push({ ident: identEntry.name, agent, relativePath: entry.relativePath });
|
|
116312
116750
|
continue;
|
|
@@ -116330,8 +116768,8 @@ function planStationHydration(stationId, repoRoot) {
|
|
|
116330
116768
|
});
|
|
116331
116769
|
continue;
|
|
116332
116770
|
}
|
|
116333
|
-
const withinIdent = relativeParts.slice(1).join(
|
|
116334
|
-
const homeRelative = relativeParts.join(
|
|
116771
|
+
const withinIdent = relativeParts.slice(1).join(sep16);
|
|
116772
|
+
const homeRelative = relativeParts.join(sep16);
|
|
116335
116773
|
if (REFUSED_SCANNER_FLAGGED.has(homeRelative)) {
|
|
116336
116774
|
skippedByRule.push({
|
|
116337
116775
|
ident: identEntry.name,
|
|
@@ -116404,7 +116842,7 @@ function planStationHydration(stationId, repoRoot) {
|
|
|
116404
116842
|
for (const copy of copies) {
|
|
116405
116843
|
let isStub = false;
|
|
116406
116844
|
try {
|
|
116407
|
-
isStub = isPointerSkillMd(
|
|
116845
|
+
isStub = isPointerSkillMd(readFileSync46(copy.fullPath, "utf8"));
|
|
116408
116846
|
} catch {
|
|
116409
116847
|
isStub = false;
|
|
116410
116848
|
}
|
|
@@ -116450,7 +116888,7 @@ function skillSha256(skill) {
|
|
|
116450
116888
|
return sha256File(skill.files[0].winner.fullPath);
|
|
116451
116889
|
}
|
|
116452
116890
|
const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
|
|
116453
|
-
return
|
|
116891
|
+
return createHash41("sha256").update(joined.sort().join(`
|
|
116454
116892
|
`)).digest("hex");
|
|
116455
116893
|
}
|
|
116456
116894
|
function writeStationHydration(options) {
|
|
@@ -116509,7 +116947,7 @@ function writeStationHydration(options) {
|
|
|
116509
116947
|
}
|
|
116510
116948
|
let written = 0;
|
|
116511
116949
|
for (const entry of toWrite) {
|
|
116512
|
-
mkdirSync29(
|
|
116950
|
+
mkdirSync29(dirname38(entry.destination), { recursive: true });
|
|
116513
116951
|
copyFileSync3(entry.fullPath, entry.destination);
|
|
116514
116952
|
written += 1;
|
|
116515
116953
|
}
|
|
@@ -116530,8 +116968,8 @@ function writeStationHydration(options) {
|
|
|
116530
116968
|
},
|
|
116531
116969
|
skills: resultSkills
|
|
116532
116970
|
};
|
|
116533
|
-
const hydrationManifestPath = join67(
|
|
116534
|
-
mkdirSync29(
|
|
116971
|
+
const hydrationManifestPath = join67(dirname38(cacheRoot), `hydration-${options.stationId}.json`);
|
|
116972
|
+
mkdirSync29(dirname38(hydrationManifestPath), { recursive: true });
|
|
116535
116973
|
writeFileSync30(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
|
|
116536
116974
|
`);
|
|
116537
116975
|
return {
|
|
@@ -116607,10 +117045,10 @@ var init_hydrate = __esm(() => {
|
|
|
116607
117045
|
});
|
|
116608
117046
|
|
|
116609
117047
|
// src/lib/prepare-skill.ts
|
|
116610
|
-
import { createHash as
|
|
116611
|
-
import { chmodSync as chmodSync5, existsSync as existsSync37, lstatSync as
|
|
117048
|
+
import { createHash as createHash42, randomUUID as randomUUID13 } from "crypto";
|
|
117049
|
+
import { chmodSync as chmodSync5, existsSync as existsSync37, lstatSync as lstatSync37, mkdirSync as mkdirSync30, mkdtempSync as mkdtempSync6, readFileSync as readFileSync47, readdirSync as readdirSync25, renameSync as renameSync15, rmSync as rmSync9, writeFileSync as writeFileSync31 } from "fs";
|
|
116612
117050
|
import { tmpdir as tmpdir2 } from "os";
|
|
116613
|
-
import { dirname as
|
|
117051
|
+
import { dirname as dirname39, isAbsolute as isAbsolute34, join as join68, relative as relative12, resolve as resolve31, sep as sep17 } from "path";
|
|
116614
117052
|
function prepareSkill(name, options) {
|
|
116615
117053
|
const normalized = normalizePortableSkillName(name);
|
|
116616
117054
|
if (!new RegExp(SEMVER_PATTERN).test(options.version))
|
|
@@ -116656,7 +117094,7 @@ function prepareSkill(name, options) {
|
|
|
116656
117094
|
mkdirSync30(join68(staging, directory2), { recursive: true });
|
|
116657
117095
|
for (const file2 of before2.files) {
|
|
116658
117096
|
const destination = join68(staging, file2.path);
|
|
116659
|
-
mkdirSync30(
|
|
117097
|
+
mkdirSync30(dirname39(destination), { recursive: true });
|
|
116660
117098
|
writeFileSync31(destination, file2.bytes, { mode: file2.mode });
|
|
116661
117099
|
}
|
|
116662
117100
|
const stagedManifest = join68(staging, "skill.json");
|
|
@@ -116717,7 +117155,7 @@ function validateRuntimeEntrypoint(candidate2, root2) {
|
|
|
116717
117155
|
if (typeof entry !== "string")
|
|
116718
117156
|
return;
|
|
116719
117157
|
const target = resolve31(root2, entry), rel = relative12(root2, target);
|
|
116720
|
-
if (
|
|
117158
|
+
if (isAbsolute34(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep17}`) || isAbsolute34(rel) || !existsSync37(target) || !lstatSync37(target).isFile()) {
|
|
116721
117159
|
throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
|
|
116722
117160
|
}
|
|
116723
117161
|
}
|
|
@@ -116802,11 +117240,11 @@ function compareVersions(left, right) {
|
|
|
116802
117240
|
return 0;
|
|
116803
117241
|
}
|
|
116804
117242
|
function snapshot2(root2) {
|
|
116805
|
-
const rootStat =
|
|
117243
|
+
const rootStat = lstatSync37(root2);
|
|
116806
117244
|
if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
|
|
116807
117245
|
throw new Error("Skill root must be a real directory, not a symlink.");
|
|
116808
117246
|
const files = [], directories = [];
|
|
116809
|
-
const hash6 =
|
|
117247
|
+
const hash6 = createHash42("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
|
|
116810
117248
|
let count = 0, bytes = 0;
|
|
116811
117249
|
const walk2 = (relative13) => {
|
|
116812
117250
|
for (const name of readdirSync25(join68(root2, relative13)).sort()) {
|
|
@@ -116815,7 +117253,7 @@ function snapshot2(root2) {
|
|
|
116815
117253
|
const path = relative13 ? `${relative13}/${name}` : name;
|
|
116816
117254
|
if (++count > 20000)
|
|
116817
117255
|
throw new Error("Skill exceeds the preparation entry limit (20000).");
|
|
116818
|
-
const absolute = join68(root2, path), stat3 =
|
|
117256
|
+
const absolute = join68(root2, path), stat3 = lstatSync37(absolute);
|
|
116819
117257
|
if (stat3.isSymbolicLink())
|
|
116820
117258
|
throw new Error(`Skill contains a symlink: ${path}. No files were changed.`);
|
|
116821
117259
|
if (stat3.isDirectory() && name === "node_modules")
|
|
@@ -116828,7 +117266,7 @@ function snapshot2(root2) {
|
|
|
116828
117266
|
bytes += stat3.size;
|
|
116829
117267
|
if (bytes > 50000000)
|
|
116830
117268
|
throw new Error("Skill exceeds the preparation size limit (50000000 bytes).");
|
|
116831
|
-
const content =
|
|
117269
|
+
const content = readFileSync47(absolute);
|
|
116832
117270
|
if (content.length !== stat3.size)
|
|
116833
117271
|
throw new Error("Skill changed during preparation.");
|
|
116834
117272
|
files.push({ path, bytes: content, mode: stat3.mode & 511 });
|
|
@@ -117231,7 +117669,7 @@ var init_schedule = __esm(() => {
|
|
|
117231
117669
|
|
|
117232
117670
|
// src/lib/registry-sync.ts
|
|
117233
117671
|
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync32 } from "fs";
|
|
117234
|
-
import { dirname as
|
|
117672
|
+
import { dirname as dirname40, relative as relative13 } from "path";
|
|
117235
117673
|
function createRegistrySyncArtifact(options = {}) {
|
|
117236
117674
|
const profile = options.profile ?? "all";
|
|
117237
117675
|
const includeDocs = options.includeDocs ?? true;
|
|
@@ -117288,7 +117726,7 @@ function createRegistrySyncArtifact(options = {}) {
|
|
|
117288
117726
|
};
|
|
117289
117727
|
}
|
|
117290
117728
|
function writeRegistrySyncArtifact(path, artifact) {
|
|
117291
|
-
mkdirSync31(
|
|
117729
|
+
mkdirSync31(dirname40(path), { recursive: true });
|
|
117292
117730
|
writeFileSync32(path, `${JSON.stringify(artifact, null, 2)}
|
|
117293
117731
|
`);
|
|
117294
117732
|
}
|
|
@@ -117308,8 +117746,8 @@ var init_registry_sync = __esm(() => {
|
|
|
117308
117746
|
});
|
|
117309
117747
|
|
|
117310
117748
|
// src/lib/review-export.ts
|
|
117311
|
-
import { constants as
|
|
117312
|
-
import { basename as basename17, dirname as
|
|
117749
|
+
import { constants as constants25, closeSync as closeSync27, existsSync as existsSync38, fstatSync as fstatSync27, fsyncSync as fsyncSync9, lstatSync as lstatSync38, openSync as openSync27, realpathSync as realpathSync22, statSync as statSync24, writeFileSync as writeFileSync33 } from "fs";
|
|
117750
|
+
import { basename as basename17, dirname as dirname41, isAbsolute as isAbsolute35, join as join69, parse as parse13, resolve as resolve32, sep as sep18 } from "path";
|
|
117313
117751
|
function exactVersion(spec) {
|
|
117314
117752
|
const at2 = spec.indexOf("@");
|
|
117315
117753
|
const slug2 = spec.slice(0, at2);
|
|
@@ -117320,22 +117758,22 @@ function exactVersion(spec) {
|
|
|
117320
117758
|
return { slug: slug2, version: version2 };
|
|
117321
117759
|
}
|
|
117322
117760
|
function assertPrivateDestination(output2) {
|
|
117323
|
-
if (!
|
|
117761
|
+
if (!isAbsolute35(output2) || resolve32(output2) !== output2 || !basename17(output2).endsWith(".tar.gz")) {
|
|
117324
117762
|
throw new Error("Review output must be an absolute, normalized .tar.gz path.");
|
|
117325
117763
|
}
|
|
117326
|
-
const parent =
|
|
117327
|
-
if (
|
|
117764
|
+
const parent = dirname41(output2);
|
|
117765
|
+
if (realpathSync22(parent) !== parent || lstatSync38(parent).isSymbolicLink()) {
|
|
117328
117766
|
throw new Error("Review output parent must be a real directory, not a symlink.");
|
|
117329
117767
|
}
|
|
117330
117768
|
const parentStat = statSync24(parent);
|
|
117331
117769
|
if (!parentStat.isDirectory() || (parentStat.mode & 63) !== 0 || process.getuid && parentStat.uid !== process.getuid()) {
|
|
117332
117770
|
throw new Error("Review output parent must be an owner-only directory (mode 0700).");
|
|
117333
117771
|
}
|
|
117334
|
-
const segments = parent.toLowerCase().split(
|
|
117772
|
+
const segments = parent.toLowerCase().split(sep18);
|
|
117335
117773
|
if (segments.some((segment) => NATIVE_CONTAINERS.has(segment)) || segments.some((segment, index) => segment === ".config" && segments[index + 1] === "opencode") || segments.some((segment, index) => segment === ".hasna" && segments[index + 1] === "skills")) {
|
|
117336
117774
|
throw new Error("Review output cannot be placed in agent-native discovery or Skills installation paths.");
|
|
117337
117775
|
}
|
|
117338
|
-
for (let current = parent;; current =
|
|
117776
|
+
for (let current = parent;; current = dirname41(current)) {
|
|
117339
117777
|
if (existsSync38(join69(current, ".git"))) {
|
|
117340
117778
|
throw new Error("Review output cannot be placed inside a Git worktree.");
|
|
117341
117779
|
}
|
|
@@ -117372,16 +117810,16 @@ async function exportSkillVersionForReview(spec, output2, client2) {
|
|
|
117372
117810
|
if (bytes.byteLength !== metadata2.bundleByteSize || sha256Hex(bytes) !== metadata2.bundleSha256.toLowerCase()) {
|
|
117373
117811
|
throw new Error("Published bundle bytes do not match the exact version metadata.");
|
|
117374
117812
|
}
|
|
117375
|
-
const fd =
|
|
117813
|
+
const fd = openSync27(target, constants25.O_WRONLY | constants25.O_CREAT | constants25.O_EXCL | constants25.O_NOFOLLOW, 384);
|
|
117376
117814
|
try {
|
|
117377
117815
|
writeFileSync33(fd, bytes);
|
|
117378
|
-
|
|
117379
|
-
if (
|
|
117816
|
+
fsyncSync9(fd);
|
|
117817
|
+
if (fstatSync27(fd).size !== bytes.byteLength)
|
|
117380
117818
|
throw new Error("Incomplete review output write.");
|
|
117381
117819
|
} catch (error61) {
|
|
117382
117820
|
throw new Error(`Review output write failed. A private partial file may remain at ${target}; use Trash to remove it before reusing this path.`, { cause: error61 });
|
|
117383
117821
|
} finally {
|
|
117384
|
-
|
|
117822
|
+
closeSync27(fd);
|
|
117385
117823
|
}
|
|
117386
117824
|
return { slug: slug2, version: version2, bundleSha256: metadata2.bundleSha256.toLowerCase(), bundleByteSize: bytes.byteLength, output: target };
|
|
117387
117825
|
}
|
|
@@ -117621,7 +118059,7 @@ __export(exports_publish, {
|
|
|
117621
118059
|
PushSkillError: () => PushSkillError
|
|
117622
118060
|
});
|
|
117623
118061
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
117624
|
-
import { existsSync as existsSync39, readFileSync as
|
|
118062
|
+
import { existsSync as existsSync39, readFileSync as readFileSync48 } from "fs";
|
|
117625
118063
|
import { hostname as hostname5 } from "os";
|
|
117626
118064
|
import { join as join70 } from "path";
|
|
117627
118065
|
function registerPublish(parent) {
|
|
@@ -117676,7 +118114,7 @@ async function pushSkill(name, options = {}) {
|
|
|
117676
118114
|
await verifyPackedCanonicalHash(skill.name, packed);
|
|
117677
118115
|
const versionManifest = buildVersionManifest(skill.path, packed);
|
|
117678
118116
|
const skillMdPath = join70(skill.path, "SKILL.md");
|
|
117679
|
-
const skillMd = existsSync39(skillMdPath) ?
|
|
118117
|
+
const skillMd = existsSync39(skillMdPath) ? readFileSync48(skillMdPath, "utf-8") : undefined;
|
|
117680
118118
|
const base3 = {
|
|
117681
118119
|
slug: skill.name,
|
|
117682
118120
|
path: skill.path,
|
|
@@ -119405,7 +119843,7 @@ var init_storage2 = __esm(() => {
|
|
|
119405
119843
|
});
|
|
119406
119844
|
|
|
119407
119845
|
// src/lib/registry-reconcile.ts
|
|
119408
|
-
import { existsSync as existsSync40, readFileSync as
|
|
119846
|
+
import { existsSync as existsSync40, readFileSync as readFileSync49, statSync as statSync25, writeFileSync as writeFileSync34 } from "fs";
|
|
119409
119847
|
import { join as join71 } from "path";
|
|
119410
119848
|
function isDirectory2(path) {
|
|
119411
119849
|
try {
|
|
@@ -119425,7 +119863,7 @@ function readBaseline(skillDir) {
|
|
|
119425
119863
|
if (!existsSync40(markerPath))
|
|
119426
119864
|
return;
|
|
119427
119865
|
try {
|
|
119428
|
-
const marker = JSON.parse(
|
|
119866
|
+
const marker = JSON.parse(readFileSync49(markerPath, "utf-8"));
|
|
119429
119867
|
if (!isSkillsOwnershipMarker(marker))
|
|
119430
119868
|
return;
|
|
119431
119869
|
return {
|
|
@@ -119441,7 +119879,7 @@ function readCursor(root2) {
|
|
|
119441
119879
|
if (!existsSync40(path))
|
|
119442
119880
|
return { runCount: 0 };
|
|
119443
119881
|
try {
|
|
119444
|
-
const cursor2 = JSON.parse(
|
|
119882
|
+
const cursor2 = JSON.parse(readFileSync49(path, "utf-8"));
|
|
119445
119883
|
return { runCount: typeof cursor2.runCount === "number" ? cursor2.runCount : 0 };
|
|
119446
119884
|
} catch {
|
|
119447
119885
|
return { runCount: 0 };
|
|
@@ -119845,6 +120283,10 @@ var init_registry_reconcile2 = __esm(() => {
|
|
|
119845
120283
|
init_selection_cache();
|
|
119846
120284
|
init_registry_reconcile();
|
|
119847
120285
|
});
|
|
120286
|
+
|
|
120287
|
+
// src/cli/index.tsx
|
|
120288
|
+
init_launch_cwd_apply();
|
|
120289
|
+
|
|
119848
120290
|
// node_modules/ink/build/render.js
|
|
119849
120291
|
import { Stream } from "stream";
|
|
119850
120292
|
import process12 from "process";
|