@hasna/skills 0.10.20 → 0.10.22
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 +39 -8
- package/bin/index.js +603 -349
- package/bin/mcp.js +308 -119
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +417 -172
- package/dist/lib/agent-discovery.d.ts +4 -1
- package/dist/lib/agent-integration.d.ts +4 -0
- package/dist/lib/codex-hook-rpc.d.ts +1 -1
- package/dist/lib/codex-native-compatibility.d.ts +3 -0
- package/dist/lib/codex-native-skill-catalog.d.ts +4 -0
- package/dist/lib/codex-plugin-skill-controls.d.ts +1 -0
- package/dist/lib/codex-settings-witness-v1.d.ts +12 -0
- package/dist/lib/codex-settings-witness.d.ts +13 -5
- package/dist/sdk/index.js +488 -244
- package/package.json +1 -1
package/dist/sdk/index.js
CHANGED
|
@@ -9004,7 +9004,7 @@ var require_client = __commonJS((exports) => {
|
|
|
9004
9004
|
var require_config = __commonJS((exports) => {
|
|
9005
9005
|
var { homedir: homedir7 } = __require("os");
|
|
9006
9006
|
var { sep: sep9, join: join4 } = __require("path");
|
|
9007
|
-
var { createHash:
|
|
9007
|
+
var { createHash: createHash21 } = __require("crypto");
|
|
9008
9008
|
var { readFile: readFile$1 } = __require("fs/promises");
|
|
9009
9009
|
var { IniSectionType } = require_dist_cjs();
|
|
9010
9010
|
var { normalizeProvider } = require_client();
|
|
@@ -9159,7 +9159,7 @@ var require_config = __commonJS((exports) => {
|
|
|
9159
9159
|
var DEFAULT_PROFILE = "default";
|
|
9160
9160
|
var getProfileName = (init) => init.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE;
|
|
9161
9161
|
var getSSOTokenFilepath = (id2) => {
|
|
9162
|
-
const hasher =
|
|
9162
|
+
const hasher = createHash21("sha1");
|
|
9163
9163
|
const cacheName = hasher.update(id2).digest("hex");
|
|
9164
9164
|
return join4(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
|
|
9165
9165
|
};
|
|
@@ -10511,7 +10511,7 @@ var require_endpoints = __commonJS((exports) => {
|
|
|
10511
10511
|
|
|
10512
10512
|
// node_modules/@smithy/core/dist-cjs/submodules/serde/index.js
|
|
10513
10513
|
var require_serde = __commonJS((exports) => {
|
|
10514
|
-
var { createHmac: createHmac2, createHash:
|
|
10514
|
+
var { createHmac: createHmac2, createHash: createHash21, getRandomValues } = __require("crypto");
|
|
10515
10515
|
var { hasOwn: hasOwn2, HttpResponse } = require_transport();
|
|
10516
10516
|
exports.hasOwn = hasOwn2;
|
|
10517
10517
|
var { ReadStream, lstatSync: lstatSync23, fstatSync: fstatSync4 } = __require("fs");
|
|
@@ -11416,7 +11416,7 @@ var require_serde = __commonJS((exports) => {
|
|
|
11416
11416
|
return Promise.resolve(this.hash.digest());
|
|
11417
11417
|
}
|
|
11418
11418
|
reset() {
|
|
11419
|
-
this.hash = this.secret ? createHmac2(this.algorithmIdentifier, castSourceData(this.secret)) :
|
|
11419
|
+
this.hash = this.secret ? createHmac2(this.algorithmIdentifier, castSourceData(this.secret)) : createHash21(this.algorithmIdentifier);
|
|
11420
11420
|
}
|
|
11421
11421
|
}
|
|
11422
11422
|
function castSourceData(toCast, encoding) {
|
|
@@ -12155,7 +12155,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12155
12155
|
var { createReadStream } = __require("fs");
|
|
12156
12156
|
var { Writable } = __require("stream");
|
|
12157
12157
|
var { toUint8Array, concatBytes } = require_serde();
|
|
12158
|
-
var { createHash:
|
|
12158
|
+
var { createHash: createHash21, createHmac: createHmac2 } = __require("crypto");
|
|
12159
12159
|
var zlib = __require("zlib");
|
|
12160
12160
|
async function blobReader(blob, onChunk, chunkSize = 1024 * 1024) {
|
|
12161
12161
|
const size = blob.size;
|
|
@@ -12320,7 +12320,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12320
12320
|
}
|
|
12321
12321
|
var hasNativeCrypto$1 = (() => {
|
|
12322
12322
|
try {
|
|
12323
|
-
|
|
12323
|
+
createHash21("md5");
|
|
12324
12324
|
return true;
|
|
12325
12325
|
} catch {
|
|
12326
12326
|
return false;
|
|
@@ -12330,7 +12330,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12330
12330
|
function buildNativeClass$2() {
|
|
12331
12331
|
return class Md5Node2 {
|
|
12332
12332
|
digestLength = 16;
|
|
12333
|
-
hash =
|
|
12333
|
+
hash = createHash21("md5");
|
|
12334
12334
|
update(data) {
|
|
12335
12335
|
this.hash.update(toUint8Array(data));
|
|
12336
12336
|
}
|
|
@@ -12339,7 +12339,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12339
12339
|
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
12340
12340
|
}
|
|
12341
12341
|
reset() {
|
|
12342
|
-
this.hash =
|
|
12342
|
+
this.hash = createHash21("md5");
|
|
12343
12343
|
}
|
|
12344
12344
|
};
|
|
12345
12345
|
}
|
|
@@ -12629,7 +12629,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12629
12629
|
]);
|
|
12630
12630
|
var hasNativeCrypto = (() => {
|
|
12631
12631
|
try {
|
|
12632
|
-
|
|
12632
|
+
createHash21("sha256");
|
|
12633
12633
|
return true;
|
|
12634
12634
|
} catch {
|
|
12635
12635
|
return false;
|
|
@@ -12669,7 +12669,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
12669
12669
|
this.finished = false;
|
|
12670
12670
|
}
|
|
12671
12671
|
createHash() {
|
|
12672
|
-
return this.secret ? createHmac2("sha256", toBuffer(this.secret)) :
|
|
12672
|
+
return this.secret ? createHmac2("sha256", toBuffer(this.secret)) : createHash21("sha256");
|
|
12673
12673
|
}
|
|
12674
12674
|
};
|
|
12675
12675
|
}
|
|
@@ -14538,8 +14538,8 @@ var require_protocols = __commonJS((exports) => {
|
|
|
14538
14538
|
class Fields {
|
|
14539
14539
|
entries = {};
|
|
14540
14540
|
encoding;
|
|
14541
|
-
constructor({ fields = [], encoding = "utf-8" }) {
|
|
14542
|
-
|
|
14541
|
+
constructor({ fields: fields2 = [], encoding = "utf-8" }) {
|
|
14542
|
+
fields2.forEach(this.setField.bind(this));
|
|
14543
14543
|
this.encoding = encoding;
|
|
14544
14544
|
}
|
|
14545
14545
|
setField(field2) {
|
|
@@ -18166,7 +18166,7 @@ ${toHex(hashedRequest)}`;
|
|
|
18166
18166
|
return hash2.digest();
|
|
18167
18167
|
};
|
|
18168
18168
|
var getCanonicalHeaders = ({ headers }, unsignableHeaders, signableHeaders) => {
|
|
18169
|
-
const
|
|
18169
|
+
const canonical6 = {};
|
|
18170
18170
|
for (const headerName of Object.keys(headers).sort()) {
|
|
18171
18171
|
if (headers[headerName] == undefined) {
|
|
18172
18172
|
continue;
|
|
@@ -18177,9 +18177,9 @@ ${toHex(hashedRequest)}`;
|
|
|
18177
18177
|
continue;
|
|
18178
18178
|
}
|
|
18179
18179
|
}
|
|
18180
|
-
|
|
18180
|
+
canonical6[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " ");
|
|
18181
18181
|
}
|
|
18182
|
-
return
|
|
18182
|
+
return canonical6;
|
|
18183
18183
|
};
|
|
18184
18184
|
var getPayloadHash = async ({ headers, body }, hashConstructor) => {
|
|
18185
18185
|
for (const headerName in headers) {
|
|
@@ -21700,12 +21700,12 @@ var require_protocols2 = __commonJS((exports) => {
|
|
|
21700
21700
|
return expandToDecimal(numericString) === expandToDecimal(String(value));
|
|
21701
21701
|
}
|
|
21702
21702
|
const normalized = numericString.replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
|
|
21703
|
-
const
|
|
21704
|
-
if (normalized ===
|
|
21703
|
+
const canonical6 = String(value);
|
|
21704
|
+
if (normalized === canonical6) {
|
|
21705
21705
|
return true;
|
|
21706
21706
|
}
|
|
21707
|
-
if (/[eE]/.test(
|
|
21708
|
-
return normalized === expandToDecimal(
|
|
21707
|
+
if (/[eE]/.test(canonical6)) {
|
|
21708
|
+
return normalized === expandToDecimal(canonical6);
|
|
21709
21709
|
}
|
|
21710
21710
|
return false;
|
|
21711
21711
|
}
|
|
@@ -29443,7 +29443,7 @@ var require_signin = __commonJS((exports) => {
|
|
|
29443
29443
|
});
|
|
29444
29444
|
|
|
29445
29445
|
// node_modules/@aws-sdk/credential-provider-ini/node_modules/@aws-sdk/credential-provider-login/dist-es/LoginCredentialsFetcher.js
|
|
29446
|
-
import { createHash as
|
|
29446
|
+
import { createHash as createHash21, createPrivateKey, createPublicKey, sign } from "crypto";
|
|
29447
29447
|
import { promises as fs2 } from "fs";
|
|
29448
29448
|
import { homedir as homedir7 } from "os";
|
|
29449
29449
|
import { dirname as dirname21, join as join33 } from "path";
|
|
@@ -29615,7 +29615,7 @@ var init_LoginCredentialsFetcher = __esm(() => {
|
|
|
29615
29615
|
getTokenFilePath() {
|
|
29616
29616
|
const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join33(homedir7(), ".aws", "login", "cache");
|
|
29617
29617
|
const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
|
|
29618
|
-
const loginSessionSha256 =
|
|
29618
|
+
const loginSessionSha256 = createHash21("sha256").update(loginSessionBytes).digest("hex");
|
|
29619
29619
|
return join33(directory, `${loginSessionSha256}.json`);
|
|
29620
29620
|
}
|
|
29621
29621
|
derToRawSignature(derSignature) {
|
|
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
|
|
|
32373
32373
|
// package.json
|
|
32374
32374
|
var package_default = {
|
|
32375
32375
|
name: "@hasna/skills",
|
|
32376
|
-
version: "0.10.
|
|
32376
|
+
version: "0.10.22",
|
|
32377
32377
|
description: "Skills library for AI coding agents",
|
|
32378
32378
|
type: "module",
|
|
32379
32379
|
bin: {
|
|
@@ -37455,7 +37455,7 @@ async function reconcileSkillSession(input, options = {}) {
|
|
|
37455
37455
|
return { applied: true, plan, planDigest, ...result };
|
|
37456
37456
|
}
|
|
37457
37457
|
// src/lib/selected-run.ts
|
|
37458
|
-
import { createHash as
|
|
37458
|
+
import { createHash as createHash20 } from "crypto";
|
|
37459
37459
|
import { spawn as spawn2 } from "child_process";
|
|
37460
37460
|
import { mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync9, realpathSync as realpathSync11 } from "fs";
|
|
37461
37461
|
import { dirname as dirname20, join as join32, resolve as resolve18 } from "path";
|
|
@@ -38009,6 +38009,25 @@ function hashNativeJsonControls(text, excludedMetadata) {
|
|
|
38009
38009
|
import { basename as basename3, dirname as dirname5, join as join10, relative as relative3, resolve as resolve4, sep as sep2 } from "path";
|
|
38010
38010
|
import { lstatSync as lstatSync6, readdirSync as readdirSync3, readlinkSync as readlinkSync2, realpathSync as realpathSync5 } from "fs";
|
|
38011
38011
|
|
|
38012
|
+
// src/lib/codex-native-compatibility.ts
|
|
38013
|
+
var MEASURED_CODEX_CAPABILITIES = {
|
|
38014
|
+
"codex-cli 0.153.0": ["hooks"],
|
|
38015
|
+
"codex-cli 0.154.0": ["hooks"],
|
|
38016
|
+
"codex-cli 0.155.0": ["hooks"],
|
|
38017
|
+
"codex-cli 0.155.1": ["hooks"],
|
|
38018
|
+
"codex-cli 0.156.1": ["hooks"],
|
|
38019
|
+
"codex-cli 0.157.0": ["hooks"],
|
|
38020
|
+
"codex-cli 0.157.1": ["hooks"],
|
|
38021
|
+
"codex-cli 0.158.0": ["hooks"],
|
|
38022
|
+
"codex-cli 0.159.0": ["hooks"],
|
|
38023
|
+
"codex-cli 0.159.2": ["hooks", "qualified-skill-catalog"],
|
|
38024
|
+
"codex-cli 0.160.0": ["hooks", "qualified-skill-catalog"]
|
|
38025
|
+
};
|
|
38026
|
+
function supportsCodexNativeCapability(version, capability) {
|
|
38027
|
+
return typeof version === "string" && Object.hasOwn(MEASURED_CODEX_CAPABILITIES, version) && MEASURED_CODEX_CAPABILITIES[version].includes(capability);
|
|
38028
|
+
}
|
|
38029
|
+
var SUPPORTED_CODEX_HOOK_VERSIONS = Object.freeze(Object.keys(MEASURED_CODEX_CAPABILITIES).filter((version) => supportsCodexNativeCapability(version, "hooks")));
|
|
38030
|
+
|
|
38012
38031
|
// src/lib/codex-native-skill-catalog.ts
|
|
38013
38032
|
import { realpathSync as realpathSync4 } from "fs";
|
|
38014
38033
|
import { isAbsolute as isAbsolute5, normalize } from "path";
|
|
@@ -38018,7 +38037,6 @@ import { execFile, spawn } from "child_process";
|
|
|
38018
38037
|
import { realpathSync as realpathSync3, statSync as statSync3 } from "fs";
|
|
38019
38038
|
import { isAbsolute as isAbsolute4 } from "path";
|
|
38020
38039
|
import { promisify } from "util";
|
|
38021
|
-
var SUPPORTED_CODEX_HOOK_VERSIONS = ["codex-cli 0.153.0", "codex-cli 0.154.0", "codex-cli 0.155.0", "codex-cli 0.155.1", "codex-cli 0.156.1", "codex-cli 0.157.0", "codex-cli 0.157.1", "codex-cli 0.158.0", "codex-cli 0.159.0", "codex-cli 0.159.2"];
|
|
38022
38040
|
async function connectCodexHookRpc(options) {
|
|
38023
38041
|
const timeoutMs = options.timeoutMs ?? 20000;
|
|
38024
38042
|
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 100 || timeoutMs > 20000)
|
|
@@ -38036,7 +38054,7 @@ async function connectCodexHookRpc(options) {
|
|
|
38036
38054
|
} catch {
|
|
38037
38055
|
throw new Error("CODEX_HOOK_TRUST_NATIVE_UNAVAILABLE");
|
|
38038
38056
|
}
|
|
38039
|
-
if (!
|
|
38057
|
+
if (!supportsCodexNativeCapability(version, "hooks"))
|
|
38040
38058
|
throw new Error("CODEX_HOOK_TRUST_NATIVE_UNSUPPORTED_VERSION");
|
|
38041
38059
|
const current = statSync3(binary);
|
|
38042
38060
|
if (realpathSync3(found) !== binary || ["dev", "ino", "size", "mtimeMs", "ctimeMs"].some((k) => stat[k] !== current[k]))
|
|
@@ -38161,12 +38179,12 @@ var MAX_SKILLS = 4096;
|
|
|
38161
38179
|
var MAX_NAME_BYTES = 1024;
|
|
38162
38180
|
var MAX_PATH_BYTES = 16384;
|
|
38163
38181
|
var MAX_PLUGIN_ID_BYTES = 1024;
|
|
38164
|
-
var SUPPORTED_NAME_CONTROL_VERSIONS = new Set(["codex-cli 0.159.2"]);
|
|
38165
38182
|
function refuse2() {
|
|
38166
38183
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_INVALID");
|
|
38167
38184
|
}
|
|
38168
38185
|
var object2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
38169
38186
|
var scalar = (value, max) => typeof value === "string" && value.length > 0 && value.trim() === value && Buffer.byteLength(value, "utf8") <= max && !/[\u0000-\u001f\u007f]/u.test(value);
|
|
38187
|
+
var remotePluginIdentifier = (value) => typeof value === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(value);
|
|
38170
38188
|
var absolutePath2 = (value) => scalar(value, MAX_PATH_BYTES) && isAbsolute5(value);
|
|
38171
38189
|
function projectCodexNativeSkillCatalog(response, cwd) {
|
|
38172
38190
|
if (!absolutePath2(cwd) || !object2(response) || !Array.isArray(response.data) || response.data.length !== 1)
|
|
@@ -38194,7 +38212,11 @@ function projectCodexInstalledPlugins(response) {
|
|
|
38194
38212
|
for (const value of marketplace.plugins) {
|
|
38195
38213
|
if (!object2(value) || !scalar(value.id, MAX_PLUGIN_ID_BYTES) || !scalar(value.name, MAX_NAME_BYTES) || value.id !== `${value.name}@${marketplace.name}`)
|
|
38196
38214
|
refuse2();
|
|
38197
|
-
plugins.push({
|
|
38215
|
+
plugins.push({
|
|
38216
|
+
...value,
|
|
38217
|
+
marketplace: marketplace.name,
|
|
38218
|
+
sourceType: object2(value.source) && value.source.type === "remote" ? "remote" : undefined
|
|
38219
|
+
});
|
|
38198
38220
|
}
|
|
38199
38221
|
}
|
|
38200
38222
|
return projectCodexInstalledPluginEntries(plugins);
|
|
@@ -38204,13 +38226,21 @@ function projectCodexInstalledPluginEntries(value) {
|
|
|
38204
38226
|
refuse2();
|
|
38205
38227
|
const ids = new Set;
|
|
38206
38228
|
return value.map((item) => {
|
|
38207
|
-
if (!object2(item) || !scalar(item.id, MAX_PLUGIN_ID_BYTES) || !scalar(item.name, MAX_NAME_BYTES) || typeof item.installed !== "boolean" || typeof item.enabled !== "boolean" || item.localVersion !== null && !scalar(item.localVersion, MAX_NAME_BYTES))
|
|
38229
|
+
if (!object2(item) || !scalar(item.id, MAX_PLUGIN_ID_BYTES) || !scalar(item.name, MAX_NAME_BYTES) || typeof item.installed !== "boolean" || typeof item.enabled !== "boolean" || item.localVersion !== null && !scalar(item.localVersion, MAX_NAME_BYTES) || item.remotePluginId !== undefined && item.remotePluginId !== null && !remotePluginIdentifier(item.remotePluginId) || item.sourceType !== undefined && item.sourceType !== "remote")
|
|
38208
38230
|
refuse2();
|
|
38209
38231
|
const at = item.id.lastIndexOf("@");
|
|
38210
38232
|
if (at < 1 || item.id.slice(0, at) !== item.name || at === item.id.length - 1 || ids.has(item.id))
|
|
38211
38233
|
refuse2();
|
|
38212
38234
|
ids.add(item.id);
|
|
38213
|
-
return {
|
|
38235
|
+
return {
|
|
38236
|
+
id: item.id,
|
|
38237
|
+
name: item.name,
|
|
38238
|
+
installed: item.installed,
|
|
38239
|
+
enabled: item.enabled,
|
|
38240
|
+
localVersion: item.localVersion ?? null,
|
|
38241
|
+
...item.sourceType === "remote" ? { sourceType: "remote" } : {},
|
|
38242
|
+
...item.remotePluginId == null ? {} : { remotePluginId: item.remotePluginId }
|
|
38243
|
+
};
|
|
38214
38244
|
});
|
|
38215
38245
|
}
|
|
38216
38246
|
async function captureCodexNativeSkillCatalog(options, connect = connectCodexHookRpc) {
|
|
@@ -38223,7 +38253,7 @@ async function captureCodexNativeSkillCatalog(options, connect = connectCodexHoo
|
|
|
38223
38253
|
...options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }
|
|
38224
38254
|
});
|
|
38225
38255
|
try {
|
|
38226
|
-
if (!
|
|
38256
|
+
if (!supportsCodexNativeCapability(rpc.version, "qualified-skill-catalog"))
|
|
38227
38257
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_UNSUPPORTED_VERSION");
|
|
38228
38258
|
const response = await rpc.request("skills/list", { cwds: [options.cwd], forceReload: true });
|
|
38229
38259
|
const installed = await rpc.request("plugin/installed", { cwds: [options.cwd] });
|
|
@@ -38281,6 +38311,21 @@ var CODEX_DEFAULT_AGENT_PLUGIN_VERSION = "1.0.0";
|
|
|
38281
38311
|
function refuse3() {
|
|
38282
38312
|
throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
|
|
38283
38313
|
}
|
|
38314
|
+
function remoteInstallationMatches(parent, remotePluginId, read) {
|
|
38315
|
+
try {
|
|
38316
|
+
if (!remotePluginIdentifier(remotePluginId) || !lstatSync6(parent).isDirectory() || realpathSync5(parent) !== parent)
|
|
38317
|
+
return false;
|
|
38318
|
+
const path = join10(parent, ".codex-remote-plugin-install.json"), stat = lstatSync6(path, { throwIfNoEntry: false });
|
|
38319
|
+
if (!stat?.isFile() || stat.isSymbolicLink() || stat.size > 16384)
|
|
38320
|
+
return false;
|
|
38321
|
+
const text = read(path);
|
|
38322
|
+
hashNativeJsonControls(text);
|
|
38323
|
+
const value = JSON.parse(text);
|
|
38324
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 2 && value.schema_version === 1 && value.remote_plugin_id === remotePluginId);
|
|
38325
|
+
} catch {
|
|
38326
|
+
return false;
|
|
38327
|
+
}
|
|
38328
|
+
}
|
|
38284
38329
|
function appControls(path, read) {
|
|
38285
38330
|
const text = read(path);
|
|
38286
38331
|
let value, sha2562;
|
|
@@ -38370,6 +38415,10 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read) {
|
|
|
38370
38415
|
for (const parent of new Set(controls.map((control) => control.pluginParent))) {
|
|
38371
38416
|
if (!parent.startsWith(cache + sep2) || !lstatSync6(parent, { throwIfNoEntry: false })?.isDirectory())
|
|
38372
38417
|
return false;
|
|
38418
|
+
for (const control of controls.filter((control2) => control2.pluginParent === parent)) {
|
|
38419
|
+
if (control.remotePluginId !== undefined && !remoteInstallationMatches(parent, control.remotePluginId, read))
|
|
38420
|
+
return false;
|
|
38421
|
+
}
|
|
38373
38422
|
const names = readdirSync3(parent);
|
|
38374
38423
|
entries += names.length;
|
|
38375
38424
|
if (entries > 4096)
|
|
@@ -38396,7 +38445,7 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read) {
|
|
|
38396
38445
|
}
|
|
38397
38446
|
}
|
|
38398
38447
|
function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read, rules) {
|
|
38399
|
-
if (catalog?.version
|
|
38448
|
+
if (!supportsCodexNativeCapability(catalog?.version, "qualified-skill-catalog") || catalog.cwd !== cwd)
|
|
38400
38449
|
refuse3();
|
|
38401
38450
|
const skills = projectCodexNativeSkillCatalog({ data: [{ cwd, errors: [], skills: catalog.skills }] }, cwd);
|
|
38402
38451
|
const allowed = new Set(documents), result = [];
|
|
@@ -38423,20 +38472,28 @@ function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read, ru
|
|
|
38423
38472
|
const listed = skills.filter((skill) => skill.path === document);
|
|
38424
38473
|
if (listed.length > 1)
|
|
38425
38474
|
refuse3();
|
|
38475
|
+
let remotePluginId;
|
|
38426
38476
|
if (listed.length === 1) {
|
|
38427
38477
|
if (listed[0].name !== parsed.name || listed[0].pluginId !== expectedPluginId)
|
|
38428
38478
|
refuse3();
|
|
38429
38479
|
} else {
|
|
38430
|
-
const installed = installedPlugins.filter((
|
|
38431
|
-
if (installed.length !== 1 || !installed[0].installed || !installed[0].enabled
|
|
38480
|
+
const installed = installedPlugins.filter((plugin2) => plugin2.id === expectedPluginId && plugin2.name === pluginName);
|
|
38481
|
+
if (installed.length !== 1 || !installed[0].installed || !installed[0].enabled)
|
|
38432
38482
|
refuse3();
|
|
38433
|
-
|
|
38434
|
-
|
|
38483
|
+
const plugin = installed[0];
|
|
38484
|
+
if (plugin.localVersion !== null) {
|
|
38485
|
+
if (plugin.localVersion !== basename3(dirname5(dirname5(dirname5(document)))))
|
|
38486
|
+
continue;
|
|
38487
|
+
} else {
|
|
38488
|
+
if (plugin.sourceType !== "remote" || !plugin.remotePluginId || !remoteInstallationMatches(parsed.pluginParent, plugin.remotePluginId, read) || !lstatSync6(document).isFile() || realpathSync5(document) !== document)
|
|
38489
|
+
refuse3();
|
|
38490
|
+
remotePluginId = plugin.remotePluginId;
|
|
38491
|
+
}
|
|
38435
38492
|
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document && rule?.enabled === false);
|
|
38436
38493
|
if (!exactPathDeny || !isCodexNativeSkillDisabled({ name: parsed.name, path: document, pluginId: expectedPluginId, enabled: true }, rules))
|
|
38437
38494
|
refuse3();
|
|
38438
38495
|
}
|
|
38439
|
-
result.push({ ...parsed, pluginId: expectedPluginId });
|
|
38496
|
+
result.push({ ...parsed, pluginId: expectedPluginId, ...remotePluginId ? { remotePluginId } : {} });
|
|
38440
38497
|
}
|
|
38441
38498
|
if (!result.length || new Set(result.map((item) => item.name)).size !== result.length)
|
|
38442
38499
|
refuse3();
|
|
@@ -38452,7 +38509,7 @@ function isReviewedCodexPluginSkillDisabled(document, cache, controls, rules, re
|
|
|
38452
38509
|
return false;
|
|
38453
38510
|
}
|
|
38454
38511
|
const reviewed = controls.find((item) => item.name === parsed.name && item.namespace === parsed.namespace && item.pluginParent === parsed.pluginParent && item.manifestSha256 === parsed.manifestSha256 && item.appSha256 === parsed.appSha256);
|
|
38455
|
-
if (!reviewed)
|
|
38512
|
+
if (!reviewed || reviewed.remotePluginId !== undefined && !remoteInstallationMatches(reviewed.pluginParent, reviewed.remotePluginId, read))
|
|
38456
38513
|
return false;
|
|
38457
38514
|
return isCodexNativeSkillDisabled({ name: parsed.name, path: document, pluginId: reviewed.pluginId, enabled: true }, rules);
|
|
38458
38515
|
}
|
|
@@ -38471,7 +38528,7 @@ enabled = false
|
|
|
38471
38528
|
return text;
|
|
38472
38529
|
}
|
|
38473
38530
|
|
|
38474
|
-
// src/lib/codex-settings-witness.ts
|
|
38531
|
+
// src/lib/codex-settings-witness-v1.ts
|
|
38475
38532
|
import { createHash as createHash6 } from "crypto";
|
|
38476
38533
|
var sha = (text) => createHash6("sha256").update(text).digest("hex");
|
|
38477
38534
|
var EFFORT = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
|
|
@@ -38565,15 +38622,162 @@ function captureCodexSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
|
38565
38622
|
const text = readNativeSettingsWitnessFile(path, budget, "config.toml");
|
|
38566
38623
|
return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text) };
|
|
38567
38624
|
}
|
|
38625
|
+
|
|
38626
|
+
// src/lib/codex-settings-witness.ts
|
|
38627
|
+
import { createHash as createHash7 } from "crypto";
|
|
38628
|
+
var sha2 = (text) => createHash7("sha256").update(text).digest("hex");
|
|
38629
|
+
var EFFORT2 = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
|
|
38630
|
+
var VERBOSITY2 = new Set(["low", "medium", "high"]);
|
|
38631
|
+
var MODEL = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/;
|
|
38632
|
+
var CODEX_DISCOVERY_PROJECTION_FIELDS = ["plugins", "marketplaces", "skills"];
|
|
38633
|
+
var INFERENCE = ["model", "model_reasoning_effort", "model_verbosity"];
|
|
38634
|
+
function need3(value) {
|
|
38635
|
+
if (!value)
|
|
38636
|
+
throw new Error("Invalid Codex settings witness");
|
|
38637
|
+
}
|
|
38638
|
+
function isRecord(value) {
|
|
38639
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
38640
|
+
}
|
|
38641
|
+
function isDate(value) {
|
|
38642
|
+
return value instanceof Date;
|
|
38643
|
+
}
|
|
38644
|
+
function numericTokens2(text) {
|
|
38645
|
+
const result = [];
|
|
38646
|
+
for (let at = 0;at < text.length; ) {
|
|
38647
|
+
const char = text[at];
|
|
38648
|
+
if (char === "#") {
|
|
38649
|
+
while (at < text.length && text[at] !== `
|
|
38650
|
+
`)
|
|
38651
|
+
at++;
|
|
38652
|
+
continue;
|
|
38653
|
+
}
|
|
38654
|
+
if (char === '"' || char === "'") {
|
|
38655
|
+
const quote = char, triple = text.slice(at, at + 3) === quote.repeat(3);
|
|
38656
|
+
at += triple ? 3 : 1;
|
|
38657
|
+
while (at < text.length) {
|
|
38658
|
+
if (quote === '"' && text[at] === "\\") {
|
|
38659
|
+
at += 2;
|
|
38660
|
+
continue;
|
|
38661
|
+
}
|
|
38662
|
+
if (text.slice(at, at + (triple ? 3 : 1)) === quote.repeat(triple ? 3 : 1)) {
|
|
38663
|
+
at += triple ? 3 : 1;
|
|
38664
|
+
break;
|
|
38665
|
+
}
|
|
38666
|
+
at++;
|
|
38667
|
+
}
|
|
38668
|
+
continue;
|
|
38669
|
+
}
|
|
38670
|
+
if (/[0-9+-]/.test(char)) {
|
|
38671
|
+
const start = at;
|
|
38672
|
+
while (at < text.length && !/[\s,\]{}#=]/.test(text[at]))
|
|
38673
|
+
at++;
|
|
38674
|
+
if (at > start) {
|
|
38675
|
+
result.push(text.slice(start, at));
|
|
38676
|
+
continue;
|
|
38677
|
+
}
|
|
38678
|
+
}
|
|
38679
|
+
at++;
|
|
38680
|
+
}
|
|
38681
|
+
return result.sort();
|
|
38682
|
+
}
|
|
38683
|
+
function canonical3(value, depth = 0, budget = { remaining: 65536 }) {
|
|
38684
|
+
need3(depth <= 32 && --budget.remaining >= 0);
|
|
38685
|
+
if (value === null)
|
|
38686
|
+
return ["null"];
|
|
38687
|
+
if (typeof value === "string")
|
|
38688
|
+
return ["string", value];
|
|
38689
|
+
if (typeof value === "boolean")
|
|
38690
|
+
return ["boolean", value];
|
|
38691
|
+
if (typeof value === "number") {
|
|
38692
|
+
need3(Number.isFinite(value));
|
|
38693
|
+
return ["number", String(value)];
|
|
38694
|
+
}
|
|
38695
|
+
if (isDate(value)) {
|
|
38696
|
+
need3(Number.isFinite(value.getTime()));
|
|
38697
|
+
return ["date", value.toISOString()];
|
|
38698
|
+
}
|
|
38699
|
+
if (Array.isArray(value))
|
|
38700
|
+
return ["array", value.map((child) => canonical3(child, depth + 1, budget))];
|
|
38701
|
+
need3(isRecord(value));
|
|
38702
|
+
return ["object", Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, child]) => [key, canonical3(child, depth + 1, budget)])];
|
|
38703
|
+
}
|
|
38704
|
+
function normalize2(config) {
|
|
38705
|
+
if (isRecord(config.hooks)) {
|
|
38706
|
+
delete config.hooks.state;
|
|
38707
|
+
if (!Object.keys(config.hooks).length)
|
|
38708
|
+
delete config.hooks;
|
|
38709
|
+
}
|
|
38710
|
+
if (isRecord(config.skills) && Array.isArray(config.skills.config)) {
|
|
38711
|
+
const skills = config.skills;
|
|
38712
|
+
const retained = skills.config.filter((entry) => !disablesOneSkill(entry));
|
|
38713
|
+
if (retained.length !== skills.config.length) {
|
|
38714
|
+
if (retained.length)
|
|
38715
|
+
skills.config = retained;
|
|
38716
|
+
else
|
|
38717
|
+
delete skills.config;
|
|
38718
|
+
}
|
|
38719
|
+
if (!Object.keys(skills).length)
|
|
38720
|
+
delete config.skills;
|
|
38721
|
+
}
|
|
38722
|
+
inference(config);
|
|
38723
|
+
if (isRecord(config.profiles)) {
|
|
38724
|
+
for (const profile of Object.values(config.profiles))
|
|
38725
|
+
if (isRecord(profile))
|
|
38726
|
+
inference(profile);
|
|
38727
|
+
}
|
|
38728
|
+
}
|
|
38729
|
+
function disablesOneSkill(entry) {
|
|
38730
|
+
if (!isRecord(entry) || entry.enabled !== false)
|
|
38731
|
+
return false;
|
|
38732
|
+
const keys2 = Object.keys(entry);
|
|
38733
|
+
if (!keys2.every((key) => key === "path" || key === "name" || key === "enabled"))
|
|
38734
|
+
return false;
|
|
38735
|
+
const selector = ["path", "name"].filter((key) => Object.hasOwn(entry, key));
|
|
38736
|
+
return selector.length === 1 && typeof entry[selector[0]] === "string" && entry[selector[0]].length > 0;
|
|
38737
|
+
}
|
|
38738
|
+
function inference(target) {
|
|
38739
|
+
for (const key of INFERENCE)
|
|
38740
|
+
if (Object.hasOwn(target, key)) {
|
|
38741
|
+
const value = target[key];
|
|
38742
|
+
if (key === "model")
|
|
38743
|
+
need3(typeof value === "string" && MODEL.test(value));
|
|
38744
|
+
else
|
|
38745
|
+
need3(typeof value === "string" && (key === "model_reasoning_effort" ? EFFORT2.has(value) : VERBOSITY2.has(value)));
|
|
38746
|
+
delete target[key];
|
|
38747
|
+
}
|
|
38748
|
+
}
|
|
38749
|
+
function settingsDigest2(text) {
|
|
38750
|
+
let config;
|
|
38751
|
+
try {
|
|
38752
|
+
config = Bun.TOML.parse(text);
|
|
38753
|
+
} catch {
|
|
38754
|
+
throw new Error("Invalid Codex settings witness");
|
|
38755
|
+
}
|
|
38756
|
+
need3(isRecord(config));
|
|
38757
|
+
normalize2(config);
|
|
38758
|
+
return sha2(`hasna.skills.codex-settings.v2\x00${JSON.stringify([canonical3(config), numericTokens2(text)])}`);
|
|
38759
|
+
}
|
|
38760
|
+
function hashCodexSettingsReplacementV2(text, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
38761
|
+
need3(Buffer.byteLength(text) <= 1024 * 1024 && budget.remaining >= Buffer.byteLength(text));
|
|
38762
|
+
budget.remaining -= Buffer.byteLength(text);
|
|
38763
|
+
return settingsDigest2(text);
|
|
38764
|
+
}
|
|
38765
|
+
function captureCodexSettingsV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
38766
|
+
const text = readNativeSettingsWitnessFile(path, budget, "config.toml");
|
|
38767
|
+
return { path, hashMode: "codex-settings-v2", sha256: settingsDigest2(text) };
|
|
38768
|
+
}
|
|
38769
|
+
function readCodexSettingsPreimage(path, budget = { remaining: 2 * 1024 * 1024 }) {
|
|
38770
|
+
return readNativeSettingsWitnessFile(path, budget, "config.toml");
|
|
38771
|
+
}
|
|
38568
38772
|
function upgradeCodexSettingsWitness(previous, reviewedSettingsPath) {
|
|
38569
|
-
|
|
38773
|
+
need3(previous && Object.keys(previous).every((key) => ["path", "hashMode", "sha256"].includes(key)) && (previous.hashMode === undefined || previous.hashMode === "bytes" || previous.hashMode === "codex-settings-v1") && /^[a-f0-9]{64}$/.test(previous.sha256));
|
|
38570
38774
|
const budget = { remaining: 2 * 1024 * 1024 };
|
|
38571
38775
|
const before = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
|
|
38572
|
-
|
|
38573
|
-
const sha2562 =
|
|
38574
|
-
if (
|
|
38776
|
+
need3((previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before) : sha2(before)) === previous.sha256);
|
|
38777
|
+
const sha2562 = settingsDigest2(current);
|
|
38778
|
+
if (settingsDigest2(before) !== sha2562)
|
|
38575
38779
|
throw new Error("Codex non-preference settings changed; explicit discovery review required");
|
|
38576
|
-
return { path: previous.path, hashMode: "codex-settings-
|
|
38780
|
+
return { path: previous.path, hashMode: "codex-settings-v2", sha256: sha2562 };
|
|
38577
38781
|
}
|
|
38578
38782
|
|
|
38579
38783
|
// src/lib/native-discovery-roots.ts
|
|
@@ -38596,7 +38800,8 @@ var NATIVE_SKILL_ROOTS = [
|
|
|
38596
38800
|
];
|
|
38597
38801
|
|
|
38598
38802
|
// src/lib/agent-integration.ts
|
|
38599
|
-
import { createHash as
|
|
38803
|
+
import { createHash as createHash18, randomUUID as randomUUID3 } from "crypto";
|
|
38804
|
+
import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
|
|
38600
38805
|
import { existsSync as existsSync6, lstatSync as lstatSync19, statSync as statSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync14, readdirSync as readdirSync8, opendirSync as opendirSync5, readlinkSync as readlinkSync4, realpathSync as realpathSync7, renameSync as renameSync3, rmdirSync as rmdirSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4, chmodSync, openSync as openSync16, closeSync as closeSync16, fsyncSync as fsyncSync4, fstatSync as fstatSync16, readSync as readSync11, constants as constants12, linkSync as linkSync2 } from "fs";
|
|
38601
38806
|
import { dirname as dirname15, join as join22, resolve as resolve15, relative as relative4, isAbsolute as isAbsolute17, sep as sep5 } from "path";
|
|
38602
38807
|
import { homedir as homedir3 } from "os";
|
|
@@ -38655,12 +38860,14 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38655
38860
|
}
|
|
38656
38861
|
if (bridge.codexPluginSkills !== undefined)
|
|
38657
38862
|
for (const control of array(bridge.codexPluginSkills, 4096)) {
|
|
38658
|
-
requireBound(object3(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256"].includes(key)));
|
|
38863
|
+
requireBound(object3(control) && Object.keys(control).every((key) => ["name", "pluginId", "namespace", "pluginParent", "manifestSha256", "appSha256", "remotePluginId"].includes(key)));
|
|
38659
38864
|
text(control.name, 129);
|
|
38660
38865
|
text(control.pluginId, 1024);
|
|
38661
38866
|
text(control.namespace, 64);
|
|
38662
38867
|
text(control.pluginParent);
|
|
38663
38868
|
requireBound(isAbsolute6(control.pluginParent) && resolve5(control.pluginParent) === control.pluginParent && /^[a-f0-9]{64}$/.test(control.manifestSha256));
|
|
38869
|
+
if (control.remotePluginId !== undefined)
|
|
38870
|
+
requireBound(typeof control.remotePluginId === "string" && /^[A-Za-z0-9_~-]{1,1024}$/.test(control.remotePluginId));
|
|
38664
38871
|
if (control.appSha256 !== undefined)
|
|
38665
38872
|
requireBound(typeof control.appSha256 === "string" && /^[a-f0-9]{64}$/.test(control.appSha256));
|
|
38666
38873
|
}
|
|
@@ -38683,8 +38890,8 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38683
38890
|
text(source.path);
|
|
38684
38891
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
38685
38892
|
if (source.hashMode !== undefined)
|
|
38686
|
-
requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
38687
|
-
if (source.hashMode === "codex-settings-v1")
|
|
38893
|
+
requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry", "claude-settings-v1", "claude-settings-v2", "claude-settings-v3", "claude-marketplace-registry-v2", "codex-settings-v1", "codex-settings-v2"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
38894
|
+
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2")
|
|
38688
38895
|
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path && basename4(source.path) === "config.toml");
|
|
38689
38896
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
|
|
38690
38897
|
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path && basename4(source.path) === "settings.json");
|
|
@@ -38798,7 +39005,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
|
|
|
38798
39005
|
}
|
|
38799
39006
|
|
|
38800
39007
|
// src/lib/agent-bridge.ts
|
|
38801
|
-
import { createHash as
|
|
39008
|
+
import { createHash as createHash8 } from "crypto";
|
|
38802
39009
|
import { lstatSync as lstatSync8, readFileSync as readFileSync9, readdirSync as readdirSync4 } from "fs";
|
|
38803
39010
|
import { join as join12 } from "path";
|
|
38804
39011
|
var CLI_BRIDGE_NAME = "skills-cli";
|
|
@@ -38817,7 +39024,7 @@ Use the Skills CLI as the skill authority for this station.
|
|
|
38817
39024
|
|
|
38818
39025
|
This bridge contains no skill payloads. Do not copy skill content into agent-native skill directories or load other native skill copies. If a Skills command refuses authority, selection, integrity, or native drift, report that refusal and use its repair guidance; do not substitute bundled or stale local content. Explicit local draft authoring remains available.
|
|
38819
39026
|
`;
|
|
38820
|
-
var CLI_BRIDGE_DIGEST =
|
|
39027
|
+
var CLI_BRIDGE_DIGEST = createHash8("sha256").update(markdown).digest("hex");
|
|
38821
39028
|
var CLI_BRIDGE_FILES = Object.freeze({
|
|
38822
39029
|
"SKILL.md": markdown,
|
|
38823
39030
|
".hasna-skills.json": `${JSON.stringify({ managedBy: "@hasna/skills", kind: "cli-bridge", version: CLI_BRIDGE_VERSION, protocol: "selection-v1", contentSha256: CLI_BRIDGE_DIGEST }, null, 2)}
|
|
@@ -38841,7 +39048,7 @@ function isOwnedCliBridge(path, expectedPaths) {
|
|
|
38841
39048
|
}
|
|
38842
39049
|
|
|
38843
39050
|
// src/lib/agent-discovery.ts
|
|
38844
|
-
import { createHash as
|
|
39051
|
+
import { createHash as createHash17 } from "crypto";
|
|
38845
39052
|
import { lstatSync as lstatSync18, readFileSync as readFileSync13, readdirSync as readdirSync7, realpathSync as realpathSync6 } from "fs";
|
|
38846
39053
|
import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute16, join as join21, resolve as resolve14, sep as sep4 } from "path";
|
|
38847
39054
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
@@ -39100,17 +39307,17 @@ if (failed) process.exitCode = 2;
|
|
|
39100
39307
|
}
|
|
39101
39308
|
|
|
39102
39309
|
// src/lib/agent-discovery-directories.ts
|
|
39103
|
-
import { createHash as
|
|
39310
|
+
import { createHash as createHash9 } from "crypto";
|
|
39104
39311
|
import { lstatSync as lstatSync10, opendirSync as opendirSync2 } from "fs";
|
|
39105
39312
|
import { dirname as dirname7, isAbsolute as isAbsolute8, join as join14, resolve as resolve7 } from "path";
|
|
39106
|
-
function
|
|
39313
|
+
function need4(value, message) {
|
|
39107
39314
|
if (!value)
|
|
39108
39315
|
throw new Error(message);
|
|
39109
39316
|
}
|
|
39110
39317
|
function safe(path) {
|
|
39111
|
-
|
|
39318
|
+
need4(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute8(path) && resolve7(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
|
|
39112
39319
|
for (let cursor = path;; cursor = dirname7(cursor)) {
|
|
39113
|
-
|
|
39320
|
+
need4(!lstatSync10(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
|
|
39114
39321
|
if (dirname7(cursor) === cursor)
|
|
39115
39322
|
break;
|
|
39116
39323
|
}
|
|
@@ -39123,55 +39330,55 @@ function capture(path, budget) {
|
|
|
39123
39330
|
const root = lstatSync10(path, { throwIfNoEntry: false });
|
|
39124
39331
|
if (!root)
|
|
39125
39332
|
return { path, sha256: null };
|
|
39126
|
-
|
|
39127
|
-
const hash2 =
|
|
39333
|
+
need4(root.isDirectory(), "Unsupported native discovery directory input");
|
|
39334
|
+
const hash2 = createHash9("sha256");
|
|
39128
39335
|
function walk2(current, relative4, before, depth) {
|
|
39129
|
-
|
|
39336
|
+
need4(depth <= 64, "Native discovery directory depth limit exceeded");
|
|
39130
39337
|
const names = [], directory = opendirSync2(current);
|
|
39131
39338
|
try {
|
|
39132
39339
|
for (let entry = directory.readSync();entry; entry = directory.readSync()) {
|
|
39133
|
-
|
|
39340
|
+
need4(++budget.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
|
|
39134
39341
|
names.push(entry.name);
|
|
39135
39342
|
}
|
|
39136
39343
|
} finally {
|
|
39137
39344
|
directory.closeSync();
|
|
39138
39345
|
}
|
|
39139
|
-
|
|
39346
|
+
need4(new Set(names).size === names.length, "Ambiguous native discovery directory names");
|
|
39140
39347
|
for (const name of names.sort()) {
|
|
39141
39348
|
const child = join14(current, name), childRelative = relative4 ? `${relative4}/${name}` : name;
|
|
39142
|
-
|
|
39349
|
+
need4(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
|
|
39143
39350
|
const stat = lstatSync10(child);
|
|
39144
|
-
|
|
39351
|
+
need4(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
|
|
39145
39352
|
const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
|
|
39146
39353
|
`;
|
|
39147
39354
|
budget.bytes += Buffer.byteLength(row);
|
|
39148
|
-
|
|
39355
|
+
need4(budget.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
|
|
39149
39356
|
hash2.update(row);
|
|
39150
39357
|
if (stat.isDirectory())
|
|
39151
39358
|
walk2(child, childRelative, stat, depth + 1);
|
|
39152
39359
|
}
|
|
39153
|
-
|
|
39360
|
+
need4(same(before, lstatSync10(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
|
|
39154
39361
|
}
|
|
39155
39362
|
walk2(path, "", root, 0);
|
|
39156
39363
|
safe(path);
|
|
39157
39364
|
return { path, sha256: hash2.digest("hex") };
|
|
39158
39365
|
}
|
|
39159
39366
|
function captureDiscoveryDirectories(paths) {
|
|
39160
|
-
|
|
39367
|
+
need4(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
|
|
39161
39368
|
const budget = { entries: 0, bytes: 0 };
|
|
39162
39369
|
return paths.map((path) => capture(path, budget));
|
|
39163
39370
|
}
|
|
39164
39371
|
function verifyDiscoveryDirectories(directories) {
|
|
39165
|
-
|
|
39372
|
+
need4(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
|
|
39166
39373
|
for (const directory of directories)
|
|
39167
|
-
|
|
39374
|
+
need4(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
|
|
39168
39375
|
const current = captureDiscoveryDirectories(directories.map((directory) => directory.path));
|
|
39169
39376
|
for (let i = 0;i < directories.length; i++)
|
|
39170
|
-
|
|
39377
|
+
need4(current[i].sha256 === directories[i].sha256, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`);
|
|
39171
39378
|
}
|
|
39172
39379
|
|
|
39173
39380
|
// src/lib/agent-discovery-bytes.ts
|
|
39174
|
-
import { createHash as
|
|
39381
|
+
import { createHash as createHash10 } from "crypto";
|
|
39175
39382
|
import { closeSync as closeSync11, constants as constants7, fstatSync as fstatSync11, lstatSync as lstatSync11, openSync as openSync11, readSync as readSync6 } from "fs";
|
|
39176
39383
|
import { dirname as dirname8, isAbsolute as isAbsolute9, resolve as resolve8 } from "path";
|
|
39177
39384
|
function discoveryByteBudget() {
|
|
@@ -39202,7 +39409,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
|
|
|
39202
39409
|
if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
|
|
39203
39410
|
throw new Error("Raw discovery file byte limit exceeded");
|
|
39204
39411
|
consume(budget, bytes);
|
|
39205
|
-
return
|
|
39412
|
+
return createHash10("sha256").update(text2).digest("hex");
|
|
39206
39413
|
}
|
|
39207
39414
|
const initial = lstatSync11(path, { throwIfNoEntry: false });
|
|
39208
39415
|
if (!initial)
|
|
@@ -39216,7 +39423,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
|
|
|
39216
39423
|
const opened = fstatSync11(fd);
|
|
39217
39424
|
if (!opened.isFile() || !same2(initial, opened))
|
|
39218
39425
|
throw new Error("Raw discovery input changed during open");
|
|
39219
|
-
const hash2 =
|
|
39426
|
+
const hash2 = createHash10("sha256"), buffer = Buffer.alloc(64 * 1024);
|
|
39220
39427
|
let bytes = 0;
|
|
39221
39428
|
while (true) {
|
|
39222
39429
|
const count = readSync6(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
|
|
@@ -39239,7 +39446,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
|
|
|
39239
39446
|
}
|
|
39240
39447
|
|
|
39241
39448
|
// src/lib/agent-discovery-path-bytes.ts
|
|
39242
|
-
import { createHash as
|
|
39449
|
+
import { createHash as createHash11 } from "crypto";
|
|
39243
39450
|
import { lstatSync as lstatSync12, readlinkSync as readlinkSync3 } from "fs";
|
|
39244
39451
|
import { dirname as dirname9, isAbsolute as isAbsolute10, join as join15, parse as parse3, resolve as resolve9, sep as sep3 } from "path";
|
|
39245
39452
|
function identity3(stat, mutable = false) {
|
|
@@ -39252,12 +39459,12 @@ function identity3(stat, mutable = false) {
|
|
|
39252
39459
|
...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
|
|
39253
39460
|
};
|
|
39254
39461
|
}
|
|
39255
|
-
function
|
|
39462
|
+
function canonical4(path) {
|
|
39256
39463
|
if (typeof path !== "string" || !isAbsolute10(path) || path !== resolve9(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
|
|
39257
39464
|
throw new Error("Expected a canonical absolute discovery path");
|
|
39258
39465
|
}
|
|
39259
39466
|
function trace(path) {
|
|
39260
|
-
|
|
39467
|
+
canonical4(path);
|
|
39261
39468
|
const rows = [], paths = [];
|
|
39262
39469
|
let metadataBytes = 0, steps = 0, links = 0, cursor = parse3(path).root, pending = path.slice(cursor.length).split(sep3);
|
|
39263
39470
|
function record3(path2, row) {
|
|
@@ -39349,7 +39556,7 @@ function hashDiscoveryPathFile(path, budget, changes) {
|
|
|
39349
39556
|
const after = trace(path);
|
|
39350
39557
|
if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
|
|
39351
39558
|
throw new Error("Discovery path input changed during read");
|
|
39352
|
-
return
|
|
39559
|
+
return createHash11("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
|
|
39353
39560
|
}
|
|
39354
39561
|
|
|
39355
39562
|
// src/lib/plugin-discovery.ts
|
|
@@ -39361,7 +39568,7 @@ import { homedir as homedir2 } from "os";
|
|
|
39361
39568
|
import { isAbsolute as isAbsolute13, join as join19, resolve as resolve11 } from "path";
|
|
39362
39569
|
|
|
39363
39570
|
// src/lib/plugin-projection.ts
|
|
39364
|
-
import { createHash as
|
|
39571
|
+
import { createHash as createHash12 } from "crypto";
|
|
39365
39572
|
import { posix as posix2 } from "path";
|
|
39366
39573
|
var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json";
|
|
39367
39574
|
var PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
|
|
@@ -39372,7 +39579,7 @@ function pluginNeed(value, message) {
|
|
|
39372
39579
|
if (!value)
|
|
39373
39580
|
pluginRefusal(message);
|
|
39374
39581
|
}
|
|
39375
|
-
var pluginHash = (bytes) =>
|
|
39582
|
+
var pluginHash = (bytes) => createHash12("sha256").update(bytes).digest("hex");
|
|
39376
39583
|
function pluginObject(value) {
|
|
39377
39584
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
39378
39585
|
}
|
|
@@ -39560,7 +39767,7 @@ function buildPluginProjection(entries) {
|
|
|
39560
39767
|
}
|
|
39561
39768
|
|
|
39562
39769
|
// src/lib/plugin-projection-store.ts
|
|
39563
|
-
import { createHash as
|
|
39770
|
+
import { createHash as createHash13, randomUUID as randomUUID2 } from "crypto";
|
|
39564
39771
|
import { constants as constants8, closeSync as closeSync12, fchmodSync, fstatSync as fstatSync12, fsyncSync as fsyncSync2, linkSync, lstatSync as lstatSync13, mkdirSync as mkdirSync4, openSync as openSync12, opendirSync as opendirSync3, readSync as readSync7, renameSync as renameSync2, rmdirSync as rmdirSync2, rmSync, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
|
|
39565
39772
|
import { dirname as dirname10, isAbsolute as isAbsolute11, join as join16, parse as parse5, resolve as resolve10 } from "path";
|
|
39566
39773
|
var READ_FLAGS = constants8.O_RDONLY | constants8.O_NOFOLLOW | constants8.O_NONBLOCK;
|
|
@@ -39576,7 +39783,7 @@ function stat(path) {
|
|
|
39576
39783
|
return pluginRefusal("Cannot inspect plugin filesystem entry");
|
|
39577
39784
|
}
|
|
39578
39785
|
}
|
|
39579
|
-
function
|
|
39786
|
+
function canonical5(path) {
|
|
39580
39787
|
pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute11(path) && resolve10(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
|
|
39581
39788
|
}
|
|
39582
39789
|
function owner(stats, system = false) {
|
|
@@ -39587,7 +39794,7 @@ function same3(left, right, identityOnly = false) {
|
|
|
39587
39794
|
pluginNeed(right && left.dev === right.dev && left.ino === right.ino && left.mode === right.mode && left.uid === right.uid && left.gid === right.gid && (identityOnly || left.size === right.size && left.nlink === right.nlink && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs), "Plugin filesystem entry changed during access");
|
|
39588
39795
|
}
|
|
39589
39796
|
function ancestors(path, create = false) {
|
|
39590
|
-
|
|
39797
|
+
canonical5(path);
|
|
39591
39798
|
const result = [], parent = dirname10(path), filesystemRoot = parse5(parent).root;
|
|
39592
39799
|
let current = filesystemRoot;
|
|
39593
39800
|
for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
|
|
@@ -39902,7 +40109,7 @@ function pluginExecutableDigest(path) {
|
|
|
39902
40109
|
const opened = fstatSync12(fd, { bigint: true });
|
|
39903
40110
|
same3(before, opened);
|
|
39904
40111
|
fileShape(opened, maximum, "executable");
|
|
39905
|
-
const hash2 =
|
|
40112
|
+
const hash2 = createHash13("sha256"), buffer = new Uint8Array(64 * 1024);
|
|
39906
40113
|
let remaining = Number(opened.size);
|
|
39907
40114
|
while (remaining > 0) {
|
|
39908
40115
|
const count = readSync7(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
|
|
@@ -39927,7 +40134,7 @@ function pluginExecutableDigest(path) {
|
|
|
39927
40134
|
|
|
39928
40135
|
// src/lib/skill-validation.ts
|
|
39929
40136
|
import { existsSync as existsSync5, lstatSync as lstatSync14, readFileSync as readFileSync12, readdirSync as readdirSync6, statSync as statSync5 } from "fs";
|
|
39930
|
-
import { isAbsolute as isAbsolute12, join as join18, normalize as
|
|
40137
|
+
import { isAbsolute as isAbsolute12, join as join18, normalize as normalize3 } from "path";
|
|
39931
40138
|
|
|
39932
40139
|
// src/lib/hosted-skill-set.ts
|
|
39933
40140
|
import { existsSync as existsSync4, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
@@ -40033,7 +40240,7 @@ function sortMessages(messages) {
|
|
|
40033
40240
|
function isSafeRelativePath(value) {
|
|
40034
40241
|
if (!value.trim() || isAbsolute12(value))
|
|
40035
40242
|
return false;
|
|
40036
|
-
const normalized =
|
|
40243
|
+
const normalized = normalize3(value).replace(/\\/g, "/");
|
|
40037
40244
|
return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
|
|
40038
40245
|
}
|
|
40039
40246
|
function validateRuntimeEntry(skillPath, entrypoint, issues, warnings) {
|
|
@@ -40897,23 +41104,23 @@ function captureManagedPluginRegistry(path, managedPlugins) {
|
|
|
40897
41104
|
}
|
|
40898
41105
|
|
|
40899
41106
|
// src/lib/claude-marketplace-registry.ts
|
|
40900
|
-
import { createHash as
|
|
41107
|
+
import { createHash as createHash14 } from "crypto";
|
|
40901
41108
|
import { closeSync as closeSync14, constants as constants10, fstatSync as fstatSync14, lstatSync as lstatSync16, openSync as openSync14, readSync as readSync9 } from "fs";
|
|
40902
41109
|
import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute15, resolve as resolve13 } from "path";
|
|
40903
41110
|
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
40904
|
-
function
|
|
41111
|
+
function need5(value, reason) {
|
|
40905
41112
|
if (!value)
|
|
40906
41113
|
throw new Error(`Claude marketplace registry ${reason}`);
|
|
40907
41114
|
}
|
|
40908
41115
|
function absolutePath3(value) {
|
|
40909
|
-
|
|
41116
|
+
need5(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute15(value) && resolve13(value) === value, "requires a normalized absolute path");
|
|
40910
41117
|
}
|
|
40911
41118
|
var 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;
|
|
40912
41119
|
function parents2(path) {
|
|
40913
41120
|
const result = [];
|
|
40914
41121
|
for (let at = dirname12(path);; at = dirname12(at)) {
|
|
40915
41122
|
const stat2 = lstatSync16(at, { bigint: true });
|
|
40916
|
-
|
|
41123
|
+
need5(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
40917
41124
|
result.push([at, stat2]);
|
|
40918
41125
|
if (at === dirname12(at))
|
|
40919
41126
|
return result;
|
|
@@ -40921,15 +41128,15 @@ function parents2(path) {
|
|
|
40921
41128
|
}
|
|
40922
41129
|
function readRegistry2(path, budget) {
|
|
40923
41130
|
absolutePath3(path);
|
|
40924
|
-
|
|
40925
|
-
|
|
41131
|
+
need5(basename6(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
41132
|
+
need5(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
|
|
40926
41133
|
const ancestors2 = parents2(path), initial = lstatSync16(path, { bigint: true });
|
|
40927
|
-
|
|
40928
|
-
|
|
41134
|
+
need5(initial.isFile() && !initial.isSymbolicLink() && initial.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
41135
|
+
need5(initial.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
|
|
40929
41136
|
const fd = openSync14(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
|
|
40930
41137
|
try {
|
|
40931
41138
|
const opened = fstatSync14(fd, { bigint: true });
|
|
40932
|
-
|
|
41139
|
+
need5(opened.isFile() && sameFile2(initial, opened), "changed during open");
|
|
40933
41140
|
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
40934
41141
|
let length = 0;
|
|
40935
41142
|
while (length < bytes.length) {
|
|
@@ -40939,10 +41146,10 @@ function readRegistry2(path, budget) {
|
|
|
40939
41146
|
length += count;
|
|
40940
41147
|
}
|
|
40941
41148
|
const after = fstatSync14(fd, { bigint: true }), current = lstatSync16(path, { bigint: true });
|
|
40942
|
-
|
|
41149
|
+
need5(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
|
|
40943
41150
|
for (const [ancestor, before] of ancestors2) {
|
|
40944
41151
|
const now = lstatSync16(ancestor, { bigint: true });
|
|
40945
|
-
|
|
41152
|
+
need5(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
40946
41153
|
}
|
|
40947
41154
|
budget.remaining -= length;
|
|
40948
41155
|
try {
|
|
@@ -40962,7 +41169,7 @@ function parse6(text2) {
|
|
|
40962
41169
|
at++;
|
|
40963
41170
|
};
|
|
40964
41171
|
function string() {
|
|
40965
|
-
|
|
41172
|
+
need5(text2[at] === '"', "contains invalid JSON");
|
|
40966
41173
|
const start = at++;
|
|
40967
41174
|
while (at < text2.length) {
|
|
40968
41175
|
const character = text2[at++];
|
|
@@ -40973,7 +41180,7 @@ function parse6(text2) {
|
|
|
40973
41180
|
} catch {
|
|
40974
41181
|
throw new Error("Claude marketplace registry contains invalid JSON string");
|
|
40975
41182
|
}
|
|
40976
|
-
|
|
41183
|
+
need5(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
|
|
40977
41184
|
return value2;
|
|
40978
41185
|
}
|
|
40979
41186
|
if (character === "\\")
|
|
@@ -40982,7 +41189,7 @@ function parse6(text2) {
|
|
|
40982
41189
|
throw new Error("Claude marketplace registry contains an unterminated JSON string");
|
|
40983
41190
|
}
|
|
40984
41191
|
function value(depth) {
|
|
40985
|
-
|
|
41192
|
+
need5(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
40986
41193
|
space();
|
|
40987
41194
|
const character = text2[at];
|
|
40988
41195
|
if (character === '"')
|
|
@@ -40996,17 +41203,17 @@ function parse6(text2) {
|
|
|
40996
41203
|
if (object5) {
|
|
40997
41204
|
space();
|
|
40998
41205
|
const key = string();
|
|
40999
|
-
|
|
41206
|
+
need5(!keys2.has(key), "contains a duplicate JSON key");
|
|
41000
41207
|
keys2.add(key);
|
|
41001
41208
|
space();
|
|
41002
|
-
|
|
41209
|
+
need5(text2[at++] === ":", "contains invalid JSON");
|
|
41003
41210
|
entries.push([key, value(depth + 1)]);
|
|
41004
41211
|
} else
|
|
41005
41212
|
items.push(value(depth + 1));
|
|
41006
41213
|
space();
|
|
41007
41214
|
if (text2[at] === end)
|
|
41008
41215
|
break;
|
|
41009
|
-
|
|
41216
|
+
need5(text2[at++] === ",", "contains invalid JSON");
|
|
41010
41217
|
}
|
|
41011
41218
|
at++;
|
|
41012
41219
|
return object5 ? { kind: "object", entries } : { kind: "array", items };
|
|
@@ -41018,14 +41225,14 @@ function parse6(text2) {
|
|
|
41018
41225
|
}
|
|
41019
41226
|
numberPattern.lastIndex = at;
|
|
41020
41227
|
const number = numberPattern.exec(text2);
|
|
41021
|
-
|
|
41228
|
+
need5(number, "contains invalid JSON");
|
|
41022
41229
|
at += number[0].length;
|
|
41023
41230
|
return { kind: "number", value: number[0] };
|
|
41024
41231
|
}
|
|
41025
41232
|
const root2 = value(0);
|
|
41026
41233
|
space();
|
|
41027
|
-
|
|
41028
|
-
|
|
41234
|
+
need5(at === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
|
|
41235
|
+
need5(root2.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
|
|
41029
41236
|
return root2;
|
|
41030
41237
|
}
|
|
41031
41238
|
function exactKeys2(value, keys2) {
|
|
@@ -41033,7 +41240,7 @@ function exactKeys2(value, keys2) {
|
|
|
41033
41240
|
}
|
|
41034
41241
|
var field = (object5, key) => object5.entries.find(([name]) => name === key)?.[1];
|
|
41035
41242
|
function textField(value) {
|
|
41036
|
-
|
|
41243
|
+
need5(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
|
|
41037
41244
|
return value.value;
|
|
41038
41245
|
}
|
|
41039
41246
|
function normalizeRow(row, version = 1) {
|
|
@@ -41041,7 +41248,7 @@ function normalizeRow(row, version = 1) {
|
|
|
41041
41248
|
if (version !== 2 || !exactKeys2(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
|
|
41042
41249
|
return;
|
|
41043
41250
|
const autoUpdate = field(row, "autoUpdate");
|
|
41044
|
-
|
|
41251
|
+
need5(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
|
|
41045
41252
|
}
|
|
41046
41253
|
const source = field(row, "source");
|
|
41047
41254
|
if (source?.kind !== "object")
|
|
@@ -41057,34 +41264,34 @@ function normalizeRow(row, version = 1) {
|
|
|
41057
41264
|
absolutePath3(sourceLocation);
|
|
41058
41265
|
absolutePath3(textField(field(row, "installLocation")));
|
|
41059
41266
|
const updated = textField(field(row, "lastUpdated"));
|
|
41060
|
-
|
|
41267
|
+
need5(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
|
|
41061
41268
|
const millis = Date.parse(updated);
|
|
41062
|
-
|
|
41269
|
+
need5(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
|
|
41063
41270
|
row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
|
|
41064
41271
|
}
|
|
41065
41272
|
function captureClaudeMarketplaceRegistry(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
41066
41273
|
const value = parse6(readRegistry2(path, budget));
|
|
41067
41274
|
for (const [, row] of value.entries)
|
|
41068
41275
|
normalizeRow(row);
|
|
41069
|
-
const sha2562 =
|
|
41276
|
+
const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
41070
41277
|
return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
|
|
41071
41278
|
}
|
|
41072
41279
|
function captureClaudeMarketplaceRegistryV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
41073
41280
|
const value = parse6(readRegistry2(path, budget));
|
|
41074
41281
|
for (const [, row] of value.entries)
|
|
41075
41282
|
normalizeRow(row, 2);
|
|
41076
|
-
const sha2562 =
|
|
41283
|
+
const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
|
|
41077
41284
|
return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
|
|
41078
41285
|
}
|
|
41079
41286
|
|
|
41080
41287
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
41081
|
-
import { createHash as
|
|
41288
|
+
import { createHash as createHash16 } from "crypto";
|
|
41082
41289
|
|
|
41083
41290
|
// src/lib/codex-hook-trust-files.ts
|
|
41084
41291
|
import { closeSync as closeSync15, constants as constants11, fstatSync as fstatSync15, fsyncSync as fsyncSync3, lstatSync as lstatSync17, openSync as openSync15, readSync as readSync10, writeFileSync as writeFileSync3 } from "fs";
|
|
41085
|
-
import { createHash as
|
|
41292
|
+
import { createHash as createHash15 } from "crypto";
|
|
41086
41293
|
import { dirname as dirname13 } from "path";
|
|
41087
|
-
function
|
|
41294
|
+
function need6(value, code) {
|
|
41088
41295
|
if (!value)
|
|
41089
41296
|
throw new Error(`CODEX_HOOK_TRUST_${code}`);
|
|
41090
41297
|
}
|
|
@@ -41092,8 +41299,8 @@ var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs
|
|
|
41092
41299
|
function safeParents(file) {
|
|
41093
41300
|
for (let p = dirname13(file);; p = dirname13(p)) {
|
|
41094
41301
|
const s = lstatSync17(p);
|
|
41095
|
-
|
|
41096
|
-
|
|
41302
|
+
need6(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
|
|
41303
|
+
need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
|
|
41097
41304
|
if (dirname13(p) === p)
|
|
41098
41305
|
break;
|
|
41099
41306
|
}
|
|
@@ -41102,12 +41309,12 @@ function snapshot(file, privateFile = false, options = {}) {
|
|
|
41102
41309
|
const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
|
|
41103
41310
|
safeParents(file);
|
|
41104
41311
|
const initial = lstatSync17(file, { bigint: true });
|
|
41105
|
-
|
|
41106
|
-
|
|
41312
|
+
need6(initial.isFile() && initial.uid === BigInt(process.getuid()) && (initial.nlink === 1n || readOnlyPackage && initial.nlink > 1n) && (initial.mode & 0o022n) === 0n && (!privateFile || (initial.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
|
|
41313
|
+
need6(initial.size <= 8n * 1024n * 1024n, "FILE_BOUND");
|
|
41107
41314
|
const fd = openSync15(file, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
|
|
41108
41315
|
try {
|
|
41109
41316
|
const before = fstatSync15(fd, { bigint: true });
|
|
41110
|
-
|
|
41317
|
+
need6(sameStat(initial, before), "INPUT_CHANGED");
|
|
41111
41318
|
const bytes = Buffer.alloc(Number(before.size) + 1);
|
|
41112
41319
|
let length = 0;
|
|
41113
41320
|
while (length < bytes.length) {
|
|
@@ -41116,16 +41323,16 @@ function snapshot(file, privateFile = false, options = {}) {
|
|
|
41116
41323
|
break;
|
|
41117
41324
|
length += n2;
|
|
41118
41325
|
}
|
|
41119
|
-
|
|
41326
|
+
need6(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before, lstatSync17(file, { bigint: true })), "INPUT_CHANGED");
|
|
41120
41327
|
const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
41121
|
-
return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256:
|
|
41328
|
+
return { file, privateFile, readOnlyPackage, text: text2, bytes: content, stat: before, sha256: createHash15("sha256").update(content).digest("hex") };
|
|
41122
41329
|
} finally {
|
|
41123
41330
|
closeSync15(fd);
|
|
41124
41331
|
}
|
|
41125
41332
|
}
|
|
41126
41333
|
function unchanged2(before) {
|
|
41127
41334
|
const after = snapshot(before.file, before.privateFile, before.readOnlyPackage ? { readOnlyPackage: true } : {});
|
|
41128
|
-
|
|
41335
|
+
need6(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
|
|
41129
41336
|
}
|
|
41130
41337
|
|
|
41131
41338
|
// src/lib/codex-hook-additions-review.ts
|
|
@@ -41134,11 +41341,12 @@ var matchedEvents = { ...events, PreToolUse: ["preToolUse", "pre_tool_use"] };
|
|
|
41134
41341
|
var proofs = new WeakMap;
|
|
41135
41342
|
|
|
41136
41343
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
41137
|
-
var
|
|
41344
|
+
var sha3 = (text2) => createHash16("sha256").update(text2).digest("hex");
|
|
41345
|
+
var fields = [...CODEX_DISCOVERY_PROJECTION_FIELDS];
|
|
41138
41346
|
var proofs2 = new WeakMap;
|
|
41139
41347
|
function assertCodexHookDiscoveryRecovery(binding, witness) {
|
|
41140
41348
|
const proof = proofs2.get(witness);
|
|
41141
|
-
|
|
41349
|
+
need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha3(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
41142
41350
|
unchanged2(proof.before);
|
|
41143
41351
|
unchanged2(proof.current);
|
|
41144
41352
|
proof.recheckAdditions();
|
|
@@ -41147,12 +41355,12 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
|
|
|
41147
41355
|
if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
|
|
41148
41356
|
return false;
|
|
41149
41357
|
assertCodexHookDiscoveryRecovery(binding, witness);
|
|
41150
|
-
|
|
41358
|
+
need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
41151
41359
|
return true;
|
|
41152
41360
|
}
|
|
41153
41361
|
|
|
41154
41362
|
// src/lib/agent-discovery.ts
|
|
41155
|
-
var digest2 = (text2) =>
|
|
41363
|
+
var digest2 = (text2) => createHash17("sha256").update(text2).digest("hex");
|
|
41156
41364
|
function parseConfig(text2, path, toml = false) {
|
|
41157
41365
|
try {
|
|
41158
41366
|
const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
|
|
@@ -41184,14 +41392,26 @@ function read2(path, changes) {
|
|
|
41184
41392
|
throw new Error(`Unsupported or oversized native discovery input: ${path}`);
|
|
41185
41393
|
return readFileSync13(path, "utf8");
|
|
41186
41394
|
}
|
|
41395
|
+
function projectNativeDiscoveryFields(text2, format, fields2, path) {
|
|
41396
|
+
const object5 = format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, path, format === "toml");
|
|
41397
|
+
if (!object5 || typeof object5 !== "object" || Array.isArray(object5))
|
|
41398
|
+
throw new Error("Expected native discovery configuration object");
|
|
41399
|
+
return digest2(JSON.stringify(Object.fromEntries(fields2.map((field2) => [field2, object5[field2] ?? null]))));
|
|
41400
|
+
}
|
|
41401
|
+
function isSupersededCodexProjection(agent, configPath, source) {
|
|
41402
|
+
return agent === "codex" && source.path === configPath && source.format === "toml" && isDeepStrictEqual3(source.fields, [...CODEX_DISCOVERY_PROJECTION_FIELDS]);
|
|
41403
|
+
}
|
|
41404
|
+
function supersedesCodexProjection(sources, configPath) {
|
|
41405
|
+
return sources.some((source) => source.path === configPath && source.hashMode === "codex-settings-v2");
|
|
41406
|
+
}
|
|
41187
41407
|
function projected(source, changes, budget = discoveryByteBudget()) {
|
|
41188
|
-
if (source.hashMode === "codex-settings-v1") {
|
|
41408
|
+
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") {
|
|
41189
41409
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
41190
41410
|
throw new Error("Codex settings witnesses require exact typed metadata");
|
|
41191
|
-
const current = captureCodexSettings(source.path, budget).sha256;
|
|
41411
|
+
const current = (source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
|
|
41192
41412
|
if (current !== source.sha256)
|
|
41193
41413
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
41194
|
-
return changes?.has(source.path) ? hashCodexSettingsReplacement(changes.get(source.path), budget) : current;
|
|
41414
|
+
return changes?.has(source.path) ? (source.hashMode === "codex-settings-v2" ? hashCodexSettingsReplacementV2 : hashCodexSettingsReplacement)(changes.get(source.path), budget) : current;
|
|
41195
41415
|
}
|
|
41196
41416
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
|
|
41197
41417
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
@@ -41230,10 +41450,7 @@ function projected(source, changes, budget = discoveryByteBudget()) {
|
|
|
41230
41450
|
return null;
|
|
41231
41451
|
if (!source.format)
|
|
41232
41452
|
return digest2(text2);
|
|
41233
|
-
|
|
41234
|
-
if (!object5 || typeof object5 !== "object" || Array.isArray(object5))
|
|
41235
|
-
throw new Error("Expected native discovery configuration object");
|
|
41236
|
-
return digest2(JSON.stringify(Object.fromEntries((source.fields ?? []).map((field2) => [field2, object5[field2] ?? null]))));
|
|
41453
|
+
return projectNativeDiscoveryFields(text2, source.format, source.fields ?? [], source.path);
|
|
41237
41454
|
}
|
|
41238
41455
|
function verifyAgentDiscovery(binding, codexRecovery) {
|
|
41239
41456
|
if (codexRecovery)
|
|
@@ -41261,7 +41478,7 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
41261
41478
|
safe4(root2);
|
|
41262
41479
|
}
|
|
41263
41480
|
function assertMarketplaceBinding(binding, source) {
|
|
41264
|
-
if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" || basename7(source.path) !== "config.toml"))
|
|
41481
|
+
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") && (binding.agent !== "codex" || binding.method !== "reviewed" || basename7(source.path) !== "config.toml"))
|
|
41265
41482
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
41266
41483
|
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" || basename7(source.path) !== "settings.json"))
|
|
41267
41484
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
@@ -41290,8 +41507,8 @@ function captureDiscoveryPathSources(paths) {
|
|
|
41290
41507
|
const budget = discoveryByteBudget();
|
|
41291
41508
|
return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget) }));
|
|
41292
41509
|
}
|
|
41293
|
-
function assertProjectDiscovery(agent, directories, home,
|
|
41294
|
-
const homeConfigPath =
|
|
41510
|
+
function assertProjectDiscovery(agent, directories, home, canonical6 = resolve14, reviewed) {
|
|
41511
|
+
const homeConfigPath = canonical6(agentDiscoveryConfigPath(home, agent));
|
|
41295
41512
|
for (const directory of directories) {
|
|
41296
41513
|
const isHome = resolve14(directory) === resolve14(home);
|
|
41297
41514
|
if (agent === "hermes") {
|
|
@@ -41302,7 +41519,7 @@ function assertProjectDiscovery(agent, directories, home, canonical5 = resolve14
|
|
|
41302
41519
|
continue;
|
|
41303
41520
|
const paths = agent === "claude" ? [...isHome ? [] : [".claude/settings.json"], ".claude/settings.local.json"] : agent === "codex" ? [".codex/config.toml"] : agent === "gemini" ? [".gemini/settings.json"] : agent === "opencode" ? ["opencode.json", "opencode.jsonc", ".opencode/opencode.json", ".opencode/opencode.jsonc"] : [".cursor/hooks.json"];
|
|
41304
41521
|
for (const suffix of paths) {
|
|
41305
|
-
const path =
|
|
41522
|
+
const path = canonical6(join21(directory, suffix)), raw = read2(path);
|
|
41306
41523
|
if (raw === null)
|
|
41307
41524
|
continue;
|
|
41308
41525
|
const isRootAliasedHomeConfig = agent === "claude" && suffix === ".claude/settings.json" || agent === "codex" && suffix === ".codex/config.toml";
|
|
@@ -41318,14 +41535,14 @@ function assertProjectDiscovery(agent, directories, home, canonical5 = resolve14
|
|
|
41318
41535
|
const managed = reviewed.sources.flatMap((source) => source.hashMode === "claude-plugin-registry" ? source.managedPlugins ?? [] : []);
|
|
41319
41536
|
if (exact && projected(exact) === exact.sha256 && managed.length) {
|
|
41320
41537
|
const bindings = managed.map((item) => readPluginBinding(item.storeRoot, item.bindingId));
|
|
41321
|
-
admittedPlugins = Object.entries(config.enabledPlugins).every(([id2, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id2 && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath ===
|
|
41538
|
+
admittedPlugins = Object.entries(config.enabledPlugins).every(([id2, enabled]) => typeof enabled === "boolean" && bindings.some((binding) => binding.target.pluginId === id2 && binding.target.registrations.some((scope) => scope.scope === "project" && scope.projectPath === canonical6(directory))));
|
|
41322
41539
|
}
|
|
41323
41540
|
}
|
|
41324
41541
|
if (keys2.some((key) => config[key] !== undefined && !(key === "enabledPlugins" && admittedPlugins)) || config.disableAllHooks === true || config.disableBundledSkills === false || config.hooksConfig?.enabled === false || config.permission?.skill !== undefined || config.permissions?.deny?.some((rule) => typeof rule === "string" && /^Skill(?:\(|$)/.test(rule)))
|
|
41325
41542
|
throw new Error(`NATIVE_SKILL_DRIFT: higher-precedence project skill or hook configuration requires review: ${path}`);
|
|
41326
41543
|
}
|
|
41327
41544
|
if (agent === "claude") {
|
|
41328
|
-
const commands =
|
|
41545
|
+
const commands = canonical6(join21(directory, ".claude/commands"));
|
|
41329
41546
|
safe4(commands);
|
|
41330
41547
|
if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
41331
41548
|
throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
|
|
@@ -41336,10 +41553,10 @@ function agentDiscoveryConfigPath(home, agent) {
|
|
|
41336
41553
|
return join21(home, agent === "hermes" ? ".hermes/config.yaml" : agent === "opencode" ? ".config/opencode/opencode.json" : `.${agent}/${agent === "codex" ? "config.toml" : agent === "cursor" ? "hooks.json" : "settings.json"}`);
|
|
41337
41554
|
}
|
|
41338
41555
|
function resolveAgentDiscovery(options) {
|
|
41339
|
-
const
|
|
41556
|
+
const canonical6 = options.canonical ?? resolve14, home = resolve14(options.home), agent = options.agent;
|
|
41340
41557
|
const sources = [], roots = new Set, builtinNames = [];
|
|
41341
|
-
const witness = (path, format,
|
|
41342
|
-
const source = { path:
|
|
41558
|
+
const witness = (path, format, fields2) => {
|
|
41559
|
+
const source = { path: canonical6(path), sha256: null, ...format ? { format, fields: fields2 } : {} };
|
|
41343
41560
|
source.sha256 = projected(source);
|
|
41344
41561
|
sources.push(source);
|
|
41345
41562
|
return read2(source.path);
|
|
@@ -41347,7 +41564,7 @@ function resolveAgentDiscovery(options) {
|
|
|
41347
41564
|
if (agent === "hermes")
|
|
41348
41565
|
assertHermesEnvironment(home);
|
|
41349
41566
|
const configPath = agentDiscoveryConfigPath(home, agent);
|
|
41350
|
-
const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [
|
|
41567
|
+
const configText = witness(configPath, agent === "hermes" ? "yaml" : agent === "codex" ? "toml" : "json", agent === "hermes" ? ["skills", "plugins", "hooks"] : agent === "claude" ? ["enabledPlugins", "extraKnownMarketplaces"] : agent === "codex" ? [...CODEX_DISCOVERY_PROJECTION_FIELDS] : agent === "gemini" ? ["skills", "extensions", "security"] : agent === "opencode" ? ["plugin", "skills"] : ["version"]);
|
|
41351
41568
|
const config = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
|
|
41352
41569
|
const unresolved = (detail) => {
|
|
41353
41570
|
throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
|
|
@@ -41406,11 +41623,12 @@ function resolveAgentDiscovery(options) {
|
|
|
41406
41623
|
if (retained.agent !== agent || retained.method !== "reviewed")
|
|
41407
41624
|
unresolved("invalid retained review");
|
|
41408
41625
|
verifyAgentDiscovery(retained);
|
|
41409
|
-
if (!retained.sources.some((source) => source.path ===
|
|
41626
|
+
if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
|
|
41410
41627
|
unresolved("retained review is missing the full agent configuration source");
|
|
41411
|
-
if (retained.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "codex-settings-v1")) && source.path !==
|
|
41628
|
+
if (retained.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2"))) && source.path !== canonical6(configPath)))
|
|
41412
41629
|
unresolved("retained settings witness names another configuration source");
|
|
41413
|
-
|
|
41630
|
+
const covered = supersedesCodexProjection(retained.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
|
|
41631
|
+
if (covered.some((source) => !retained.sources.some((saved) => isDeepStrictEqual3(saved, source))) || [...roots].some((root2) => !retained.roots.includes(root2)) || agent === "gemini" && JSON.stringify(retained.builtinNames) !== JSON.stringify(builtinNames))
|
|
41414
41632
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
41415
41633
|
return retained;
|
|
41416
41634
|
}
|
|
@@ -41424,14 +41642,15 @@ function resolveAgentDiscovery(options) {
|
|
|
41424
41642
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
41425
41643
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
41426
41644
|
verifyAgentDiscovery(supplied);
|
|
41427
|
-
if (review.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || source.hashMode === "codex-settings-v1")) && source.path !==
|
|
41645
|
+
if (review.sources.some((source) => (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || (source.hashMode === "claude-settings-v3" || (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2"))) && source.path !== canonical6(configPath)))
|
|
41428
41646
|
throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
|
|
41429
|
-
if (!review.sources.some((source) => source.path ===
|
|
41647
|
+
if (!review.sources.some((source) => source.path === canonical6(configPath)))
|
|
41430
41648
|
throw new Error("Discovery review must include the agent configuration source");
|
|
41431
|
-
|
|
41649
|
+
const reviewedSources = supersedesCodexProjection(review.sources, canonical6(configPath)) ? sources.filter((source) => !isSupersededCodexProjection(agent, canonical6(configPath), source)) : sources;
|
|
41650
|
+
return { ...supplied, roots: [...new Set([...roots, ...supplied.roots])].sort(), sources: [...reviewedSources, ...review.sources], ...agent === "gemini" ? { builtinNames } : {} };
|
|
41432
41651
|
}
|
|
41433
41652
|
function plugin(root2) {
|
|
41434
|
-
root2 =
|
|
41653
|
+
root2 = canonical6(root2);
|
|
41435
41654
|
safe4(root2);
|
|
41436
41655
|
const manifestPath = join21(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
41437
41656
|
const raw = witness(manifestPath);
|
|
@@ -41463,7 +41682,7 @@ function resolveAgentDiscovery(options) {
|
|
|
41463
41682
|
if (agent === "claude") {
|
|
41464
41683
|
const registrations = witness(join21(home, ".claude/plugins/installed_plugins.json"));
|
|
41465
41684
|
const installed = registrations === null ? {} : parseConfig(registrations, join21(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
41466
|
-
const commands =
|
|
41685
|
+
const commands = canonical6(join21(home, ".claude/commands"));
|
|
41467
41686
|
safe4(commands);
|
|
41468
41687
|
if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
41469
41688
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
@@ -41537,7 +41756,7 @@ function resolveAgentDiscovery(options) {
|
|
|
41537
41756
|
roots.add(join21(root2, "skills"));
|
|
41538
41757
|
}
|
|
41539
41758
|
}
|
|
41540
|
-
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join21(home, ".hermes/plugins"), join21(home, ".hermes/hermes-agent")].map((path) =>
|
|
41759
|
+
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join21(home, ".hermes/plugins"), join21(home, ".hermes/hermes-agent")].map((path) => canonical6(path))) } : {} };
|
|
41541
41760
|
}
|
|
41542
41761
|
|
|
41543
41762
|
// src/lib/agent-adapters.ts
|
|
@@ -41716,10 +41935,10 @@ function inlineRowsAsTables(value, newline) {
|
|
|
41716
41935
|
for (const row of rows) {
|
|
41717
41936
|
if (!row.startsWith("{") || !row.endsWith("}"))
|
|
41718
41937
|
return null;
|
|
41719
|
-
const
|
|
41720
|
-
if (!
|
|
41938
|
+
const fields2 = splitTopLevel(row.slice(1, -1), ",");
|
|
41939
|
+
if (!fields2)
|
|
41721
41940
|
return null;
|
|
41722
|
-
const lines =
|
|
41941
|
+
const lines = fields2.map((field2) => field2.trim()).filter(Boolean);
|
|
41723
41942
|
if (lines.some((line) => !/^(?:path|name|enabled)\s*=/.test(line)))
|
|
41724
41943
|
return null;
|
|
41725
41944
|
const keys2 = lines.map((line) => line.slice(0, line.indexOf("=")).trim());
|
|
@@ -41875,7 +42094,7 @@ function disableCodexBundledSkills(text2) {
|
|
|
41875
42094
|
}
|
|
41876
42095
|
|
|
41877
42096
|
// src/lib/agent-integration.ts
|
|
41878
|
-
var
|
|
42097
|
+
var sha4 = (data) => createHash18("sha256").update(data).digest("hex");
|
|
41879
42098
|
var ROOTS = NATIVE_SKILL_ROOTS;
|
|
41880
42099
|
function assertSafePath(path) {
|
|
41881
42100
|
let cursor = resolve15(path);
|
|
@@ -41982,7 +42201,7 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
|
|
|
41982
42201
|
}
|
|
41983
42202
|
}
|
|
41984
42203
|
function treeHash(root2) {
|
|
41985
|
-
const hash2 =
|
|
42204
|
+
const hash2 = createHash18("sha256");
|
|
41986
42205
|
let bytes = 0, files = 0;
|
|
41987
42206
|
function visit2(path) {
|
|
41988
42207
|
const stat2 = lstatSync19(path);
|
|
@@ -42367,7 +42586,7 @@ function planAgentIntegration(options) {
|
|
|
42367
42586
|
const observedNativeSources = [];
|
|
42368
42587
|
const codexPluginSkills = options.codexNativeCatalog ? reviewCodexPluginSkillControls(options.codexNativeCatalog, nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor).map((entry) => join22(entry.path, "SKILL.md")), canonicalAgentPath(join22(home, ".codex/plugins/cache"), aliases), resolve15(options.projectDir ?? home), (path) => {
|
|
42369
42588
|
const bytes = readNativeBytes(path, 1024 * 1024);
|
|
42370
|
-
observedNativeSources.push({ path, sha256:
|
|
42589
|
+
observedNativeSources.push({ path, sha256: sha4(bytes) });
|
|
42371
42590
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
42372
42591
|
}, codexConfig.skills?.config ?? []) : policy.bridge?.codexPluginSkills ?? [];
|
|
42373
42592
|
const changes = [];
|
|
@@ -42395,7 +42614,7 @@ function planAgentIntegration(options) {
|
|
|
42395
42614
|
throw new Error("Refusing to overwrite an unrecognized Hermes supervisor");
|
|
42396
42615
|
if (supervisorBefore !== supervisorAfter)
|
|
42397
42616
|
changes.push({ path: supervisorPath, before: supervisorBefore, after: supervisorAfter });
|
|
42398
|
-
const supervisor = { path: supervisorPath, runtime: process.execPath, sha256:
|
|
42617
|
+
const supervisor = { path: supervisorPath, runtime: process.execPath, sha256: sha4(supervisorAfter) };
|
|
42399
42618
|
const after2 = configureHermesHooks(before, supervisor, previous);
|
|
42400
42619
|
if (before !== after2)
|
|
42401
42620
|
changes.push({ path, before, after: after2 });
|
|
@@ -42442,12 +42661,12 @@ function planAgentIntegration(options) {
|
|
|
42442
42661
|
agents: [...new Set([...priorAgents, ...options.agents])].sort(),
|
|
42443
42662
|
home: resolve15(home),
|
|
42444
42663
|
includeVendor: true,
|
|
42445
|
-
...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join22(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256:
|
|
42664
|
+
...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join22(dataDir2, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha4(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
|
|
42446
42665
|
commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
|
|
42447
42666
|
profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
|
|
42448
42667
|
disabledBuiltins: options.agents.includes("codex") ? nativeSkills.filter((entry) => entry.agent === "codex" && entry.vendor && entry.path.startsWith(canonicalAgentPath(join22(home, ".codex", "skills", ".system"), aliases) + sep5)).map((entry) => ({ path: entry.path, hash: entry.hash })) : policy.bridge?.disabledBuiltins ?? [],
|
|
42449
42668
|
rootAliases: aliases,
|
|
42450
|
-
...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256:
|
|
42669
|
+
...codexPluginSkills.length ? { codexPluginSkills, codexPluginSkillReview: options.codexNativeCatalog ? { version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, catalogSha256: sha4(JSON.stringify({ version: options.codexNativeCatalog.version, cwd: options.codexNativeCatalog.cwd, skills: projectCodexNativeSkillCatalog({ data: [{ cwd: options.codexNativeCatalog.cwd, errors: [], skills: options.codexNativeCatalog.skills }] }, options.codexNativeCatalog.cwd), ...options.codexNativeCatalog.plugins === undefined ? {} : { plugins: projectCodexInstalledPluginEntries(options.codexNativeCatalog.plugins) } })), configSha256: changes.find((change) => change.path === canonicalAgentPath(join22(home, ".codex/config.toml"), aliases))?.before === null ? null : sha4(readOptional(canonicalAgentPath(join22(home, ".codex/config.toml"), aliases)) ?? "") } : policy.bridge?.codexPluginSkillReview } : {},
|
|
42451
42670
|
discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
|
|
42452
42671
|
} };
|
|
42453
42672
|
const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
|
|
@@ -42463,12 +42682,12 @@ function planClaudePreToolUseHookUpdate(options) {
|
|
|
42463
42682
|
return planClaudeHookEventsUpdate({ ...options, events: ["PreToolUse"] });
|
|
42464
42683
|
}
|
|
42465
42684
|
function claudeSettingsConsumers(home, path, discoveries, aliases) {
|
|
42466
|
-
const
|
|
42685
|
+
const canonical6 = (value) => canonicalAgentPath(value, aliases);
|
|
42467
42686
|
const containsSettings = (root2) => {
|
|
42468
|
-
const distance = relative4(
|
|
42687
|
+
const distance = relative4(canonical6(root2), path);
|
|
42469
42688
|
return distance === "" || distance !== ".." && !distance.startsWith(`..${sep5}`) && !isAbsolute17(distance);
|
|
42470
42689
|
};
|
|
42471
|
-
return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" ||
|
|
42690
|
+
return discoveries.filter((binding) => binding.agent === "claude" || binding.agent === "opencode" || canonical6(join22(home, AGENT_ADAPTERS[binding.agent].config)) === path || binding.sources.some((source) => canonical6(source.path) === path) || binding.roots.some(containsSettings) || binding.directories?.some((directory) => containsSettings(directory.path))).map((binding) => binding.agent);
|
|
42472
42691
|
}
|
|
42473
42692
|
function verifyCoordinatedDiscovery(binding, home, aliases) {
|
|
42474
42693
|
try {
|
|
@@ -42500,7 +42719,7 @@ function planClaudeHookEventsUpdate(options) {
|
|
|
42500
42719
|
const path = canonicalAgentPath(join22(home, ".claude", "settings.json"), aliases);
|
|
42501
42720
|
assertSafePath(path);
|
|
42502
42721
|
const before = lstatSync19(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
|
|
42503
|
-
if ((before === null ? "absent" :
|
|
42722
|
+
if ((before === null ? "absent" : sha4(before)) !== options.expectedSettingsSha256)
|
|
42504
42723
|
throw new Error("Claude settings preimage changed");
|
|
42505
42724
|
assertClaudeHookEventsReplacement(before, options.replacement, options.events);
|
|
42506
42725
|
const agents = bridge.agents;
|
|
@@ -42566,7 +42785,7 @@ function atomicWrite2(path, content) {
|
|
|
42566
42785
|
function planAgentSettingsWitnessUpgrade(options) {
|
|
42567
42786
|
const home = resolve15(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
|
|
42568
42787
|
const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
|
|
42569
|
-
if (!snapshot2 ||
|
|
42788
|
+
if (!snapshot2 || sha4(snapshot2.text) !== options.expectedPolicySha256)
|
|
42570
42789
|
throw new Error("Managed policy preimage changed");
|
|
42571
42790
|
const policy = snapshot2.value, aliases = policy.bridge?.rootAliases ?? [];
|
|
42572
42791
|
recheckRootAliases(aliases);
|
|
@@ -42575,7 +42794,7 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
42575
42794
|
throw new Error("Settings witness upgrade requires an existing reviewed native binding");
|
|
42576
42795
|
const configPath = canonicalAgentPath(join22(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
|
|
42577
42796
|
const settings = readOptional(configPath);
|
|
42578
|
-
if (settings === null ||
|
|
42797
|
+
if (settings === null || sha4(settings) !== options.expectedSettingsSha256)
|
|
42579
42798
|
throw new Error("Native settings preimage changed");
|
|
42580
42799
|
const sources = binding.sources.filter((source) => source.path === configPath && source.format === undefined && source.fields === undefined);
|
|
42581
42800
|
if (sources.length !== 1)
|
|
@@ -42583,15 +42802,40 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
42583
42802
|
const previous = sources[0];
|
|
42584
42803
|
if (typeof previous.sha256 !== "string")
|
|
42585
42804
|
throw new Error("Settings witness upgrade requires a preserved settings preimage");
|
|
42805
|
+
const replaced = [previous];
|
|
42806
|
+
if (options.agent === "codex") {
|
|
42807
|
+
if (previous.hashMode !== undefined && previous.hashMode !== "bytes" && previous.hashMode !== "codex-settings-v1")
|
|
42808
|
+
throw new Error("Codex settings witness upgrade requires a preserved raw or codex-settings-v1 configuration witness");
|
|
42809
|
+
const preimage = readCodexSettingsPreimage(options.reviewedPreimage);
|
|
42810
|
+
for (const source of binding.sources) {
|
|
42811
|
+
if (source === previous || source.path !== configPath)
|
|
42812
|
+
continue;
|
|
42813
|
+
const fields2 = source.fields;
|
|
42814
|
+
if (source.hashMode !== undefined || source.format !== "toml" || !Array.isArray(fields2) || !isDeepStrictEqual5(fields2, [...CODEX_DISCOVERY_PROJECTION_FIELDS]) || typeof source.sha256 !== "string")
|
|
42815
|
+
throw new Error("Codex settings witness upgrade found an unrecognized configuration witness");
|
|
42816
|
+
if (projectNativeDiscoveryFields(preimage, "toml", fields2, configPath) !== source.sha256)
|
|
42817
|
+
throw new Error("Reviewed preimage does not explain the Codex discovery projection witness");
|
|
42818
|
+
replaced.push(source);
|
|
42819
|
+
}
|
|
42820
|
+
}
|
|
42586
42821
|
const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
|
|
42587
|
-
const
|
|
42822
|
+
const rebound = [];
|
|
42823
|
+
for (const source of binding.sources) {
|
|
42824
|
+
if (!replaced.includes(source)) {
|
|
42825
|
+
rebound.push(source);
|
|
42826
|
+
continue;
|
|
42827
|
+
}
|
|
42828
|
+
if (source === replaced[0])
|
|
42829
|
+
rebound.push(next);
|
|
42830
|
+
}
|
|
42831
|
+
const replacement = { ...binding, sources: rebound };
|
|
42588
42832
|
verifyAgentDiscovery(replacement);
|
|
42589
42833
|
const after = serializeManagedSkillPolicy({ ...policy, bridge: { ...policy.bridge, discovery: { ...policy.bridge.discovery, [options.agent]: replacement } } });
|
|
42590
|
-
return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join22(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join22(dataDir2, "agent-policy.json"), before: snapshot2.text }, observedSettings: { path: configPath, before: settings }, discoveryBefore: [replacement], discoveryAfter: [replacement], rootAliases: aliases, managedAgentChecks: { home, agents: [options.agent] }, settingsWitnessUpgrade: { agent: options.agent, path: configPath, fromHashMode: previous.hashMode ?? "bytes", fromSha256: previous.sha256, toHashMode: next.hashMode, toSha256: next.sha256, reviewedPreimage: options.reviewedPreimage, currentSettingsSha256: options.expectedSettingsSha256 } };
|
|
42834
|
+
return { dataDir: dataDir2, profileId: policy.profileId, changes: [{ path: join22(dataDir2, "agent-policy.json"), before: snapshot2.text, after }], nativeSkills: [], observedPolicy: { path: join22(dataDir2, "agent-policy.json"), before: snapshot2.text }, observedSettings: { path: configPath, before: settings }, discoveryBefore: [replacement], discoveryAfter: [replacement], rootAliases: aliases, managedAgentChecks: { home, agents: [options.agent] }, settingsWitnessUpgrade: { agent: options.agent, path: configPath, fromHashMode: previous.hashMode ?? "bytes", fromSha256: previous.sha256, toHashMode: next.hashMode, toSha256: next.sha256, reviewedPreimage: options.reviewedPreimage, currentSettingsSha256: options.expectedSettingsSha256, replacedWitnesses: replaced.map((source) => ({ hashMode: source.hashMode ?? "bytes", sha256: source.sha256 })) } };
|
|
42591
42835
|
}
|
|
42592
42836
|
function applyAgentIntegration(plan) {
|
|
42593
42837
|
for (const source of plan.observedNativeSources ?? [])
|
|
42594
|
-
if (
|
|
42838
|
+
if (sha4(readNativeBytes(source.path, 1024 * 1024)) !== source.sha256)
|
|
42595
42839
|
throw new Error("Native identity source changed after planning");
|
|
42596
42840
|
if (plan.observedSettings && readOptional(plan.observedSettings.path) !== plan.observedSettings.before)
|
|
42597
42841
|
throw new Error("Native settings changed after witness planning");
|
|
@@ -42611,7 +42855,7 @@ function applyAgentIntegration(plan) {
|
|
|
42611
42855
|
const upgrade = plan.settingsWitnessUpgrade;
|
|
42612
42856
|
if (!plan.managedAgentChecks || !plan.observedPolicy?.before)
|
|
42613
42857
|
throw new Error("Invalid settings witness upgrade plan");
|
|
42614
|
-
const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256:
|
|
42858
|
+
const verified = planAgentSettingsWitnessUpgrade({ agent: upgrade.agent, reviewedPreimage: upgrade.reviewedPreimage, home: plan.managedAgentChecks.home, dataDir: plan.dataDir, expectedPolicySha256: sha4(plan.observedPolicy.before), expectedSettingsSha256: upgrade.currentSettingsSha256 });
|
|
42615
42859
|
if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.settingsWitnessUpgrade) !== JSON.stringify(upgrade))
|
|
42616
42860
|
throw new Error("Settings witness upgrade plan changed");
|
|
42617
42861
|
provenDiscovery = verified.discoveryBefore[0];
|
|
@@ -42639,7 +42883,7 @@ function applyAgentIntegration(plan) {
|
|
|
42639
42883
|
chmodSync(backupRoot, 448);
|
|
42640
42884
|
for (const [index, change] of plan.changes.entries())
|
|
42641
42885
|
if (change.before !== null) {
|
|
42642
|
-
const backup = join22(backupRoot, `${index}-${
|
|
42886
|
+
const backup = join22(backupRoot, `${index}-${sha4(change.path).slice(0, 12)}.backup`);
|
|
42643
42887
|
writeFileSync4(backup, change.before, { mode: 384, flag: "wx" });
|
|
42644
42888
|
if (readFileSync14(backup, "utf8") !== change.before)
|
|
42645
42889
|
throw new Error("Native configuration preservation readback failed");
|
|
@@ -42658,7 +42902,7 @@ function applyAgentIntegration(plan) {
|
|
|
42658
42902
|
}
|
|
42659
42903
|
recheckRootAliases(aliases);
|
|
42660
42904
|
for (const source of plan.observedNativeSources ?? [])
|
|
42661
|
-
if (
|
|
42905
|
+
if (sha4(readNativeBytes(source.path, 1024 * 1024)) !== source.sha256)
|
|
42662
42906
|
throw new Error("Native identity source changed during application");
|
|
42663
42907
|
if (plan.observedSettings && readOptional(plan.observedSettings.path) !== plan.observedSettings.before)
|
|
42664
42908
|
throw new Error("Native settings changed during witness application");
|
|
@@ -42670,7 +42914,7 @@ function applyAgentIntegration(plan) {
|
|
|
42670
42914
|
}
|
|
42671
42915
|
for (const agent of plan.managedAgentChecks?.agents ?? [])
|
|
42672
42916
|
assertManagedAgentBridge(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home });
|
|
42673
|
-
atomicWrite2(join22(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null :
|
|
42917
|
+
atomicWrite2(join22(backupRoot, "receipt.json"), JSON.stringify({ version: 1, changes: written.map((change) => ({ path: change.path, beforeHash: change.before === null ? null : sha4(change.before), afterHash: sha4(change.after) })), backups, ...aliases.length ? { rootAliases: aliases } : {} }) + `
|
|
42674
42918
|
`);
|
|
42675
42919
|
} catch (error) {
|
|
42676
42920
|
for (const change of written.reverse()) {
|
|
@@ -42749,8 +42993,8 @@ function archiveNativeSkills(inventory, options) {
|
|
|
42749
42993
|
const operationId = randomUUID3(), archiveRoot = join22(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join22(archiveRoot, "receipt.json");
|
|
42750
42994
|
const entries = selected.map((entry, index) => ({
|
|
42751
42995
|
source: entry.vendor ? join22(entry.path, "SKILL.md") : entry.path,
|
|
42752
|
-
archive: join22(archiveRoot, `${index}-${
|
|
42753
|
-
hash: entry.vendor ?
|
|
42996
|
+
archive: join22(archiveRoot, `${index}-${sha4(entry.path).slice(0, 12)}`),
|
|
42997
|
+
hash: entry.vendor ? sha4(readNativeBytes(join22(entry.path, "SKILL.md"))) : entry.hash,
|
|
42754
42998
|
...entry.vendor ? { discoveryOnly: true } : {},
|
|
42755
42999
|
status: "planned"
|
|
42756
43000
|
}));
|
|
@@ -42761,7 +43005,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
42761
43005
|
const stat2 = lstatSync19(entry.archive);
|
|
42762
43006
|
if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
|
|
42763
43007
|
throw new Error("Archive type changed");
|
|
42764
|
-
if ((entry.discoveryOnly ?
|
|
43008
|
+
if ((entry.discoveryOnly ? sha4(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
|
|
42765
43009
|
throw new Error("Archive bytes changed");
|
|
42766
43010
|
};
|
|
42767
43011
|
assertSafePath(archiveRoot);
|
|
@@ -42881,7 +43125,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
42881
43125
|
throw new Error("NATIVE_SKILL_DRIFT: the hook selection profile differs from its managed binding; restart the native client after reviewing skills hook install");
|
|
42882
43126
|
if (agent === "hermes") {
|
|
42883
43127
|
const supervisor = binding.supervisors?.hermes;
|
|
42884
|
-
if (supervisor?.path !== join22(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !==
|
|
43128
|
+
if (supervisor?.path !== join22(dataDir2, "agent-hooks", "hermes.js") || supervisor?.sha256 !== sha4(renderHermesSupervisor(command, profile)))
|
|
42885
43129
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
|
|
42886
43130
|
assertHermesProtection(home, config, command, profile, supervisor);
|
|
42887
43131
|
} else if (agent === "opencode") {
|
|
@@ -42979,13 +43223,13 @@ import {
|
|
|
42979
43223
|
statSync as statSync9,
|
|
42980
43224
|
writeFileSync as writeFileSync6
|
|
42981
43225
|
} from "fs";
|
|
42982
|
-
import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute18, join as join26, normalize as
|
|
43226
|
+
import { basename as basename10, dirname as dirname18, isAbsolute as isAbsolute18, join as join26, normalize as normalize4, relative as relative6, resolve as resolve17, sep as sep8 } from "path";
|
|
42983
43227
|
|
|
42984
43228
|
// src/lib/registry-data/index.ts
|
|
42985
43229
|
var SKILLS = [];
|
|
42986
43230
|
|
|
42987
43231
|
// src/lib/skill-hash.ts
|
|
42988
|
-
import { createHash as
|
|
43232
|
+
import { createHash as createHash19 } from "crypto";
|
|
42989
43233
|
import { existsSync as existsSync7, readdirSync as readdirSync9, readFileSync as readFileSync15, statSync as statSync7 } from "fs";
|
|
42990
43234
|
import { join as join23, sep as sep6 } from "path";
|
|
42991
43235
|
var CONTENT_HASH_ALGORITHM = "sha256";
|
|
@@ -43109,13 +43353,13 @@ function* bundleHashParts(files) {
|
|
|
43109
43353
|
yield new TextEncoder().encode("\x00");
|
|
43110
43354
|
}
|
|
43111
43355
|
function hashBundleFiles(files) {
|
|
43112
|
-
const hash2 =
|
|
43356
|
+
const hash2 = createHash19(CONTENT_HASH_ALGORITHM);
|
|
43113
43357
|
for (const part of bundleHashParts(files))
|
|
43114
43358
|
hash2.update(part);
|
|
43115
43359
|
return hash2.digest("hex");
|
|
43116
43360
|
}
|
|
43117
43361
|
async function hashBundleFilesCooperatively(files, check) {
|
|
43118
|
-
const hash2 =
|
|
43362
|
+
const hash2 = createHash19(CONTENT_HASH_ALGORITHM);
|
|
43119
43363
|
let bytesSinceYield = 0;
|
|
43120
43364
|
for (const part of bundleHashParts(files)) {
|
|
43121
43365
|
for (let offset = 0;offset < part.byteLength; offset += 64 * 1024) {
|
|
@@ -43373,7 +43617,7 @@ var MAX_RUNTIME_TIMEOUT_SECONDS = 900;
|
|
|
43373
43617
|
function add2(target, code, message) {
|
|
43374
43618
|
target.push({ code, message });
|
|
43375
43619
|
}
|
|
43376
|
-
function
|
|
43620
|
+
function isRecord2(value) {
|
|
43377
43621
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
43378
43622
|
}
|
|
43379
43623
|
function isNonEmptyString(value) {
|
|
@@ -43401,7 +43645,7 @@ function validatePortableManifestContract(manifest, options = {}) {
|
|
|
43401
43645
|
}
|
|
43402
43646
|
validateRuntimeContract(manifest, issues, options.strict === true);
|
|
43403
43647
|
const provenance = manifest.provenance;
|
|
43404
|
-
if (provenance && !
|
|
43648
|
+
if (provenance && !isRecord2(provenance)) {
|
|
43405
43649
|
add2(issues, "contract.provenance_invalid", "provenance must be an object");
|
|
43406
43650
|
} else {
|
|
43407
43651
|
const sourceCommit = provenance?.source_commit;
|
|
@@ -43434,7 +43678,7 @@ function validateRuntimeContract(manifest, issues, strict) {
|
|
|
43434
43678
|
}
|
|
43435
43679
|
return;
|
|
43436
43680
|
}
|
|
43437
|
-
if (!
|
|
43681
|
+
if (!isRecord2(runtime)) {
|
|
43438
43682
|
add2(issues, "contract.runtime_invalid", "runtime must be an object");
|
|
43439
43683
|
return;
|
|
43440
43684
|
}
|
|
@@ -43721,7 +43965,7 @@ function readExistingSkillJson(skillPath) {
|
|
|
43721
43965
|
return {};
|
|
43722
43966
|
try {
|
|
43723
43967
|
const parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
43724
|
-
return
|
|
43968
|
+
return isRecord3(parsed) ? parsed : {};
|
|
43725
43969
|
} catch {
|
|
43726
43970
|
return {};
|
|
43727
43971
|
}
|
|
@@ -43777,7 +44021,7 @@ function ensurePackageJson(skillPath, manifest) {
|
|
|
43777
44021
|
}
|
|
43778
44022
|
const existing = readJsonObject(pkgPath);
|
|
43779
44023
|
const bin = {};
|
|
43780
|
-
if (
|
|
44024
|
+
if (isRecord3(existing.bin)) {
|
|
43781
44025
|
for (const [name, value] of Object.entries(existing.bin)) {
|
|
43782
44026
|
if (typeof value === "string" && value.trim())
|
|
43783
44027
|
bin[normalizePortableSkillName(name)] = value.replace(/^\.\//, "");
|
|
@@ -43788,7 +44032,7 @@ function ensurePackageJson(skillPath, manifest) {
|
|
|
43788
44032
|
bin[manifest.name] = binEntry.replace(/^\.\//, "");
|
|
43789
44033
|
}
|
|
43790
44034
|
bin[commandName] = entry;
|
|
43791
|
-
const scripts =
|
|
44035
|
+
const scripts = isRecord3(existing.scripts) ? { ...existing.scripts } : {};
|
|
43792
44036
|
if (!stringValue(scripts.dev))
|
|
43793
44037
|
scripts.dev = `bun run ${entry}`;
|
|
43794
44038
|
writeFileSync5(pkgPath, `${JSON.stringify({
|
|
@@ -44009,7 +44253,7 @@ function parseManifestCommands(value) {
|
|
|
44009
44253
|
if (!Array.isArray(raw))
|
|
44010
44254
|
return;
|
|
44011
44255
|
const commands = raw.map((item) => {
|
|
44012
|
-
if (!
|
|
44256
|
+
if (!isRecord3(item))
|
|
44013
44257
|
return null;
|
|
44014
44258
|
const name = stringValue(item.name);
|
|
44015
44259
|
if (!name)
|
|
@@ -44026,7 +44270,7 @@ function parseManifestCommands(value) {
|
|
|
44026
44270
|
}
|
|
44027
44271
|
function parseManifestRuntime(value) {
|
|
44028
44272
|
const raw = value?.runtime;
|
|
44029
|
-
if (!
|
|
44273
|
+
if (!isRecord3(raw))
|
|
44030
44274
|
return;
|
|
44031
44275
|
const runtimeName = stringValue(raw.runtime);
|
|
44032
44276
|
if (!runtimeName)
|
|
@@ -44052,7 +44296,7 @@ function parseManifestRuntime(value) {
|
|
|
44052
44296
|
}
|
|
44053
44297
|
function parseManifestProvenance(value) {
|
|
44054
44298
|
const raw = value?.provenance;
|
|
44055
|
-
if (!
|
|
44299
|
+
if (!isRecord3(raw))
|
|
44056
44300
|
return;
|
|
44057
44301
|
const parsed = {};
|
|
44058
44302
|
if (stringValue(raw.source_commit))
|
|
@@ -44068,7 +44312,7 @@ function parseManifestInputs(value) {
|
|
|
44068
44312
|
if (!Array.isArray(raw))
|
|
44069
44313
|
return;
|
|
44070
44314
|
const inputs = raw.map((item) => {
|
|
44071
|
-
if (!
|
|
44315
|
+
if (!isRecord3(item))
|
|
44072
44316
|
return null;
|
|
44073
44317
|
const name = stringValue(item.name);
|
|
44074
44318
|
const type = stringValue(item.type);
|
|
@@ -44086,7 +44330,7 @@ function parseManifestInputs(value) {
|
|
|
44086
44330
|
function inferPackageCommands(pkg, fallbackName) {
|
|
44087
44331
|
if (!pkg)
|
|
44088
44332
|
return;
|
|
44089
|
-
if (
|
|
44333
|
+
if (isRecord3(pkg.bin)) {
|
|
44090
44334
|
const commands = Object.entries(pkg.bin).filter((entry) => typeof entry[1] === "string" && entry[1].trim().length > 0).map(([name, entry]) => ({
|
|
44091
44335
|
name: normalizePortableSkillName(name),
|
|
44092
44336
|
entry: entry.replace(/^\.\//, ""),
|
|
@@ -44095,7 +44339,7 @@ function inferPackageCommands(pkg, fallbackName) {
|
|
|
44095
44339
|
if (commands.length)
|
|
44096
44340
|
return commands;
|
|
44097
44341
|
}
|
|
44098
|
-
const scripts =
|
|
44342
|
+
const scripts = isRecord3(pkg.scripts) ? pkg.scripts : undefined;
|
|
44099
44343
|
const dev = stringValue(scripts?.dev);
|
|
44100
44344
|
const match = dev?.match(/(?:bun\s+run\s+|bun\s+)([^ ]+)/);
|
|
44101
44345
|
if (match?.[1]) {
|
|
@@ -44111,20 +44355,20 @@ function inferRuntimeFromCommands(commands) {
|
|
|
44111
44355
|
}
|
|
44112
44356
|
function readJsonObject(path) {
|
|
44113
44357
|
const parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
44114
|
-
if (!
|
|
44358
|
+
if (!isRecord3(parsed))
|
|
44115
44359
|
throw new Error(`${basename8(path)} must contain a JSON object`);
|
|
44116
44360
|
return parsed;
|
|
44117
44361
|
}
|
|
44118
44362
|
function hasPackageDependencies(pkgPath) {
|
|
44119
44363
|
try {
|
|
44120
44364
|
const pkg = readJsonObject(pkgPath);
|
|
44121
|
-
const deps =
|
|
44365
|
+
const deps = isRecord3(pkg.dependencies) ? Object.keys(pkg.dependencies) : [];
|
|
44122
44366
|
return deps.length > 0;
|
|
44123
44367
|
} catch {
|
|
44124
44368
|
return false;
|
|
44125
44369
|
}
|
|
44126
44370
|
}
|
|
44127
|
-
function
|
|
44371
|
+
function isRecord3(value) {
|
|
44128
44372
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44129
44373
|
}
|
|
44130
44374
|
function stringField(value, key) {
|
|
@@ -44339,7 +44583,7 @@ function scaffoldPortableSkill(name, options = {}) {
|
|
|
44339
44583
|
return { name: skillName, path: skillPath, manifest, created: true };
|
|
44340
44584
|
}
|
|
44341
44585
|
function portPortableSkillDirectory(sourceDir, options = {}) {
|
|
44342
|
-
const absoluteSource =
|
|
44586
|
+
const absoluteSource = normalize4(sourceDir);
|
|
44343
44587
|
if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
|
|
44344
44588
|
throw new Error(`Import directory not found: ${sourceDir}`);
|
|
44345
44589
|
}
|
|
@@ -44406,7 +44650,7 @@ function assertDisjointImportPaths(source, destination) {
|
|
|
44406
44650
|
}
|
|
44407
44651
|
}
|
|
44408
44652
|
function portPortableSkill(sourcePath, options = {}) {
|
|
44409
|
-
const absoluteSource =
|
|
44653
|
+
const absoluteSource = normalize4(sourcePath);
|
|
44410
44654
|
if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
|
|
44411
44655
|
throw new Error(`Skill source directory not found: ${sourcePath}`);
|
|
44412
44656
|
}
|
|
@@ -44682,7 +44926,7 @@ function safeIsDirectory(path) {
|
|
|
44682
44926
|
function isSafeRelativePath2(value) {
|
|
44683
44927
|
if (!value.trim() || isAbsolute18(value))
|
|
44684
44928
|
return false;
|
|
44685
|
-
const normalized =
|
|
44929
|
+
const normalized = normalize4(value).replace(/\\/g, "/");
|
|
44686
44930
|
return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
|
|
44687
44931
|
}
|
|
44688
44932
|
function add3(target, code, message) {
|
|
@@ -46333,7 +46577,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
46333
46577
|
selection: selection2,
|
|
46334
46578
|
target: "local",
|
|
46335
46579
|
runtime: runtimeName,
|
|
46336
|
-
inputDigest: `sha256:${
|
|
46580
|
+
inputDigest: `sha256:${createHash20("sha256").update(input).digest("hex")}`,
|
|
46337
46581
|
runDirectory,
|
|
46338
46582
|
...executionGrant ? { executionGrant } : {},
|
|
46339
46583
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
@@ -46391,7 +46635,7 @@ async function subprocess(command, cwd, env, input, timeoutMs) {
|
|
|
46391
46635
|
// src/lib/remote-run-contract.ts
|
|
46392
46636
|
var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
|
|
46393
46637
|
function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
|
|
46394
|
-
const record3 =
|
|
46638
|
+
const record3 = isRecord4(payload) ? payload : {};
|
|
46395
46639
|
return {
|
|
46396
46640
|
contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
46397
46641
|
...pickString(record3, "id"),
|
|
@@ -46413,7 +46657,7 @@ function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
|
|
|
46413
46657
|
...hasOwn(record3, "details") ? { details: record3.details } : {}
|
|
46414
46658
|
};
|
|
46415
46659
|
}
|
|
46416
|
-
function
|
|
46660
|
+
function isRecord4(value) {
|
|
46417
46661
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
46418
46662
|
}
|
|
46419
46663
|
function hasOwn(record3, key) {
|
|
@@ -55623,7 +55867,7 @@ var import_node_http_handler2 = __toESM(require_dist_cjs6(), 1);
|
|
|
55623
55867
|
|
|
55624
55868
|
// node_modules/@aws-sdk/checksums/dist-cjs/submodules/sha/index.js
|
|
55625
55869
|
var { toUint8Array: toUint8Array2, concatBytes } = require_serde();
|
|
55626
|
-
var { createHmac: createHmac2, createHash:
|
|
55870
|
+
var { createHmac: createHmac2, createHash: createHash22 } = __require("crypto");
|
|
55627
55871
|
var { Sha256: Sha2562, Sha256Js, Sha256Node } = require_checksum();
|
|
55628
55872
|
var BLOCK2 = 64;
|
|
55629
55873
|
var DIGEST_LENGTH = 20;
|
|
@@ -55792,7 +56036,7 @@ class Sha1Js {
|
|
|
55792
56036
|
}
|
|
55793
56037
|
var hasNativeCrypto = (() => {
|
|
55794
56038
|
try {
|
|
55795
|
-
|
|
56039
|
+
createHash22("sha1");
|
|
55796
56040
|
return true;
|
|
55797
56041
|
} catch {
|
|
55798
56042
|
return false;
|
|
@@ -55832,7 +56076,7 @@ function buildNativeClass() {
|
|
|
55832
56076
|
this.finished = false;
|
|
55833
56077
|
}
|
|
55834
56078
|
createHash() {
|
|
55835
|
-
return this.secret ? createHmac2("sha1", toBuffer(this.secret)) :
|
|
56079
|
+
return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash22("sha1");
|
|
55836
56080
|
}
|
|
55837
56081
|
};
|
|
55838
56082
|
}
|
|
@@ -56700,9 +56944,9 @@ import { mkdirSync as mkdirSync11, readFileSync as readFileSync23, readdirSync a
|
|
|
56700
56944
|
import { dirname as dirname23, join as join36 } from "path";
|
|
56701
56945
|
|
|
56702
56946
|
// src/server/auth.ts
|
|
56703
|
-
import { createHash as
|
|
56947
|
+
import { createHash as createHash23 } from "crypto";
|
|
56704
56948
|
function hashApiKey(token) {
|
|
56705
|
-
return
|
|
56949
|
+
return createHash23("sha256").update(token).digest("hex");
|
|
56706
56950
|
}
|
|
56707
56951
|
function bearerToken(request2) {
|
|
56708
56952
|
const header = request2.headers.get("authorization") || "";
|
|
@@ -57024,7 +57268,7 @@ function validOperatorScopeEnrollmentInput(input) {
|
|
|
57024
57268
|
}
|
|
57025
57269
|
|
|
57026
57270
|
// src/lib/revision.ts
|
|
57027
|
-
import { createHash as
|
|
57271
|
+
import { createHash as createHash24 } from "crypto";
|
|
57028
57272
|
var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
|
|
57029
57273
|
function revisionIdOf(content) {
|
|
57030
57274
|
const canonicalContent = {
|
|
@@ -57045,8 +57289,8 @@ function revisionIdOf(content) {
|
|
|
57045
57289
|
canonicalContent.archiveReason = content.archiveReason ?? null;
|
|
57046
57290
|
canonicalContent.replacementSlug = content.replacementSlug ?? null;
|
|
57047
57291
|
}
|
|
57048
|
-
const
|
|
57049
|
-
return
|
|
57292
|
+
const canonical6 = JSON.stringify(canonicalContent);
|
|
57293
|
+
return createHash24("sha256").update(canonical6).digest("hex");
|
|
57050
57294
|
}
|
|
57051
57295
|
function revisionIdOfRecord(record3) {
|
|
57052
57296
|
return revisionIdOf(record3);
|
|
@@ -58130,7 +58374,7 @@ function nextMonthPrefix(monthPrefix) {
|
|
|
58130
58374
|
}
|
|
58131
58375
|
|
|
58132
58376
|
// src/server/skills-api.ts
|
|
58133
|
-
import { createHash as
|
|
58377
|
+
import { createHash as createHash25 } from "crypto";
|
|
58134
58378
|
var SLUG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
|
|
58135
58379
|
var SHA256_HEX2 = /^[0-9a-f]{64}$/;
|
|
58136
58380
|
var MAX_SLUG_LENGTH = 128;
|
|
@@ -58320,7 +58564,7 @@ async function parsePublishRequest(request2, config) {
|
|
|
58320
58564
|
if (bundleBytes.byteLength === 0) {
|
|
58321
58565
|
throw new SkillRequestError(400, "BUNDLE_EMPTY", "the uploaded bundle is empty");
|
|
58322
58566
|
}
|
|
58323
|
-
const sha2562 =
|
|
58567
|
+
const sha2562 = createHash25("sha256").update(bundleBytes).digest("hex");
|
|
58324
58568
|
const claimed = optionalString(manifest.bundleSha256);
|
|
58325
58569
|
if (claimed)
|
|
58326
58570
|
assertSha2562(claimed);
|
|
@@ -58435,7 +58679,7 @@ async function readPublishedBundle(store, artifactStorage, principal, slug) {
|
|
|
58435
58679
|
if (!bytes) {
|
|
58436
58680
|
throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
|
|
58437
58681
|
}
|
|
58438
|
-
const actual =
|
|
58682
|
+
const actual = createHash25("sha256").update(bytes).digest("hex");
|
|
58439
58683
|
if (actual !== record3.bundleSha256) {
|
|
58440
58684
|
throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}' hashes to ${actual} but was published as ${record3.bundleSha256}`);
|
|
58441
58685
|
}
|
|
@@ -58583,7 +58827,7 @@ async function readSkillVersionBundle(store, artifactStorage, principal, slug, v
|
|
|
58583
58827
|
const bytes = await artifactStorage.readBundle(bundle2);
|
|
58584
58828
|
if (!bytes)
|
|
58585
58829
|
throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
|
|
58586
|
-
const actual =
|
|
58830
|
+
const actual = createHash25("sha256").update(bytes).digest("hex");
|
|
58587
58831
|
if (actual !== found.bundleSha256) {
|
|
58588
58832
|
throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}@${version2}' hashes to ${actual} but was published as ${found.bundleSha256}`);
|
|
58589
58833
|
}
|
|
@@ -59286,7 +59530,7 @@ class RuntimeExecutionStore {
|
|
|
59286
59530
|
}
|
|
59287
59531
|
|
|
59288
59532
|
// src/sdk/execution/admission.ts
|
|
59289
|
-
import { createHash as
|
|
59533
|
+
import { createHash as createHash27 } from "crypto";
|
|
59290
59534
|
|
|
59291
59535
|
// src/sdk/execution/image-profile.ts
|
|
59292
59536
|
class ImageProfileResolutionError extends Error {
|
|
@@ -59898,11 +60142,11 @@ function ownedAdmission(admission) {
|
|
|
59898
60142
|
};
|
|
59899
60143
|
}
|
|
59900
60144
|
function digestInput(input) {
|
|
59901
|
-
return
|
|
60145
|
+
return createHash27("sha256").update(canonicalJson2(input)).digest("hex");
|
|
59902
60146
|
}
|
|
59903
60147
|
|
|
59904
60148
|
// src/sdk/execution/dispatchers/ecs.ts
|
|
59905
|
-
import { createHash as
|
|
60149
|
+
import { createHash as createHash28 } from "crypto";
|
|
59906
60150
|
|
|
59907
60151
|
// src/sdk/execution/state-machine.ts
|
|
59908
60152
|
var LEGAL_TRANSITIONS = {
|
|
@@ -63302,13 +63546,13 @@ function observedTask(states, taskArn) {
|
|
|
63302
63546
|
return state2.lastStatus === "STOPPED" || LIVE_TASK_STATUSES.has(state2.lastStatus) ? state2 : undefined;
|
|
63303
63547
|
}
|
|
63304
63548
|
function clientTokenFor(runId3, attemptId) {
|
|
63305
|
-
return
|
|
63549
|
+
return createHash28("sha256").update(`${runId3}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
|
|
63306
63550
|
}
|
|
63307
63551
|
function startedByFor(runId3, attemptNumber) {
|
|
63308
63552
|
return `skills-exec/${runId3}/a${attemptNumber}`;
|
|
63309
63553
|
}
|
|
63310
63554
|
function requestDigestFor(admission, attemptId) {
|
|
63311
|
-
return
|
|
63555
|
+
return createHash28("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
|
|
63312
63556
|
}
|
|
63313
63557
|
|
|
63314
63558
|
class EcsDispatcher {
|
|
@@ -63604,10 +63848,10 @@ function validText(value) {
|
|
|
63604
63848
|
}
|
|
63605
63849
|
|
|
63606
63850
|
// src/server/runtime-policy.ts
|
|
63607
|
-
import { createHash as
|
|
63851
|
+
import { createHash as createHash30, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
63608
63852
|
|
|
63609
63853
|
// src/server/runtime-pure-contract.ts
|
|
63610
|
-
import { createHash as
|
|
63854
|
+
import { createHash as createHash29 } from "crypto";
|
|
63611
63855
|
var PURE_DESCRIPTOR = Object.freeze({
|
|
63612
63856
|
id: "regex-test.v1",
|
|
63613
63857
|
runtime: "bun",
|
|
@@ -63631,7 +63875,7 @@ var PURE_LIMITS = Object.freeze({
|
|
|
63631
63875
|
maxArtifactsBytes: 0,
|
|
63632
63876
|
maxConcurrency: 1
|
|
63633
63877
|
});
|
|
63634
|
-
var hash2 = (bytes) =>
|
|
63878
|
+
var hash2 = (bytes) => createHash29("sha256").update(bytes).digest("hex");
|
|
63635
63879
|
var object6 = (v2) => {
|
|
63636
63880
|
if (!v2 || typeof v2 !== "object" || Array.isArray(v2))
|
|
63637
63881
|
throw Error("Pure contract requires an object");
|
|
@@ -63860,7 +64104,7 @@ function verifyRuntimeToken(token, key, admission, attempt, now = Date.now()) {
|
|
|
63860
64104
|
const actual = Buffer.from(token);
|
|
63861
64105
|
return actual.length === expected.length && timingSafeEqual2(actual, expected);
|
|
63862
64106
|
}
|
|
63863
|
-
var hashBytes = (bytes) =>
|
|
64107
|
+
var hashBytes = (bytes) => createHash30("sha256").update(bytes).digest("hex");
|
|
63864
64108
|
|
|
63865
64109
|
// src/server/runtime-api.ts
|
|
63866
64110
|
async function createRuntimeService(options) {
|
|
@@ -66048,7 +66292,7 @@ async function readJson(request2, limitBytes) {
|
|
|
66048
66292
|
if (!text2.trim())
|
|
66049
66293
|
return {};
|
|
66050
66294
|
const parsed = JSON.parse(text2);
|
|
66051
|
-
return
|
|
66295
|
+
return isRecord5(parsed) ? parsed : {};
|
|
66052
66296
|
}
|
|
66053
66297
|
function pathSegments(pathname) {
|
|
66054
66298
|
return pathname.split("/").filter(Boolean).map(decodeSegment);
|
|
@@ -66069,7 +66313,7 @@ function json4(payload, init = {}) {
|
|
|
66069
66313
|
headers: { "Cache-Control": "no-store", ...init.headers }
|
|
66070
66314
|
});
|
|
66071
66315
|
}
|
|
66072
|
-
function
|
|
66316
|
+
function isRecord5(value) {
|
|
66073
66317
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
66074
66318
|
}
|
|
66075
66319
|
function clampInt(value, fallback, max) {
|
|
@@ -70232,7 +70476,7 @@ var localRunExecutor = {
|
|
|
70232
70476
|
// src/sdk/storage.ts
|
|
70233
70477
|
var artifactStorageSeam = ArtifactStorage;
|
|
70234
70478
|
// src/sdk/outputs.ts
|
|
70235
|
-
import { createHash as
|
|
70479
|
+
import { createHash as createHash31 } from "crypto";
|
|
70236
70480
|
class DatabaseOnlyObjectStore {
|
|
70237
70481
|
usesS3 = false;
|
|
70238
70482
|
async materialize(run, artifact, body4) {
|
|
@@ -70279,7 +70523,7 @@ function createGovernedArtifactWriter(options) {
|
|
|
70279
70523
|
const stamped = {
|
|
70280
70524
|
...meta,
|
|
70281
70525
|
byteSize: outputBytes,
|
|
70282
|
-
sha256:
|
|
70526
|
+
sha256: createHash31("sha256").update(persistedBytes).digest("hex"),
|
|
70283
70527
|
visibility: options.visibility ?? config.defaultVisibility,
|
|
70284
70528
|
...config.artifactTtlSeconds !== undefined ? { expiresAt: expiresAtFor(createdAt, config.artifactTtlSeconds) } : {}
|
|
70285
70529
|
};
|
|
@@ -73750,15 +73994,15 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
|
|
|
73750
73994
|
} catch (_err) {}
|
|
73751
73995
|
}
|
|
73752
73996
|
const input = payload.value;
|
|
73753
|
-
const
|
|
73754
|
-
const isValidDate =
|
|
73997
|
+
const isDate2 = input instanceof Date;
|
|
73998
|
+
const isValidDate = isDate2 && !Number.isNaN(input.getTime());
|
|
73755
73999
|
if (isValidDate)
|
|
73756
74000
|
return payload;
|
|
73757
74001
|
payload.issues.push({
|
|
73758
74002
|
expected: "date",
|
|
73759
74003
|
code: "invalid_type",
|
|
73760
74004
|
input,
|
|
73761
|
-
...
|
|
74005
|
+
...isDate2 ? { received: "Invalid Date" } : {},
|
|
73762
74006
|
inst
|
|
73763
74007
|
});
|
|
73764
74008
|
return payload;
|
|
@@ -89046,7 +89290,7 @@ function date4(params) {
|
|
|
89046
89290
|
return _coercedDate(ZodDate2, params);
|
|
89047
89291
|
}
|
|
89048
89292
|
// src/lib/canonical-json.ts
|
|
89049
|
-
import { createHash as
|
|
89293
|
+
import { createHash as createHash32 } from "crypto";
|
|
89050
89294
|
function canonicalJson3(value, maximumBytes = 2 * 1024 * 1024) {
|
|
89051
89295
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
89052
89296
|
}
|
|
@@ -89090,7 +89334,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
89090
89334
|
return visit3(value, 0);
|
|
89091
89335
|
}
|
|
89092
89336
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
89093
|
-
return
|
|
89337
|
+
return createHash32("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
|
|
89094
89338
|
}
|
|
89095
89339
|
|
|
89096
89340
|
// src/lib/remote-recurring-contract.ts
|
|
@@ -89956,7 +90200,7 @@ function creditCheckoutFailure(value, status, key) {
|
|
|
89956
90200
|
|
|
89957
90201
|
// src/lib/remote-profile.ts
|
|
89958
90202
|
function customerNamePatch(input2, field2) {
|
|
89959
|
-
if (!
|
|
90203
|
+
if (!isRecord6(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field2))
|
|
89960
90204
|
throw new Error("Provide only the requested name field.");
|
|
89961
90205
|
const value = input2[field2];
|
|
89962
90206
|
if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
|
|
@@ -89964,22 +90208,22 @@ function customerNamePatch(input2, field2) {
|
|
|
89964
90208
|
}
|
|
89965
90209
|
return { [field2]: value.trim() };
|
|
89966
90210
|
}
|
|
89967
|
-
function
|
|
90211
|
+
function isRecord6(value) {
|
|
89968
90212
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
89969
90213
|
}
|
|
89970
90214
|
function string4(value) {
|
|
89971
90215
|
return typeof value === "string" && value.length > 0;
|
|
89972
90216
|
}
|
|
89973
90217
|
function parseUpdatedProfile(value) {
|
|
89974
|
-
const user =
|
|
89975
|
-
if (!
|
|
90218
|
+
const user = isRecord6(value) && value.user;
|
|
90219
|
+
if (!isRecord6(user) || !string4(user.id) || !string4(user.email) || !(user.displayName === null || typeof user.displayName === "string") || typeof user.role !== "string" || !["owner", "admin", "member", "viewer"].includes(user.role)) {
|
|
89976
90220
|
throw new Error("The server returned an invalid account profile.");
|
|
89977
90221
|
}
|
|
89978
90222
|
return { user: { id: user.id, email: user.email, displayName: user.displayName, role: user.role } };
|
|
89979
90223
|
}
|
|
89980
90224
|
function parseUpdatedWorkspace(value) {
|
|
89981
|
-
const organization2 =
|
|
89982
|
-
if (!
|
|
90225
|
+
const organization2 = isRecord6(value) && value.organization;
|
|
90226
|
+
if (!isRecord6(organization2) || !string4(organization2.id) || !string4(organization2.slug) || !string4(organization2.name)) {
|
|
89983
90227
|
throw new Error("The server returned an invalid workspace.");
|
|
89984
90228
|
}
|
|
89985
90229
|
return { organization: { id: organization2.id, slug: organization2.slug, name: organization2.name } };
|
|
@@ -91204,7 +91448,7 @@ async function requestInvitationEmail(origin, action, input2) {
|
|
|
91204
91448
|
}
|
|
91205
91449
|
|
|
91206
91450
|
// src/lib/remote-private-publications.ts
|
|
91207
|
-
import { createHash as
|
|
91451
|
+
import { createHash as createHash33 } from "crypto";
|
|
91208
91452
|
var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
|
|
91209
91453
|
var failures2 = {
|
|
91210
91454
|
INVALID_REQUEST: [400, "The publication request is invalid."],
|
|
@@ -91251,7 +91495,7 @@ var hash4 = (v2) => typeof v2 === "string" && /^[a-f0-9]{64}$/.test(v2);
|
|
|
91251
91495
|
var record9 = (v2) => !!v2 && typeof v2 === "object" && !Array.isArray(v2);
|
|
91252
91496
|
var exact = (v2, keys3) => record9(v2) && Object.keys(v2).sort().join(",") === keys3.sort().join(",");
|
|
91253
91497
|
var date5 = (v2) => typeof v2 === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v2) && Number.isFinite(Date.parse(v2));
|
|
91254
|
-
var publicationSha256 = (bytes) =>
|
|
91498
|
+
var publicationSha256 = (bytes) => createHash33("sha256").update(bytes).digest("hex");
|
|
91255
91499
|
function checkedPublicationDeclaration(value) {
|
|
91256
91500
|
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 || !hash4(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
|
|
91257
91501
|
return bad();
|
|
@@ -91550,7 +91794,7 @@ async function requestAuthApi(instance, path2, options) {
|
|
|
91550
91794
|
const text3 = await res.text();
|
|
91551
91795
|
const body4 = text3 ? parseJsonBody(text3) : {};
|
|
91552
91796
|
if (!res.ok) {
|
|
91553
|
-
const record10 =
|
|
91797
|
+
const record10 = isRecord7(body4) ? body4 : {};
|
|
91554
91798
|
const detail = typeof record10.detail === "string" ? record10.detail : undefined;
|
|
91555
91799
|
const error61 = typeof record10.error === "string" ? record10.error : undefined;
|
|
91556
91800
|
const code = typeof record10.code === "string" ? record10.code : undefined;
|
|
@@ -91578,7 +91822,7 @@ function condenseErrorBody(text3) {
|
|
|
91578
91822
|
return collapsed;
|
|
91579
91823
|
return `${collapsed.slice(0, MAX_ERROR_DETAIL_LENGTH - 1).trimEnd()}\u2026`;
|
|
91580
91824
|
}
|
|
91581
|
-
function
|
|
91825
|
+
function isRecord7(value) {
|
|
91582
91826
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
91583
91827
|
}
|
|
91584
91828
|
|
|
@@ -92086,16 +92330,16 @@ function resultSnapshot(input2, requestId) {
|
|
|
92086
92330
|
const value = snapshot2(input2, SKILL_OPERATION_LIMITS.resultBytes).value;
|
|
92087
92331
|
if (!record10(value) || value.contractVersion !== 1 || value.requestId !== requestId)
|
|
92088
92332
|
throw Error();
|
|
92089
|
-
const
|
|
92333
|
+
const fields2 = ["contractVersion", "requestId", "status"];
|
|
92090
92334
|
if (value.status === "succeeded")
|
|
92091
|
-
|
|
92335
|
+
fields2.push("output");
|
|
92092
92336
|
else if (value.status === "refused") {
|
|
92093
|
-
|
|
92337
|
+
fields2.push("code");
|
|
92094
92338
|
if (!refusalCodes.has(value.code))
|
|
92095
92339
|
throw Error();
|
|
92096
92340
|
} else if (!["not-executed", "pending", "unknown"].includes(value.status))
|
|
92097
92341
|
throw Error();
|
|
92098
|
-
if (!exact2(value,
|
|
92342
|
+
if (!exact2(value, fields2))
|
|
92099
92343
|
throw Error();
|
|
92100
92344
|
return value;
|
|
92101
92345
|
} catch {
|