@hasna/skills 0.10.19 → 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 +48 -12
- package/bin/index.js +761 -443
- 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 +2 -2
- package/dist/index.js +520 -207
- 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 +20 -0
- package/dist/lib/codex-plugin-skill-controls.d.ts +2 -1
- 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 +594 -284
- 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
|
}
|
|
@@ -25954,12 +25954,12 @@ import fs from "fs/promises";
|
|
|
25954
25954
|
var import_client9, import_config17, import_node_http_handler, AWS_CONTAINER_CREDENTIALS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", DEFAULT_LINK_LOCAL_HOST = "http://169.254.170.2", AWS_CONTAINER_CREDENTIALS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI", AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE = "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE", AWS_CONTAINER_AUTHORIZATION_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN", fromHttp = (options = {}) => {
|
|
25955
25955
|
options.logger?.debug("@aws-sdk/credential-provider-http - fromHttp");
|
|
25956
25956
|
let host;
|
|
25957
|
-
const
|
|
25957
|
+
const relative7 = options.awsContainerCredentialsRelativeUri ?? process.env[AWS_CONTAINER_CREDENTIALS_RELATIVE_URI];
|
|
25958
25958
|
const full = options.awsContainerCredentialsFullUri ?? process.env[AWS_CONTAINER_CREDENTIALS_FULL_URI];
|
|
25959
25959
|
const token = options.awsContainerAuthorizationToken ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN];
|
|
25960
25960
|
const tokenFile = options.awsContainerAuthorizationTokenFile ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE];
|
|
25961
25961
|
const warn = options.logger?.constructor?.name === "NoOpLogger" || !options.logger?.warn ? console.warn : options.logger.warn.bind(options.logger);
|
|
25962
|
-
if (
|
|
25962
|
+
if (relative7 && full) {
|
|
25963
25963
|
warn("@aws-sdk/credential-provider-http: " + "you have set both awsContainerCredentialsRelativeUri and awsContainerCredentialsFullUri.");
|
|
25964
25964
|
warn("awsContainerCredentialsRelativeUri will take precedence.");
|
|
25965
25965
|
}
|
|
@@ -25967,8 +25967,8 @@ var import_client9, import_config17, import_node_http_handler, AWS_CONTAINER_CRE
|
|
|
25967
25967
|
warn("@aws-sdk/credential-provider-http: " + "you have set both awsContainerAuthorizationToken and awsContainerAuthorizationTokenFile.");
|
|
25968
25968
|
warn("awsContainerAuthorizationTokenFile will take precedence.");
|
|
25969
25969
|
}
|
|
25970
|
-
if (
|
|
25971
|
-
host = `${DEFAULT_LINK_LOCAL_HOST}${
|
|
25970
|
+
if (relative7) {
|
|
25971
|
+
host = `${DEFAULT_LINK_LOCAL_HOST}${relative7}`;
|
|
25972
25972
|
} else if (full) {
|
|
25973
25973
|
host = full;
|
|
25974
25974
|
} else {
|
|
@@ -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";
|
|
@@ -37692,7 +37692,7 @@ import {
|
|
|
37692
37692
|
writeFileSync as writeFileSync7
|
|
37693
37693
|
} from "fs";
|
|
37694
37694
|
import { homedir as homedir5 } from "os";
|
|
37695
|
-
import { basename as
|
|
37695
|
+
import { basename as basename11, dirname as dirname19, join as join27 } from "path";
|
|
37696
37696
|
|
|
37697
37697
|
// src/lib/claude-settings-witness.ts
|
|
37698
37698
|
import { createHash as createHash5 } from "crypto";
|
|
@@ -38006,9 +38006,28 @@ function hashNativeJsonControls(text, excludedMetadata) {
|
|
|
38006
38006
|
}
|
|
38007
38007
|
|
|
38008
38008
|
// src/lib/codex-plugin-skill-controls.ts
|
|
38009
|
-
import { dirname as dirname5, join as join10, resolve as resolve4, sep as sep2 } from "path";
|
|
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]))
|
|
@@ -38160,12 +38178,13 @@ async function connectCodexHookRpc(options) {
|
|
|
38160
38178
|
var MAX_SKILLS = 4096;
|
|
38161
38179
|
var MAX_NAME_BYTES = 1024;
|
|
38162
38180
|
var MAX_PATH_BYTES = 16384;
|
|
38163
|
-
var
|
|
38181
|
+
var MAX_PLUGIN_ID_BYTES = 1024;
|
|
38164
38182
|
function refuse2() {
|
|
38165
38183
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_INVALID");
|
|
38166
38184
|
}
|
|
38167
38185
|
var object2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
38168
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);
|
|
38169
38188
|
var absolutePath2 = (value) => scalar(value, MAX_PATH_BYTES) && isAbsolute5(value);
|
|
38170
38189
|
function projectCodexNativeSkillCatalog(response, cwd) {
|
|
38171
38190
|
if (!absolutePath2(cwd) || !object2(response) || !Array.isArray(response.data) || response.data.length !== 1)
|
|
@@ -38183,6 +38202,47 @@ function projectCodexNativeSkillCatalog(response, cwd) {
|
|
|
38183
38202
|
return { name: value.name, path: value.path, enabled: value.enabled, pluginId: value.pluginId ?? null };
|
|
38184
38203
|
});
|
|
38185
38204
|
}
|
|
38205
|
+
function projectCodexInstalledPlugins(response) {
|
|
38206
|
+
if (!object2(response) || !Array.isArray(response.marketplaces) || !Array.isArray(response.marketplaceLoadErrors) || response.marketplaceLoadErrors.length !== 0 || response.marketplaces.length > MAX_SKILLS)
|
|
38207
|
+
refuse2();
|
|
38208
|
+
const plugins = [];
|
|
38209
|
+
for (const marketplace of response.marketplaces) {
|
|
38210
|
+
if (!object2(marketplace) || !scalar(marketplace.name, MAX_NAME_BYTES) || !Array.isArray(marketplace.plugins) || marketplace.plugins.length > MAX_SKILLS)
|
|
38211
|
+
refuse2();
|
|
38212
|
+
for (const value of marketplace.plugins) {
|
|
38213
|
+
if (!object2(value) || !scalar(value.id, MAX_PLUGIN_ID_BYTES) || !scalar(value.name, MAX_NAME_BYTES) || value.id !== `${value.name}@${marketplace.name}`)
|
|
38214
|
+
refuse2();
|
|
38215
|
+
plugins.push({
|
|
38216
|
+
...value,
|
|
38217
|
+
marketplace: marketplace.name,
|
|
38218
|
+
sourceType: object2(value.source) && value.source.type === "remote" ? "remote" : undefined
|
|
38219
|
+
});
|
|
38220
|
+
}
|
|
38221
|
+
}
|
|
38222
|
+
return projectCodexInstalledPluginEntries(plugins);
|
|
38223
|
+
}
|
|
38224
|
+
function projectCodexInstalledPluginEntries(value) {
|
|
38225
|
+
if (!Array.isArray(value) || value.length > MAX_SKILLS)
|
|
38226
|
+
refuse2();
|
|
38227
|
+
const ids = new Set;
|
|
38228
|
+
return value.map((item) => {
|
|
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")
|
|
38230
|
+
refuse2();
|
|
38231
|
+
const at = item.id.lastIndexOf("@");
|
|
38232
|
+
if (at < 1 || item.id.slice(0, at) !== item.name || at === item.id.length - 1 || ids.has(item.id))
|
|
38233
|
+
refuse2();
|
|
38234
|
+
ids.add(item.id);
|
|
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
|
+
};
|
|
38244
|
+
});
|
|
38245
|
+
}
|
|
38186
38246
|
async function captureCodexNativeSkillCatalog(options, connect = connectCodexHookRpc) {
|
|
38187
38247
|
if (!absolutePath2(options.cwd) || !absolutePath2(options.home))
|
|
38188
38248
|
refuse2();
|
|
@@ -38193,10 +38253,16 @@ async function captureCodexNativeSkillCatalog(options, connect = connectCodexHoo
|
|
|
38193
38253
|
...options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }
|
|
38194
38254
|
});
|
|
38195
38255
|
try {
|
|
38196
|
-
if (!
|
|
38256
|
+
if (!supportsCodexNativeCapability(rpc.version, "qualified-skill-catalog"))
|
|
38197
38257
|
throw new Error("CODEX_NATIVE_SKILL_CATALOG_UNSUPPORTED_VERSION");
|
|
38198
38258
|
const response = await rpc.request("skills/list", { cwds: [options.cwd], forceReload: true });
|
|
38199
|
-
|
|
38259
|
+
const installed = await rpc.request("plugin/installed", { cwds: [options.cwd] });
|
|
38260
|
+
return {
|
|
38261
|
+
version: rpc.version,
|
|
38262
|
+
cwd: options.cwd,
|
|
38263
|
+
skills: projectCodexNativeSkillCatalog(response, options.cwd),
|
|
38264
|
+
plugins: projectCodexInstalledPlugins(installed)
|
|
38265
|
+
};
|
|
38200
38266
|
} finally {
|
|
38201
38267
|
await rpc.close();
|
|
38202
38268
|
}
|
|
@@ -38241,9 +38307,25 @@ function isCodexNativeSkillDisabled(skill, rules) {
|
|
|
38241
38307
|
|
|
38242
38308
|
// src/lib/codex-plugin-skill-controls.ts
|
|
38243
38309
|
var identifier3 = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(v);
|
|
38310
|
+
var CODEX_DEFAULT_AGENT_PLUGIN_VERSION = "1.0.0";
|
|
38244
38311
|
function refuse3() {
|
|
38245
38312
|
throw new Error("CODEX_NATIVE_SKILL_IDENTITY_UNSUPPORTED: review native plugin names and hook controls");
|
|
38246
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
|
+
}
|
|
38247
38329
|
function appControls(path, read) {
|
|
38248
38330
|
const text = read(path);
|
|
38249
38331
|
let value, sha2562;
|
|
@@ -38279,6 +38361,9 @@ function rootControls(root, read) {
|
|
|
38279
38361
|
}
|
|
38280
38362
|
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || !identifier3(manifest.name))
|
|
38281
38363
|
refuse3();
|
|
38364
|
+
const cacheVersion = basename3(root), declaredVersion = manifest.version === undefined ? "" : typeof manifest.version === "string" ? manifest.version.trim() : null;
|
|
38365
|
+
if (declaredVersion === null || (declaredVersion ? declaredVersion !== cacheVersion : cacheVersion !== CODEX_DEFAULT_AGENT_PLUGIN_VERSION))
|
|
38366
|
+
refuse3();
|
|
38282
38367
|
if (manifest.hooks !== undefined || manifest.mcpServers !== undefined || manifest.commands !== undefined || manifest.apps !== undefined && manifest.apps !== "./.app.json" || ["hooks", ".mcp.json"].some((path) => lstatSync6(join10(root, path), { throwIfNoEntry: false })))
|
|
38283
38368
|
refuse3();
|
|
38284
38369
|
const app = join10(root, ".app.json"), present = lstatSync6(app, { throwIfNoEntry: false });
|
|
@@ -38330,6 +38415,10 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read) {
|
|
|
38330
38415
|
for (const parent of new Set(controls.map((control) => control.pluginParent))) {
|
|
38331
38416
|
if (!parent.startsWith(cache + sep2) || !lstatSync6(parent, { throwIfNoEntry: false })?.isDirectory())
|
|
38332
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
|
+
}
|
|
38333
38422
|
const names = readdirSync3(parent);
|
|
38334
38423
|
entries += names.length;
|
|
38335
38424
|
if (entries > 4096)
|
|
@@ -38355,22 +38444,56 @@ function reviewedCodexPluginCapabilitiesUnchanged(cache, controls, read) {
|
|
|
38355
38444
|
return false;
|
|
38356
38445
|
}
|
|
38357
38446
|
}
|
|
38358
|
-
function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read) {
|
|
38359
|
-
if (catalog?.version
|
|
38447
|
+
function reviewCodexPluginSkillControls(catalog, documents, cache, cwd, read, rules) {
|
|
38448
|
+
if (!supportsCodexNativeCapability(catalog?.version, "qualified-skill-catalog") || catalog.cwd !== cwd)
|
|
38360
38449
|
refuse3();
|
|
38361
38450
|
const skills = projectCodexNativeSkillCatalog({ data: [{ cwd, errors: [], skills: catalog.skills }] }, cwd);
|
|
38362
38451
|
const allowed = new Set(documents), result = [];
|
|
38363
|
-
|
|
38364
|
-
|
|
38452
|
+
let installedPlugins;
|
|
38453
|
+
try {
|
|
38454
|
+
installedPlugins = projectCodexInstalledPluginEntries(catalog.plugins ?? []);
|
|
38455
|
+
} catch {
|
|
38456
|
+
refuse3();
|
|
38457
|
+
}
|
|
38458
|
+
const candidates = catalog.plugins === undefined ? skills.map((skill) => skill.path).filter((path) => allowed.has(path)) : allowed;
|
|
38459
|
+
for (const document of candidates) {
|
|
38460
|
+
if (!document.startsWith(cache + sep2))
|
|
38365
38461
|
continue;
|
|
38366
|
-
|
|
38462
|
+
const parsed = identity(document, cache, read);
|
|
38463
|
+
if (parsed.name === "skills-cli" || parsed.name.endsWith(":skills-cli"))
|
|
38367
38464
|
refuse3();
|
|
38368
|
-
|
|
38465
|
+
const cacheParts = relative3(cache, parsed.pluginParent).split(sep2);
|
|
38466
|
+
if (cacheParts.length !== 2 || cacheParts.some((part) => !identifier3(part)))
|
|
38369
38467
|
refuse3();
|
|
38370
|
-
const
|
|
38371
|
-
if (
|
|
38468
|
+
const [marketplace, pluginName] = cacheParts;
|
|
38469
|
+
if (pluginName !== parsed.namespace)
|
|
38372
38470
|
refuse3();
|
|
38373
|
-
|
|
38471
|
+
const expectedPluginId = `${pluginName}@${marketplace}`;
|
|
38472
|
+
const listed = skills.filter((skill) => skill.path === document);
|
|
38473
|
+
if (listed.length > 1)
|
|
38474
|
+
refuse3();
|
|
38475
|
+
let remotePluginId;
|
|
38476
|
+
if (listed.length === 1) {
|
|
38477
|
+
if (listed[0].name !== parsed.name || listed[0].pluginId !== expectedPluginId)
|
|
38478
|
+
refuse3();
|
|
38479
|
+
} else {
|
|
38480
|
+
const installed = installedPlugins.filter((plugin2) => plugin2.id === expectedPluginId && plugin2.name === pluginName);
|
|
38481
|
+
if (installed.length !== 1 || !installed[0].installed || !installed[0].enabled)
|
|
38482
|
+
refuse3();
|
|
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
|
+
}
|
|
38492
|
+
const exactPathDeny = Array.isArray(rules) && rules.some((rule) => rule?.path === document && rule?.enabled === false);
|
|
38493
|
+
if (!exactPathDeny || !isCodexNativeSkillDisabled({ name: parsed.name, path: document, pluginId: expectedPluginId, enabled: true }, rules))
|
|
38494
|
+
refuse3();
|
|
38495
|
+
}
|
|
38496
|
+
result.push({ ...parsed, pluginId: expectedPluginId, ...remotePluginId ? { remotePluginId } : {} });
|
|
38374
38497
|
}
|
|
38375
38498
|
if (!result.length || new Set(result.map((item) => item.name)).size !== result.length)
|
|
38376
38499
|
refuse3();
|
|
@@ -38386,7 +38509,7 @@ function isReviewedCodexPluginSkillDisabled(document, cache, controls, rules, re
|
|
|
38386
38509
|
return false;
|
|
38387
38510
|
}
|
|
38388
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);
|
|
38389
|
-
if (!reviewed)
|
|
38512
|
+
if (!reviewed || reviewed.remotePluginId !== undefined && !remoteInstallationMatches(reviewed.pluginParent, reviewed.remotePluginId, read))
|
|
38390
38513
|
return false;
|
|
38391
38514
|
return isCodexNativeSkillDisabled({ name: parsed.name, path: document, pluginId: reviewed.pluginId, enabled: true }, rules);
|
|
38392
38515
|
}
|
|
@@ -38405,7 +38528,7 @@ enabled = false
|
|
|
38405
38528
|
return text;
|
|
38406
38529
|
}
|
|
38407
38530
|
|
|
38408
|
-
// src/lib/codex-settings-witness.ts
|
|
38531
|
+
// src/lib/codex-settings-witness-v1.ts
|
|
38409
38532
|
import { createHash as createHash6 } from "crypto";
|
|
38410
38533
|
var sha = (text) => createHash6("sha256").update(text).digest("hex");
|
|
38411
38534
|
var EFFORT = new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
|
|
@@ -38499,15 +38622,162 @@ function captureCodexSettings(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
|
38499
38622
|
const text = readNativeSettingsWitnessFile(path, budget, "config.toml");
|
|
38500
38623
|
return { path, hashMode: "codex-settings-v1", sha256: hashCodexSettingsReplacement(text) };
|
|
38501
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
|
+
}
|
|
38502
38772
|
function upgradeCodexSettingsWitness(previous, reviewedSettingsPath) {
|
|
38503
|
-
|
|
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));
|
|
38504
38774
|
const budget = { remaining: 2 * 1024 * 1024 };
|
|
38505
38775
|
const before = readNativeSettingsWitnessFile(reviewedSettingsPath, budget, "config.toml"), current = readNativeSettingsWitnessFile(previous.path, budget, "config.toml");
|
|
38506
|
-
|
|
38507
|
-
const sha2562 =
|
|
38508
|
-
if (
|
|
38776
|
+
need3((previous.hashMode === "codex-settings-v1" ? hashCodexSettingsReplacement(before) : sha2(before)) === previous.sha256);
|
|
38777
|
+
const sha2562 = settingsDigest2(current);
|
|
38778
|
+
if (settingsDigest2(before) !== sha2562)
|
|
38509
38779
|
throw new Error("Codex non-preference settings changed; explicit discovery review required");
|
|
38510
|
-
return { path: previous.path, hashMode: "codex-settings-
|
|
38780
|
+
return { path: previous.path, hashMode: "codex-settings-v2", sha256: sha2562 };
|
|
38511
38781
|
}
|
|
38512
38782
|
|
|
38513
38783
|
// src/lib/native-discovery-roots.ts
|
|
@@ -38530,9 +38800,10 @@ var NATIVE_SKILL_ROOTS = [
|
|
|
38530
38800
|
];
|
|
38531
38801
|
|
|
38532
38802
|
// src/lib/agent-integration.ts
|
|
38533
|
-
import { createHash as
|
|
38803
|
+
import { createHash as createHash18, randomUUID as randomUUID3 } from "crypto";
|
|
38804
|
+
import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
|
|
38534
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";
|
|
38535
|
-
import { dirname as dirname15, join as join22, resolve as resolve15, relative as
|
|
38806
|
+
import { dirname as dirname15, join as join22, resolve as resolve15, relative as relative4, isAbsolute as isAbsolute17, sep as sep5 } from "path";
|
|
38536
38807
|
import { homedir as homedir3 } from "os";
|
|
38537
38808
|
|
|
38538
38809
|
// src/lib/managed-policy.ts
|
|
@@ -38540,7 +38811,7 @@ import { closeSync as closeSync10, constants as constants6, fstatSync as fstatSy
|
|
|
38540
38811
|
import { join as join11 } from "path";
|
|
38541
38812
|
|
|
38542
38813
|
// src/lib/agent-policy-limits.ts
|
|
38543
|
-
import { basename as
|
|
38814
|
+
import { basename as basename4, isAbsolute as isAbsolute6, resolve as resolve5 } from "path";
|
|
38544
38815
|
var AGENT_POLICY_LIMITS = Object.freeze({ bytes: 1024 * 1024, agents: 16, discoverySources: 2048, discoveryRawSourceBytes: 64 * 1024 * 1024, discoveryRawTotalBytes: 256 * 1024 * 1024, discoveryPathLinks: 40, discoveryPathSteps: 256, discoveryPathSourceMetadataBytes: 64 * 1024, discoveryPathTotalMetadataBytes: 8 * 1024 * 1024, discoveryRoots: 512, discoveryDirectories: 64, discoveryDirectoryEntries: 20000, discoveryDirectoryBytes: 8 * 1024 * 1024, builtinNames: 2048, rootAliases: 2, fields: 64, pathCharacters: 4096 });
|
|
38545
38816
|
function object3(value) {
|
|
38546
38817
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
@@ -38589,12 +38860,14 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38589
38860
|
}
|
|
38590
38861
|
if (bridge.codexPluginSkills !== undefined)
|
|
38591
38862
|
for (const control of array(bridge.codexPluginSkills, 4096)) {
|
|
38592
|
-
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)));
|
|
38593
38864
|
text(control.name, 129);
|
|
38594
38865
|
text(control.pluginId, 1024);
|
|
38595
38866
|
text(control.namespace, 64);
|
|
38596
38867
|
text(control.pluginParent);
|
|
38597
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));
|
|
38598
38871
|
if (control.appSha256 !== undefined)
|
|
38599
38872
|
requireBound(typeof control.appSha256 === "string" && /^[a-f0-9]{64}$/.test(control.appSha256));
|
|
38600
38873
|
}
|
|
@@ -38617,13 +38890,13 @@ function assertAgentPolicyCollections(policy) {
|
|
|
38617
38890
|
text(source.path);
|
|
38618
38891
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
38619
38892
|
if (source.hashMode !== undefined)
|
|
38620
|
-
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));
|
|
38621
|
-
if (source.hashMode === "codex-settings-v1")
|
|
38622
|
-
requireBound(agent === "codex" && value.agent === "codex" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path &&
|
|
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")
|
|
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");
|
|
38623
38896
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3")
|
|
38624
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path &&
|
|
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");
|
|
38625
38898
|
if (source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2")
|
|
38626
|
-
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute6(source.path) && resolve5(source.path) === source.path &&
|
|
38899
|
+
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) === "known_marketplaces.json");
|
|
38627
38900
|
if (source.hashMode === "claude-plugin-registry") {
|
|
38628
38901
|
requireBound(agent === "claude");
|
|
38629
38902
|
const managed = array(source.managedPlugins, 64);
|
|
@@ -38732,7 +39005,7 @@ function requiresCliSkillLoading(dataDir2 = getDataDirReadOnly()) {
|
|
|
38732
39005
|
}
|
|
38733
39006
|
|
|
38734
39007
|
// src/lib/agent-bridge.ts
|
|
38735
|
-
import { createHash as
|
|
39008
|
+
import { createHash as createHash8 } from "crypto";
|
|
38736
39009
|
import { lstatSync as lstatSync8, readFileSync as readFileSync9, readdirSync as readdirSync4 } from "fs";
|
|
38737
39010
|
import { join as join12 } from "path";
|
|
38738
39011
|
var CLI_BRIDGE_NAME = "skills-cli";
|
|
@@ -38751,7 +39024,7 @@ Use the Skills CLI as the skill authority for this station.
|
|
|
38751
39024
|
|
|
38752
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.
|
|
38753
39026
|
`;
|
|
38754
|
-
var CLI_BRIDGE_DIGEST =
|
|
39027
|
+
var CLI_BRIDGE_DIGEST = createHash8("sha256").update(markdown).digest("hex");
|
|
38755
39028
|
var CLI_BRIDGE_FILES = Object.freeze({
|
|
38756
39029
|
"SKILL.md": markdown,
|
|
38757
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)}
|
|
@@ -38775,9 +39048,9 @@ function isOwnedCliBridge(path, expectedPaths) {
|
|
|
38775
39048
|
}
|
|
38776
39049
|
|
|
38777
39050
|
// src/lib/agent-discovery.ts
|
|
38778
|
-
import { createHash as
|
|
39051
|
+
import { createHash as createHash17 } from "crypto";
|
|
38779
39052
|
import { lstatSync as lstatSync18, readFileSync as readFileSync13, readdirSync as readdirSync7, realpathSync as realpathSync6 } from "fs";
|
|
38780
|
-
import { basename as
|
|
39053
|
+
import { basename as basename7, dirname as dirname14, isAbsolute as isAbsolute16, join as join21, resolve as resolve14, sep as sep4 } from "path";
|
|
38781
39054
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
38782
39055
|
|
|
38783
39056
|
// node_modules/yaml/dist/index.js
|
|
@@ -39034,17 +39307,17 @@ if (failed) process.exitCode = 2;
|
|
|
39034
39307
|
}
|
|
39035
39308
|
|
|
39036
39309
|
// src/lib/agent-discovery-directories.ts
|
|
39037
|
-
import { createHash as
|
|
39310
|
+
import { createHash as createHash9 } from "crypto";
|
|
39038
39311
|
import { lstatSync as lstatSync10, opendirSync as opendirSync2 } from "fs";
|
|
39039
39312
|
import { dirname as dirname7, isAbsolute as isAbsolute8, join as join14, resolve as resolve7 } from "path";
|
|
39040
|
-
function
|
|
39313
|
+
function need4(value, message) {
|
|
39041
39314
|
if (!value)
|
|
39042
39315
|
throw new Error(message);
|
|
39043
39316
|
}
|
|
39044
39317
|
function safe(path) {
|
|
39045
|
-
|
|
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");
|
|
39046
39319
|
for (let cursor = path;; cursor = dirname7(cursor)) {
|
|
39047
|
-
|
|
39320
|
+
need4(!lstatSync10(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
|
|
39048
39321
|
if (dirname7(cursor) === cursor)
|
|
39049
39322
|
break;
|
|
39050
39323
|
}
|
|
@@ -39057,55 +39330,55 @@ function capture(path, budget) {
|
|
|
39057
39330
|
const root = lstatSync10(path, { throwIfNoEntry: false });
|
|
39058
39331
|
if (!root)
|
|
39059
39332
|
return { path, sha256: null };
|
|
39060
|
-
|
|
39061
|
-
const hash2 =
|
|
39062
|
-
function walk2(current,
|
|
39063
|
-
|
|
39333
|
+
need4(root.isDirectory(), "Unsupported native discovery directory input");
|
|
39334
|
+
const hash2 = createHash9("sha256");
|
|
39335
|
+
function walk2(current, relative4, before, depth) {
|
|
39336
|
+
need4(depth <= 64, "Native discovery directory depth limit exceeded");
|
|
39064
39337
|
const names = [], directory = opendirSync2(current);
|
|
39065
39338
|
try {
|
|
39066
39339
|
for (let entry = directory.readSync();entry; entry = directory.readSync()) {
|
|
39067
|
-
|
|
39340
|
+
need4(++budget.entries <= AGENT_POLICY_LIMITS.discoveryDirectoryEntries, "Native discovery directory entry limit exceeded");
|
|
39068
39341
|
names.push(entry.name);
|
|
39069
39342
|
}
|
|
39070
39343
|
} finally {
|
|
39071
39344
|
directory.closeSync();
|
|
39072
39345
|
}
|
|
39073
|
-
|
|
39346
|
+
need4(new Set(names).size === names.length, "Ambiguous native discovery directory names");
|
|
39074
39347
|
for (const name of names.sort()) {
|
|
39075
|
-
const child = join14(current, name), childRelative =
|
|
39076
|
-
|
|
39348
|
+
const child = join14(current, name), childRelative = relative4 ? `${relative4}/${name}` : name;
|
|
39349
|
+
need4(child.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
|
|
39077
39350
|
const stat = lstatSync10(child);
|
|
39078
|
-
|
|
39351
|
+
need4(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
|
|
39079
39352
|
const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
|
|
39080
39353
|
`;
|
|
39081
39354
|
budget.bytes += Buffer.byteLength(row);
|
|
39082
|
-
|
|
39355
|
+
need4(budget.bytes <= AGENT_POLICY_LIMITS.discoveryDirectoryBytes, "Native discovery directory metadata limit exceeded");
|
|
39083
39356
|
hash2.update(row);
|
|
39084
39357
|
if (stat.isDirectory())
|
|
39085
39358
|
walk2(child, childRelative, stat, depth + 1);
|
|
39086
39359
|
}
|
|
39087
|
-
|
|
39360
|
+
need4(same(before, lstatSync10(current, { throwIfNoEntry: false })), "Native discovery directory changed while reading");
|
|
39088
39361
|
}
|
|
39089
39362
|
walk2(path, "", root, 0);
|
|
39090
39363
|
safe(path);
|
|
39091
39364
|
return { path, sha256: hash2.digest("hex") };
|
|
39092
39365
|
}
|
|
39093
39366
|
function captureDiscoveryDirectories(paths) {
|
|
39094
|
-
|
|
39367
|
+
need4(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
|
|
39095
39368
|
const budget = { entries: 0, bytes: 0 };
|
|
39096
39369
|
return paths.map((path) => capture(path, budget));
|
|
39097
39370
|
}
|
|
39098
39371
|
function verifyDiscoveryDirectories(directories) {
|
|
39099
|
-
|
|
39372
|
+
need4(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
|
|
39100
39373
|
for (const directory of directories)
|
|
39101
|
-
|
|
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");
|
|
39102
39375
|
const current = captureDiscoveryDirectories(directories.map((directory) => directory.path));
|
|
39103
39376
|
for (let i = 0;i < directories.length; i++)
|
|
39104
|
-
|
|
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}`);
|
|
39105
39378
|
}
|
|
39106
39379
|
|
|
39107
39380
|
// src/lib/agent-discovery-bytes.ts
|
|
39108
|
-
import { createHash as
|
|
39381
|
+
import { createHash as createHash10 } from "crypto";
|
|
39109
39382
|
import { closeSync as closeSync11, constants as constants7, fstatSync as fstatSync11, lstatSync as lstatSync11, openSync as openSync11, readSync as readSync6 } from "fs";
|
|
39110
39383
|
import { dirname as dirname8, isAbsolute as isAbsolute9, resolve as resolve8 } from "path";
|
|
39111
39384
|
function discoveryByteBudget() {
|
|
@@ -39136,7 +39409,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
|
|
|
39136
39409
|
if (bytes > AGENT_POLICY_LIMITS.discoveryRawSourceBytes)
|
|
39137
39410
|
throw new Error("Raw discovery file byte limit exceeded");
|
|
39138
39411
|
consume(budget, bytes);
|
|
39139
|
-
return
|
|
39412
|
+
return createHash10("sha256").update(text2).digest("hex");
|
|
39140
39413
|
}
|
|
39141
39414
|
const initial = lstatSync11(path, { throwIfNoEntry: false });
|
|
39142
39415
|
if (!initial)
|
|
@@ -39150,7 +39423,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
|
|
|
39150
39423
|
const opened = fstatSync11(fd);
|
|
39151
39424
|
if (!opened.isFile() || !same2(initial, opened))
|
|
39152
39425
|
throw new Error("Raw discovery input changed during open");
|
|
39153
|
-
const hash2 =
|
|
39426
|
+
const hash2 = createHash10("sha256"), buffer = Buffer.alloc(64 * 1024);
|
|
39154
39427
|
let bytes = 0;
|
|
39155
39428
|
while (true) {
|
|
39156
39429
|
const count = readSync6(fd, buffer, 0, Math.min(buffer.length, AGENT_POLICY_LIMITS.discoveryRawSourceBytes - bytes + 1), null);
|
|
@@ -39173,7 +39446,7 @@ function hashRawDiscoveryFile(path, budget, changes) {
|
|
|
39173
39446
|
}
|
|
39174
39447
|
|
|
39175
39448
|
// src/lib/agent-discovery-path-bytes.ts
|
|
39176
|
-
import { createHash as
|
|
39449
|
+
import { createHash as createHash11 } from "crypto";
|
|
39177
39450
|
import { lstatSync as lstatSync12, readlinkSync as readlinkSync3 } from "fs";
|
|
39178
39451
|
import { dirname as dirname9, isAbsolute as isAbsolute10, join as join15, parse as parse3, resolve as resolve9, sep as sep3 } from "path";
|
|
39179
39452
|
function identity3(stat, mutable = false) {
|
|
@@ -39186,12 +39459,12 @@ function identity3(stat, mutable = false) {
|
|
|
39186
39459
|
...mutable ? { size: String(stat.size), mtimeNs: String(stat.mtimeNs), ctimeNs: String(stat.ctimeNs) } : {}
|
|
39187
39460
|
};
|
|
39188
39461
|
}
|
|
39189
|
-
function
|
|
39462
|
+
function canonical4(path) {
|
|
39190
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)
|
|
39191
39464
|
throw new Error("Expected a canonical absolute discovery path");
|
|
39192
39465
|
}
|
|
39193
39466
|
function trace(path) {
|
|
39194
|
-
|
|
39467
|
+
canonical4(path);
|
|
39195
39468
|
const rows = [], paths = [];
|
|
39196
39469
|
let metadataBytes = 0, steps = 0, links = 0, cursor = parse3(path).root, pending = path.slice(cursor.length).split(sep3);
|
|
39197
39470
|
function record3(path2, row) {
|
|
@@ -39283,19 +39556,19 @@ function hashDiscoveryPathFile(path, budget, changes) {
|
|
|
39283
39556
|
const after = trace(path);
|
|
39284
39557
|
if (JSON.stringify(before.rows) !== JSON.stringify(after.rows) || before.file !== after.file)
|
|
39285
39558
|
throw new Error("Discovery path input changed during read");
|
|
39286
|
-
return
|
|
39559
|
+
return createHash11("sha256").update(JSON.stringify({ version: 1, path, rows: before.rows, content })).digest("hex");
|
|
39287
39560
|
}
|
|
39288
39561
|
|
|
39289
39562
|
// src/lib/plugin-discovery.ts
|
|
39290
39563
|
import { closeSync as closeSync13, constants as constants9, fstatSync as fstatSync13, lstatSync as lstatSync15, openSync as openSync13, opendirSync as opendirSync4, readSync as readSync8 } from "fs";
|
|
39291
|
-
import { basename as
|
|
39564
|
+
import { basename as basename5, dirname as dirname11, isAbsolute as isAbsolute14, join as join20, resolve as resolve12 } from "path";
|
|
39292
39565
|
|
|
39293
39566
|
// src/lib/plugin-admission.ts
|
|
39294
39567
|
import { homedir as homedir2 } from "os";
|
|
39295
39568
|
import { isAbsolute as isAbsolute13, join as join19, resolve as resolve11 } from "path";
|
|
39296
39569
|
|
|
39297
39570
|
// src/lib/plugin-projection.ts
|
|
39298
|
-
import { createHash as
|
|
39571
|
+
import { createHash as createHash12 } from "crypto";
|
|
39299
39572
|
import { posix as posix2 } from "path";
|
|
39300
39573
|
var PLUGIN_PROJECTION_MANIFEST = "plugin-projection.json";
|
|
39301
39574
|
var PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
|
|
@@ -39306,7 +39579,7 @@ function pluginNeed(value, message) {
|
|
|
39306
39579
|
if (!value)
|
|
39307
39580
|
pluginRefusal(message);
|
|
39308
39581
|
}
|
|
39309
|
-
var pluginHash = (bytes) =>
|
|
39582
|
+
var pluginHash = (bytes) => createHash12("sha256").update(bytes).digest("hex");
|
|
39310
39583
|
function pluginObject(value) {
|
|
39311
39584
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
39312
39585
|
}
|
|
@@ -39494,7 +39767,7 @@ function buildPluginProjection(entries) {
|
|
|
39494
39767
|
}
|
|
39495
39768
|
|
|
39496
39769
|
// src/lib/plugin-projection-store.ts
|
|
39497
|
-
import { createHash as
|
|
39770
|
+
import { createHash as createHash13, randomUUID as randomUUID2 } from "crypto";
|
|
39498
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";
|
|
39499
39772
|
import { dirname as dirname10, isAbsolute as isAbsolute11, join as join16, parse as parse5, resolve as resolve10 } from "path";
|
|
39500
39773
|
var READ_FLAGS = constants8.O_RDONLY | constants8.O_NOFOLLOW | constants8.O_NONBLOCK;
|
|
@@ -39510,7 +39783,7 @@ function stat(path) {
|
|
|
39510
39783
|
return pluginRefusal("Cannot inspect plugin filesystem entry");
|
|
39511
39784
|
}
|
|
39512
39785
|
}
|
|
39513
|
-
function
|
|
39786
|
+
function canonical5(path) {
|
|
39514
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");
|
|
39515
39788
|
}
|
|
39516
39789
|
function owner(stats, system = false) {
|
|
@@ -39521,7 +39794,7 @@ function same3(left, right, identityOnly = false) {
|
|
|
39521
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");
|
|
39522
39795
|
}
|
|
39523
39796
|
function ancestors(path, create = false) {
|
|
39524
|
-
|
|
39797
|
+
canonical5(path);
|
|
39525
39798
|
const result = [], parent = dirname10(path), filesystemRoot = parse5(parent).root;
|
|
39526
39799
|
let current = filesystemRoot;
|
|
39527
39800
|
for (const segment of ["", ...parent.slice(filesystemRoot.length).split("/").filter(Boolean)]) {
|
|
@@ -39631,7 +39904,7 @@ function directoryNames(path) {
|
|
|
39631
39904
|
function snapshotPluginTree(root, options = {}) {
|
|
39632
39905
|
const chain = ancestors(root), entries = [], files = [], directories = [];
|
|
39633
39906
|
let bytes = 0, visited = 0;
|
|
39634
|
-
const visit2 = (directory,
|
|
39907
|
+
const visit2 = (directory, relative4) => {
|
|
39635
39908
|
const before = stat(directory);
|
|
39636
39909
|
pluginNeed(before && before.isDirectory() && !before.isSymbolicLink(), "Plugin tree must contain real directories");
|
|
39637
39910
|
const names = directoryNames(directory);
|
|
@@ -39639,18 +39912,18 @@ function snapshotPluginTree(root, options = {}) {
|
|
|
39639
39912
|
directories.push({ path: directory, stat: before, names });
|
|
39640
39913
|
for (const name of names) {
|
|
39641
39914
|
pluginNeed(++visited <= PLUGIN_PROJECTION_LIMITS.files * 50, "Plugin tree membership exceeds its limit");
|
|
39642
|
-
const path =
|
|
39915
|
+
const path = relative4 ? `${relative4}/${name}` : name;
|
|
39643
39916
|
pluginNeed(new TextEncoder().encode(path).byteLength <= 100 && !/[\\:\x00-\x1f\x7f]/u.test(path), "Plugin entry path exceeds its limit or is unsafe");
|
|
39644
39917
|
const absolute = join16(directory, name), entryStat = stat(absolute);
|
|
39645
39918
|
pluginNeed(entryStat, "Plugin tree member disappeared");
|
|
39646
|
-
if (
|
|
39919
|
+
if (relative4 === "" && name === ".orphaned_at" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
39647
39920
|
const bytes2 = readBytes(absolute, 32, "native-pin");
|
|
39648
39921
|
pluginNeed(/^[1-9][0-9]{12}$/.test(new TextDecoder().decode(bytes2)), "Malformed native orphan timestamp");
|
|
39649
39922
|
same3(entryStat, stat(absolute));
|
|
39650
39923
|
files.push({ path: absolute, stat: entryStat });
|
|
39651
39924
|
continue;
|
|
39652
39925
|
}
|
|
39653
|
-
if (
|
|
39926
|
+
if (relative4 === "" && name === ".in_use" && (options.nativeRuntime === "claude-2.1.274" || options.nativeRuntime === "claude-2.1.276")) {
|
|
39654
39927
|
pluginNeed(entryStat.isDirectory() && !entryStat.isSymbolicLink(), "Native plugin pins require a real directory");
|
|
39655
39928
|
owner(entryStat);
|
|
39656
39929
|
const pins = directoryNames(absolute);
|
|
@@ -39836,7 +40109,7 @@ function pluginExecutableDigest(path) {
|
|
|
39836
40109
|
const opened = fstatSync12(fd, { bigint: true });
|
|
39837
40110
|
same3(before, opened);
|
|
39838
40111
|
fileShape(opened, maximum, "executable");
|
|
39839
|
-
const hash2 =
|
|
40112
|
+
const hash2 = createHash13("sha256"), buffer = new Uint8Array(64 * 1024);
|
|
39840
40113
|
let remaining = Number(opened.size);
|
|
39841
40114
|
while (remaining > 0) {
|
|
39842
40115
|
const count = readSync7(fd, buffer, 0, Math.min(buffer.byteLength, remaining), null);
|
|
@@ -39861,7 +40134,7 @@ function pluginExecutableDigest(path) {
|
|
|
39861
40134
|
|
|
39862
40135
|
// src/lib/skill-validation.ts
|
|
39863
40136
|
import { existsSync as existsSync5, lstatSync as lstatSync14, readFileSync as readFileSync12, readdirSync as readdirSync6, statSync as statSync5 } from "fs";
|
|
39864
|
-
import { isAbsolute as isAbsolute12, join as join18, normalize as
|
|
40137
|
+
import { isAbsolute as isAbsolute12, join as join18, normalize as normalize3 } from "path";
|
|
39865
40138
|
|
|
39866
40139
|
// src/lib/hosted-skill-set.ts
|
|
39867
40140
|
import { existsSync as existsSync4, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
@@ -39967,7 +40240,7 @@ function sortMessages(messages) {
|
|
|
39967
40240
|
function isSafeRelativePath(value) {
|
|
39968
40241
|
if (!value.trim() || isAbsolute12(value))
|
|
39969
40242
|
return false;
|
|
39970
|
-
const normalized =
|
|
40243
|
+
const normalized = normalize3(value).replace(/\\/g, "/");
|
|
39971
40244
|
return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
|
|
39972
40245
|
}
|
|
39973
40246
|
function validateRuntimeEntry(skillPath, entrypoint, issues, warnings) {
|
|
@@ -40769,7 +41042,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
40769
41042
|
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join20(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
40770
41043
|
const approval = (producer) => {
|
|
40771
41044
|
pluginText(producer);
|
|
40772
|
-
const digest2 = `sha256:${
|
|
41045
|
+
const digest2 = `sha256:${basename5(producer)}`;
|
|
40773
41046
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest2);
|
|
40774
41047
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
40775
41048
|
if (!verified.has(producer)) {
|
|
@@ -40831,23 +41104,23 @@ function captureManagedPluginRegistry(path, managedPlugins) {
|
|
|
40831
41104
|
}
|
|
40832
41105
|
|
|
40833
41106
|
// src/lib/claude-marketplace-registry.ts
|
|
40834
|
-
import { createHash as
|
|
41107
|
+
import { createHash as createHash14 } from "crypto";
|
|
40835
41108
|
import { closeSync as closeSync14, constants as constants10, fstatSync as fstatSync14, lstatSync as lstatSync16, openSync as openSync14, readSync as readSync9 } from "fs";
|
|
40836
|
-
import { basename as
|
|
41109
|
+
import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute15, resolve as resolve13 } from "path";
|
|
40837
41110
|
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
40838
|
-
function
|
|
41111
|
+
function need5(value, reason) {
|
|
40839
41112
|
if (!value)
|
|
40840
41113
|
throw new Error(`Claude marketplace registry ${reason}`);
|
|
40841
41114
|
}
|
|
40842
41115
|
function absolutePath3(value) {
|
|
40843
|
-
|
|
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");
|
|
40844
41117
|
}
|
|
40845
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;
|
|
40846
41119
|
function parents2(path) {
|
|
40847
41120
|
const result = [];
|
|
40848
41121
|
for (let at = dirname12(path);; at = dirname12(at)) {
|
|
40849
41122
|
const stat2 = lstatSync16(at, { bigint: true });
|
|
40850
|
-
|
|
41123
|
+
need5(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
40851
41124
|
result.push([at, stat2]);
|
|
40852
41125
|
if (at === dirname12(at))
|
|
40853
41126
|
return result;
|
|
@@ -40855,15 +41128,15 @@ function parents2(path) {
|
|
|
40855
41128
|
}
|
|
40856
41129
|
function readRegistry2(path, budget) {
|
|
40857
41130
|
absolutePath3(path);
|
|
40858
|
-
|
|
40859
|
-
|
|
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");
|
|
40860
41133
|
const ancestors2 = parents2(path), initial = lstatSync16(path, { bigint: true });
|
|
40861
|
-
|
|
40862
|
-
|
|
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");
|
|
40863
41136
|
const fd = openSync14(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
|
|
40864
41137
|
try {
|
|
40865
41138
|
const opened = fstatSync14(fd, { bigint: true });
|
|
40866
|
-
|
|
41139
|
+
need5(opened.isFile() && sameFile2(initial, opened), "changed during open");
|
|
40867
41140
|
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
40868
41141
|
let length = 0;
|
|
40869
41142
|
while (length < bytes.length) {
|
|
@@ -40873,10 +41146,10 @@ function readRegistry2(path, budget) {
|
|
|
40873
41146
|
length += count;
|
|
40874
41147
|
}
|
|
40875
41148
|
const after = fstatSync14(fd, { bigint: true }), current = lstatSync16(path, { bigint: true });
|
|
40876
|
-
|
|
41149
|
+
need5(current.isFile() && sameFile2(opened, after) && sameFile2(after, current) && BigInt(length) === opened.size, "changed during read");
|
|
40877
41150
|
for (const [ancestor, before] of ancestors2) {
|
|
40878
41151
|
const now = lstatSync16(ancestor, { bigint: true });
|
|
40879
|
-
|
|
41152
|
+
need5(now.isDirectory() && before.dev === now.dev && before.ino === now.ino && before.mode === now.mode, "parent changed during read");
|
|
40880
41153
|
}
|
|
40881
41154
|
budget.remaining -= length;
|
|
40882
41155
|
try {
|
|
@@ -40896,7 +41169,7 @@ function parse6(text2) {
|
|
|
40896
41169
|
at++;
|
|
40897
41170
|
};
|
|
40898
41171
|
function string() {
|
|
40899
|
-
|
|
41172
|
+
need5(text2[at] === '"', "contains invalid JSON");
|
|
40900
41173
|
const start = at++;
|
|
40901
41174
|
while (at < text2.length) {
|
|
40902
41175
|
const character = text2[at++];
|
|
@@ -40907,7 +41180,7 @@ function parse6(text2) {
|
|
|
40907
41180
|
} catch {
|
|
40908
41181
|
throw new Error("Claude marketplace registry contains invalid JSON string");
|
|
40909
41182
|
}
|
|
40910
|
-
|
|
41183
|
+
need5(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
|
|
40911
41184
|
return value2;
|
|
40912
41185
|
}
|
|
40913
41186
|
if (character === "\\")
|
|
@@ -40916,7 +41189,7 @@ function parse6(text2) {
|
|
|
40916
41189
|
throw new Error("Claude marketplace registry contains an unterminated JSON string");
|
|
40917
41190
|
}
|
|
40918
41191
|
function value(depth) {
|
|
40919
|
-
|
|
41192
|
+
need5(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
40920
41193
|
space();
|
|
40921
41194
|
const character = text2[at];
|
|
40922
41195
|
if (character === '"')
|
|
@@ -40930,17 +41203,17 @@ function parse6(text2) {
|
|
|
40930
41203
|
if (object5) {
|
|
40931
41204
|
space();
|
|
40932
41205
|
const key = string();
|
|
40933
|
-
|
|
41206
|
+
need5(!keys2.has(key), "contains a duplicate JSON key");
|
|
40934
41207
|
keys2.add(key);
|
|
40935
41208
|
space();
|
|
40936
|
-
|
|
41209
|
+
need5(text2[at++] === ":", "contains invalid JSON");
|
|
40937
41210
|
entries.push([key, value(depth + 1)]);
|
|
40938
41211
|
} else
|
|
40939
41212
|
items.push(value(depth + 1));
|
|
40940
41213
|
space();
|
|
40941
41214
|
if (text2[at] === end)
|
|
40942
41215
|
break;
|
|
40943
|
-
|
|
41216
|
+
need5(text2[at++] === ",", "contains invalid JSON");
|
|
40944
41217
|
}
|
|
40945
41218
|
at++;
|
|
40946
41219
|
return object5 ? { kind: "object", entries } : { kind: "array", items };
|
|
@@ -40952,14 +41225,14 @@ function parse6(text2) {
|
|
|
40952
41225
|
}
|
|
40953
41226
|
numberPattern.lastIndex = at;
|
|
40954
41227
|
const number = numberPattern.exec(text2);
|
|
40955
|
-
|
|
41228
|
+
need5(number, "contains invalid JSON");
|
|
40956
41229
|
at += number[0].length;
|
|
40957
41230
|
return { kind: "number", value: number[0] };
|
|
40958
41231
|
}
|
|
40959
41232
|
const root2 = value(0);
|
|
40960
41233
|
space();
|
|
40961
|
-
|
|
40962
|
-
|
|
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");
|
|
40963
41236
|
return root2;
|
|
40964
41237
|
}
|
|
40965
41238
|
function exactKeys2(value, keys2) {
|
|
@@ -40967,7 +41240,7 @@ function exactKeys2(value, keys2) {
|
|
|
40967
41240
|
}
|
|
40968
41241
|
var field = (object5, key) => object5.entries.find(([name]) => name === key)?.[1];
|
|
40969
41242
|
function textField(value) {
|
|
40970
|
-
|
|
41243
|
+
need5(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
|
|
40971
41244
|
return value.value;
|
|
40972
41245
|
}
|
|
40973
41246
|
function normalizeRow(row, version = 1) {
|
|
@@ -40975,7 +41248,7 @@ function normalizeRow(row, version = 1) {
|
|
|
40975
41248
|
if (version !== 2 || !exactKeys2(row, ["source", "installLocation", "lastUpdated", "autoUpdate"]))
|
|
40976
41249
|
return;
|
|
40977
41250
|
const autoUpdate = field(row, "autoUpdate");
|
|
40978
|
-
|
|
41251
|
+
need5(autoUpdate?.kind === "literal" && (autoUpdate.value === "true" || autoUpdate.value === "false"), "contains an invalid automatic-update preference");
|
|
40979
41252
|
}
|
|
40980
41253
|
const source = field(row, "source");
|
|
40981
41254
|
if (source?.kind !== "object")
|
|
@@ -40991,34 +41264,34 @@ function normalizeRow(row, version = 1) {
|
|
|
40991
41264
|
absolutePath3(sourceLocation);
|
|
40992
41265
|
absolutePath3(textField(field(row, "installLocation")));
|
|
40993
41266
|
const updated = textField(field(row, "lastUpdated"));
|
|
40994
|
-
|
|
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");
|
|
40995
41268
|
const millis = Date.parse(updated);
|
|
40996
|
-
|
|
41269
|
+
need5(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
|
|
40997
41270
|
row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
|
|
40998
41271
|
}
|
|
40999
41272
|
function captureClaudeMarketplaceRegistry(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
41000
41273
|
const value = parse6(readRegistry2(path, budget));
|
|
41001
41274
|
for (const [, row] of value.entries)
|
|
41002
41275
|
normalizeRow(row);
|
|
41003
|
-
const sha2562 =
|
|
41276
|
+
const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
41004
41277
|
return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
|
|
41005
41278
|
}
|
|
41006
41279
|
function captureClaudeMarketplaceRegistryV2(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
41007
41280
|
const value = parse6(readRegistry2(path, budget));
|
|
41008
41281
|
for (const [, row] of value.entries)
|
|
41009
41282
|
normalizeRow(row, 2);
|
|
41010
|
-
const sha2562 =
|
|
41283
|
+
const sha2562 = createHash14("sha256").update("hasna.skills.claude-marketplace-registry.v2\x00").update(JSON.stringify(value)).digest("hex");
|
|
41011
41284
|
return { path, hashMode: "claude-marketplace-registry-v2", sha256: sha2562 };
|
|
41012
41285
|
}
|
|
41013
41286
|
|
|
41014
41287
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
41015
|
-
import { createHash as
|
|
41288
|
+
import { createHash as createHash16 } from "crypto";
|
|
41016
41289
|
|
|
41017
41290
|
// src/lib/codex-hook-trust-files.ts
|
|
41018
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";
|
|
41019
|
-
import { createHash as
|
|
41292
|
+
import { createHash as createHash15 } from "crypto";
|
|
41020
41293
|
import { dirname as dirname13 } from "path";
|
|
41021
|
-
function
|
|
41294
|
+
function need6(value, code) {
|
|
41022
41295
|
if (!value)
|
|
41023
41296
|
throw new Error(`CODEX_HOOK_TRUST_${code}`);
|
|
41024
41297
|
}
|
|
@@ -41026,8 +41299,8 @@ var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs
|
|
|
41026
41299
|
function safeParents(file) {
|
|
41027
41300
|
for (let p = dirname13(file);; p = dirname13(p)) {
|
|
41028
41301
|
const s = lstatSync17(p);
|
|
41029
|
-
|
|
41030
|
-
|
|
41302
|
+
need6(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
|
|
41303
|
+
need6((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
|
|
41031
41304
|
if (dirname13(p) === p)
|
|
41032
41305
|
break;
|
|
41033
41306
|
}
|
|
@@ -41036,12 +41309,12 @@ function snapshot(file, privateFile = false, options = {}) {
|
|
|
41036
41309
|
const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
|
|
41037
41310
|
safeParents(file);
|
|
41038
41311
|
const initial = lstatSync17(file, { bigint: true });
|
|
41039
|
-
|
|
41040
|
-
|
|
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");
|
|
41041
41314
|
const fd = openSync15(file, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
|
|
41042
41315
|
try {
|
|
41043
41316
|
const before = fstatSync15(fd, { bigint: true });
|
|
41044
|
-
|
|
41317
|
+
need6(sameStat(initial, before), "INPUT_CHANGED");
|
|
41045
41318
|
const bytes = Buffer.alloc(Number(before.size) + 1);
|
|
41046
41319
|
let length = 0;
|
|
41047
41320
|
while (length < bytes.length) {
|
|
@@ -41050,16 +41323,16 @@ function snapshot(file, privateFile = false, options = {}) {
|
|
|
41050
41323
|
break;
|
|
41051
41324
|
length += n2;
|
|
41052
41325
|
}
|
|
41053
|
-
|
|
41326
|
+
need6(length === Number(before.size) && sameStat(before, fstatSync15(fd, { bigint: true })) && sameStat(before, lstatSync17(file, { bigint: true })), "INPUT_CHANGED");
|
|
41054
41327
|
const content = bytes.subarray(0, length), text2 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
41055
|
-
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") };
|
|
41056
41329
|
} finally {
|
|
41057
41330
|
closeSync15(fd);
|
|
41058
41331
|
}
|
|
41059
41332
|
}
|
|
41060
41333
|
function unchanged2(before) {
|
|
41061
41334
|
const after = snapshot(before.file, before.privateFile, before.readOnlyPackage ? { readOnlyPackage: true } : {});
|
|
41062
|
-
|
|
41335
|
+
need6(sameStat(before.stat, after.stat) && after.sha256 === before.sha256, "INPUT_CHANGED");
|
|
41063
41336
|
}
|
|
41064
41337
|
|
|
41065
41338
|
// src/lib/codex-hook-additions-review.ts
|
|
@@ -41068,11 +41341,12 @@ var matchedEvents = { ...events, PreToolUse: ["preToolUse", "pre_tool_use"] };
|
|
|
41068
41341
|
var proofs = new WeakMap;
|
|
41069
41342
|
|
|
41070
41343
|
// src/lib/codex-hook-discovery-recovery.ts
|
|
41071
|
-
var
|
|
41344
|
+
var sha3 = (text2) => createHash16("sha256").update(text2).digest("hex");
|
|
41345
|
+
var fields = [...CODEX_DISCOVERY_PROJECTION_FIELDS];
|
|
41072
41346
|
var proofs2 = new WeakMap;
|
|
41073
41347
|
function assertCodexHookDiscoveryRecovery(binding, witness) {
|
|
41074
41348
|
const proof = proofs2.get(witness);
|
|
41075
|
-
|
|
41349
|
+
need6(!!proof && binding.agent === "codex" && witness.discoverySha256 === sha3(JSON.stringify(binding)), "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
41076
41350
|
unchanged2(proof.before);
|
|
41077
41351
|
unchanged2(proof.current);
|
|
41078
41352
|
proof.recheckAdditions();
|
|
@@ -41081,12 +41355,12 @@ function verifiesCodexHookDiscoverySource(binding, source, currentDigest, witnes
|
|
|
41081
41355
|
if (!witness || source.path !== witness.configPath || source.hashMode !== "bytes")
|
|
41082
41356
|
return false;
|
|
41083
41357
|
assertCodexHookDiscoveryRecovery(binding, witness);
|
|
41084
|
-
|
|
41358
|
+
need6(source.sha256 === witness.beforeSha256 && currentDigest === witness.currentSha256, "RECONCILE_DISCOVERY_RECOVERY_CHANGED");
|
|
41085
41359
|
return true;
|
|
41086
41360
|
}
|
|
41087
41361
|
|
|
41088
41362
|
// src/lib/agent-discovery.ts
|
|
41089
|
-
var digest2 = (text2) =>
|
|
41363
|
+
var digest2 = (text2) => createHash17("sha256").update(text2).digest("hex");
|
|
41090
41364
|
function parseConfig(text2, path, toml = false) {
|
|
41091
41365
|
try {
|
|
41092
41366
|
const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
|
|
@@ -41118,14 +41392,26 @@ function read2(path, changes) {
|
|
|
41118
41392
|
throw new Error(`Unsupported or oversized native discovery input: ${path}`);
|
|
41119
41393
|
return readFileSync13(path, "utf8");
|
|
41120
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
|
+
}
|
|
41121
41407
|
function projected(source, changes, budget = discoveryByteBudget()) {
|
|
41122
|
-
if (source.hashMode === "codex-settings-v1") {
|
|
41408
|
+
if (source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") {
|
|
41123
41409
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
41124
41410
|
throw new Error("Codex settings witnesses require exact typed metadata");
|
|
41125
|
-
const current = captureCodexSettings(source.path, budget).sha256;
|
|
41411
|
+
const current = (source.hashMode === "codex-settings-v2" ? captureCodexSettingsV2 : captureCodexSettings)(source.path, budget).sha256;
|
|
41126
41412
|
if (current !== source.sha256)
|
|
41127
41413
|
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
41128
|
-
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;
|
|
41129
41415
|
}
|
|
41130
41416
|
if (source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") {
|
|
41131
41417
|
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
@@ -41164,10 +41450,7 @@ function projected(source, changes, budget = discoveryByteBudget()) {
|
|
|
41164
41450
|
return null;
|
|
41165
41451
|
if (!source.format)
|
|
41166
41452
|
return digest2(text2);
|
|
41167
|
-
|
|
41168
|
-
if (!object5 || typeof object5 !== "object" || Array.isArray(object5))
|
|
41169
|
-
throw new Error("Expected native discovery configuration object");
|
|
41170
|
-
return digest2(JSON.stringify(Object.fromEntries((source.fields ?? []).map((field2) => [field2, object5[field2] ?? null]))));
|
|
41453
|
+
return projectNativeDiscoveryFields(text2, source.format, source.fields ?? [], source.path);
|
|
41171
41454
|
}
|
|
41172
41455
|
function verifyAgentDiscovery(binding, codexRecovery) {
|
|
41173
41456
|
if (codexRecovery)
|
|
@@ -41195,9 +41478,9 @@ function verifyAgentDiscovery(binding, codexRecovery) {
|
|
|
41195
41478
|
safe4(root2);
|
|
41196
41479
|
}
|
|
41197
41480
|
function assertMarketplaceBinding(binding, source) {
|
|
41198
|
-
if (source.hashMode === "codex-settings-v1" && (binding.agent !== "codex" || binding.method !== "reviewed" ||
|
|
41481
|
+
if ((source.hashMode === "codex-settings-v1" || source.hashMode === "codex-settings-v2") && (binding.agent !== "codex" || binding.method !== "reviewed" || basename7(source.path) !== "config.toml"))
|
|
41199
41482
|
throw new Error("Codex settings witnesses require explicit reviewed Codex configuration");
|
|
41200
|
-
if ((source.hashMode === "claude-settings-v1" || source.hashMode === "claude-settings-v2" || source.hashMode === "claude-settings-v3") && (binding.agent !== "claude" || binding.method !== "reviewed" ||
|
|
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"))
|
|
41201
41484
|
throw new Error("Claude settings witnesses require explicit reviewed Claude configuration");
|
|
41202
41485
|
if ((source.hashMode === "claude-marketplace-registry" || source.hashMode === "claude-marketplace-registry-v2") && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
41203
41486
|
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
@@ -41224,8 +41507,8 @@ function captureDiscoveryPathSources(paths) {
|
|
|
41224
41507
|
const budget = discoveryByteBudget();
|
|
41225
41508
|
return paths.map((path) => ({ path, hashMode: "path-bytes", sha256: hashDiscoveryPathFile(path, budget) }));
|
|
41226
41509
|
}
|
|
41227
|
-
function assertProjectDiscovery(agent, directories, home,
|
|
41228
|
-
const homeConfigPath =
|
|
41510
|
+
function assertProjectDiscovery(agent, directories, home, canonical6 = resolve14, reviewed) {
|
|
41511
|
+
const homeConfigPath = canonical6(agentDiscoveryConfigPath(home, agent));
|
|
41229
41512
|
for (const directory of directories) {
|
|
41230
41513
|
const isHome = resolve14(directory) === resolve14(home);
|
|
41231
41514
|
if (agent === "hermes") {
|
|
@@ -41236,7 +41519,7 @@ function assertProjectDiscovery(agent, directories, home, canonical5 = resolve14
|
|
|
41236
41519
|
continue;
|
|
41237
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"];
|
|
41238
41521
|
for (const suffix of paths) {
|
|
41239
|
-
const path =
|
|
41522
|
+
const path = canonical6(join21(directory, suffix)), raw = read2(path);
|
|
41240
41523
|
if (raw === null)
|
|
41241
41524
|
continue;
|
|
41242
41525
|
const isRootAliasedHomeConfig = agent === "claude" && suffix === ".claude/settings.json" || agent === "codex" && suffix === ".codex/config.toml";
|
|
@@ -41252,14 +41535,14 @@ function assertProjectDiscovery(agent, directories, home, canonical5 = resolve14
|
|
|
41252
41535
|
const managed = reviewed.sources.flatMap((source) => source.hashMode === "claude-plugin-registry" ? source.managedPlugins ?? [] : []);
|
|
41253
41536
|
if (exact && projected(exact) === exact.sha256 && managed.length) {
|
|
41254
41537
|
const bindings = managed.map((item) => readPluginBinding(item.storeRoot, item.bindingId));
|
|
41255
|
-
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))));
|
|
41256
41539
|
}
|
|
41257
41540
|
}
|
|
41258
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)))
|
|
41259
41542
|
throw new Error(`NATIVE_SKILL_DRIFT: higher-precedence project skill or hook configuration requires review: ${path}`);
|
|
41260
41543
|
}
|
|
41261
41544
|
if (agent === "claude") {
|
|
41262
|
-
const commands =
|
|
41545
|
+
const commands = canonical6(join21(directory, ".claude/commands"));
|
|
41263
41546
|
safe4(commands);
|
|
41264
41547
|
if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
41265
41548
|
throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
|
|
@@ -41270,10 +41553,10 @@ function agentDiscoveryConfigPath(home, agent) {
|
|
|
41270
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"}`);
|
|
41271
41554
|
}
|
|
41272
41555
|
function resolveAgentDiscovery(options) {
|
|
41273
|
-
const
|
|
41556
|
+
const canonical6 = options.canonical ?? resolve14, home = resolve14(options.home), agent = options.agent;
|
|
41274
41557
|
const sources = [], roots = new Set, builtinNames = [];
|
|
41275
|
-
const witness = (path, format,
|
|
41276
|
-
const source = { path:
|
|
41558
|
+
const witness = (path, format, fields2) => {
|
|
41559
|
+
const source = { path: canonical6(path), sha256: null, ...format ? { format, fields: fields2 } : {} };
|
|
41277
41560
|
source.sha256 = projected(source);
|
|
41278
41561
|
sources.push(source);
|
|
41279
41562
|
return read2(source.path);
|
|
@@ -41281,7 +41564,7 @@ function resolveAgentDiscovery(options) {
|
|
|
41281
41564
|
if (agent === "hermes")
|
|
41282
41565
|
assertHermesEnvironment(home);
|
|
41283
41566
|
const configPath = agentDiscoveryConfigPath(home, agent);
|
|
41284
|
-
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"]);
|
|
41285
41568
|
const config = configText === null ? {} : agent === "hermes" ? parseHermesConfig(configText) : parseConfig(configText, configPath, agent === "codex");
|
|
41286
41569
|
const unresolved = (detail) => {
|
|
41287
41570
|
throw new Error(`Native discovery is unresolved (${agent}: ${detail}); provide a reviewed --discovery-inputs file`);
|
|
@@ -41340,11 +41623,12 @@ function resolveAgentDiscovery(options) {
|
|
|
41340
41623
|
if (retained.agent !== agent || retained.method !== "reviewed")
|
|
41341
41624
|
unresolved("invalid retained review");
|
|
41342
41625
|
verifyAgentDiscovery(retained);
|
|
41343
|
-
if (!retained.sources.some((source) => source.path ===
|
|
41626
|
+
if (!retained.sources.some((source) => source.path === canonical6(configPath) && source.format === undefined && source.fields === undefined))
|
|
41344
41627
|
unresolved("retained review is missing the full agent configuration source");
|
|
41345
|
-
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)))
|
|
41346
41629
|
unresolved("retained settings witness names another configuration source");
|
|
41347
|
-
|
|
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))
|
|
41348
41632
|
unresolved("retained review is missing current runtime discovery coverage");
|
|
41349
41633
|
return retained;
|
|
41350
41634
|
}
|
|
@@ -41358,14 +41642,15 @@ function resolveAgentDiscovery(options) {
|
|
|
41358
41642
|
if (review.sources.some((source) => source.format !== undefined || source.fields !== undefined))
|
|
41359
41643
|
throw new Error("Explicit discovery reviews require full source-file hashes");
|
|
41360
41644
|
verifyAgentDiscovery(supplied);
|
|
41361
|
-
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)))
|
|
41362
41646
|
throw new Error("Semantic settings witnesses must name the configured Claude configuration source");
|
|
41363
|
-
if (!review.sources.some((source) => source.path ===
|
|
41647
|
+
if (!review.sources.some((source) => source.path === canonical6(configPath)))
|
|
41364
41648
|
throw new Error("Discovery review must include the agent configuration source");
|
|
41365
|
-
|
|
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 } : {} };
|
|
41366
41651
|
}
|
|
41367
41652
|
function plugin(root2) {
|
|
41368
|
-
root2 =
|
|
41653
|
+
root2 = canonical6(root2);
|
|
41369
41654
|
safe4(root2);
|
|
41370
41655
|
const manifestPath = join21(root2, agent === "claude" ? ".claude-plugin/plugin.json" : ".codex-plugin/plugin.json");
|
|
41371
41656
|
const raw = witness(manifestPath);
|
|
@@ -41397,7 +41682,7 @@ function resolveAgentDiscovery(options) {
|
|
|
41397
41682
|
if (agent === "claude") {
|
|
41398
41683
|
const registrations = witness(join21(home, ".claude/plugins/installed_plugins.json"));
|
|
41399
41684
|
const installed = registrations === null ? {} : parseConfig(registrations, join21(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
41400
|
-
const commands =
|
|
41685
|
+
const commands = canonical6(join21(home, ".claude/commands"));
|
|
41401
41686
|
safe4(commands);
|
|
41402
41687
|
if (lstatSync18(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync7(commands).length)
|
|
41403
41688
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
@@ -41471,7 +41756,7 @@ function resolveAgentDiscovery(options) {
|
|
|
41471
41756
|
roots.add(join21(root2, "skills"));
|
|
41472
41757
|
}
|
|
41473
41758
|
}
|
|
41474
|
-
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))) } : {} };
|
|
41475
41760
|
}
|
|
41476
41761
|
|
|
41477
41762
|
// src/lib/agent-adapters.ts
|
|
@@ -41650,10 +41935,10 @@ function inlineRowsAsTables(value, newline) {
|
|
|
41650
41935
|
for (const row of rows) {
|
|
41651
41936
|
if (!row.startsWith("{") || !row.endsWith("}"))
|
|
41652
41937
|
return null;
|
|
41653
|
-
const
|
|
41654
|
-
if (!
|
|
41938
|
+
const fields2 = splitTopLevel(row.slice(1, -1), ",");
|
|
41939
|
+
if (!fields2)
|
|
41655
41940
|
return null;
|
|
41656
|
-
const lines =
|
|
41941
|
+
const lines = fields2.map((field2) => field2.trim()).filter(Boolean);
|
|
41657
41942
|
if (lines.some((line) => !/^(?:path|name|enabled)\s*=/.test(line)))
|
|
41658
41943
|
return null;
|
|
41659
41944
|
const keys2 = lines.map((line) => line.slice(0, line.indexOf("=")).trim());
|
|
@@ -41809,7 +42094,7 @@ function disableCodexBundledSkills(text2) {
|
|
|
41809
42094
|
}
|
|
41810
42095
|
|
|
41811
42096
|
// src/lib/agent-integration.ts
|
|
41812
|
-
var
|
|
42097
|
+
var sha4 = (data) => createHash18("sha256").update(data).digest("hex");
|
|
41813
42098
|
var ROOTS = NATIVE_SKILL_ROOTS;
|
|
41814
42099
|
function assertSafePath(path) {
|
|
41815
42100
|
let cursor = resolve15(path);
|
|
@@ -41833,7 +42118,7 @@ function readRootAlias(home, agent) {
|
|
|
41833
42118
|
const targetStat = lstatSync19(targetPath, { throwIfNoEntry: false });
|
|
41834
42119
|
if (!targetStat?.isDirectory())
|
|
41835
42120
|
throw new Error(`Agent root alias must target an existing directory: ${alias}`);
|
|
41836
|
-
const target = realpathSync7(targetPath), inside =
|
|
42121
|
+
const target = realpathSync7(targetPath), inside = relative4(realHome, target);
|
|
41837
42122
|
if (!inside || inside === ".." || inside.startsWith(`..${sep5}`) || isAbsolute17(inside))
|
|
41838
42123
|
throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
|
|
41839
42124
|
return { agent, home: realHome, alias, target, link, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
|
|
@@ -41851,7 +42136,7 @@ function rootAliases(home, allowed = false) {
|
|
|
41851
42136
|
}
|
|
41852
42137
|
function canonicalAgentPath(path, aliases) {
|
|
41853
42138
|
const absolute = resolve15(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep5));
|
|
41854
|
-
return binding ? join22(binding.target,
|
|
42139
|
+
return binding ? join22(binding.target, relative4(binding.alias, absolute)) : absolute;
|
|
41855
42140
|
}
|
|
41856
42141
|
function disabledCodexSkillPaths(config, aliases) {
|
|
41857
42142
|
const skills = config.skills;
|
|
@@ -41916,13 +42201,13 @@ function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
|
|
|
41916
42201
|
}
|
|
41917
42202
|
}
|
|
41918
42203
|
function treeHash(root2) {
|
|
41919
|
-
const hash2 =
|
|
42204
|
+
const hash2 = createHash18("sha256");
|
|
41920
42205
|
let bytes = 0, files = 0;
|
|
41921
42206
|
function visit2(path) {
|
|
41922
42207
|
const stat2 = lstatSync19(path);
|
|
41923
42208
|
if (stat2.isSymbolicLink())
|
|
41924
42209
|
throw new Error(`Refusing symlink in skill: ${path}`);
|
|
41925
|
-
const rel =
|
|
42210
|
+
const rel = relative4(root2, path);
|
|
41926
42211
|
if (stat2.isDirectory()) {
|
|
41927
42212
|
hash2.update(`d\x00${rel}\x00`);
|
|
41928
42213
|
for (const name of readdirSync8(path).sort())
|
|
@@ -41948,7 +42233,7 @@ function selectNativeMigrationTargets(inventory, manifest) {
|
|
|
41948
42233
|
const identities = new Set;
|
|
41949
42234
|
const selected = [];
|
|
41950
42235
|
for (const target of manifest.targets) {
|
|
41951
|
-
const projectRoot = resolve15(target.projectRoot), normalized =
|
|
42236
|
+
const projectRoot = resolve15(target.projectRoot), normalized = relative4(projectRoot, resolve15(projectRoot, target.path));
|
|
41952
42237
|
if (!isAbsolute17(target.projectRoot) || projectRoot !== target.projectRoot || !existsSync6(projectRoot) || !lstatSync19(projectRoot).isDirectory())
|
|
41953
42238
|
throw new Error(`Native migration target project root must be an existing absolute directory: ${target.projectRoot}`);
|
|
41954
42239
|
assertSafePath(projectRoot);
|
|
@@ -42301,9 +42586,9 @@ function planAgentIntegration(options) {
|
|
|
42301
42586
|
const observedNativeSources = [];
|
|
42302
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) => {
|
|
42303
42588
|
const bytes = readNativeBytes(path, 1024 * 1024);
|
|
42304
|
-
observedNativeSources.push({ path, sha256:
|
|
42589
|
+
observedNativeSources.push({ path, sha256: sha4(bytes) });
|
|
42305
42590
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
42306
|
-
}) : policy.bridge?.codexPluginSkills ?? [];
|
|
42591
|
+
}, codexConfig.skills?.config ?? []) : policy.bridge?.codexPluginSkills ?? [];
|
|
42307
42592
|
const changes = [];
|
|
42308
42593
|
for (const agent of [...new Set(options.agents)]) {
|
|
42309
42594
|
if (!INTEGRATION_AGENTS.includes(agent))
|
|
@@ -42329,7 +42614,7 @@ function planAgentIntegration(options) {
|
|
|
42329
42614
|
throw new Error("Refusing to overwrite an unrecognized Hermes supervisor");
|
|
42330
42615
|
if (supervisorBefore !== supervisorAfter)
|
|
42331
42616
|
changes.push({ path: supervisorPath, before: supervisorBefore, after: supervisorAfter });
|
|
42332
|
-
const supervisor = { path: supervisorPath, runtime: process.execPath, sha256:
|
|
42617
|
+
const supervisor = { path: supervisorPath, runtime: process.execPath, sha256: sha4(supervisorAfter) };
|
|
42333
42618
|
const after2 = configureHermesHooks(before, supervisor, previous);
|
|
42334
42619
|
if (before !== after2)
|
|
42335
42620
|
changes.push({ path, before, after: after2 });
|
|
@@ -42376,12 +42661,12 @@ function planAgentIntegration(options) {
|
|
|
42376
42661
|
agents: [...new Set([...priorAgents, ...options.agents])].sort(),
|
|
42377
42662
|
home: resolve15(home),
|
|
42378
42663
|
includeVendor: true,
|
|
42379
|
-
...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)) } } } : {},
|
|
42380
42665
|
commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
|
|
42381
42666
|
profiles: Object.fromEntries([...new Set([...priorAgents, ...options.agents])].sort().map((agent) => [agent, bindings.get(agent)?.profileId ?? policy.bridge?.profiles?.[agent] ?? policy.profileId])),
|
|
42382
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 ?? [],
|
|
42383
42668
|
rootAliases: aliases,
|
|
42384
|
-
...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 } : {},
|
|
42385
42670
|
discovery: { ...policy.bridge?.discovery, ...Object.fromEntries(discoveryAfter.map((binding) => [binding.agent, binding])) }
|
|
42386
42671
|
} };
|
|
42387
42672
|
const serializedPolicy = serializeManagedSkillPolicy(nextPolicy);
|
|
@@ -42397,12 +42682,12 @@ function planClaudePreToolUseHookUpdate(options) {
|
|
|
42397
42682
|
return planClaudeHookEventsUpdate({ ...options, events: ["PreToolUse"] });
|
|
42398
42683
|
}
|
|
42399
42684
|
function claudeSettingsConsumers(home, path, discoveries, aliases) {
|
|
42400
|
-
const
|
|
42685
|
+
const canonical6 = (value) => canonicalAgentPath(value, aliases);
|
|
42401
42686
|
const containsSettings = (root2) => {
|
|
42402
|
-
const distance =
|
|
42687
|
+
const distance = relative4(canonical6(root2), path);
|
|
42403
42688
|
return distance === "" || distance !== ".." && !distance.startsWith(`..${sep5}`) && !isAbsolute17(distance);
|
|
42404
42689
|
};
|
|
42405
|
-
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);
|
|
42406
42691
|
}
|
|
42407
42692
|
function verifyCoordinatedDiscovery(binding, home, aliases) {
|
|
42408
42693
|
try {
|
|
@@ -42434,7 +42719,7 @@ function planClaudeHookEventsUpdate(options) {
|
|
|
42434
42719
|
const path = canonicalAgentPath(join22(home, ".claude", "settings.json"), aliases);
|
|
42435
42720
|
assertSafePath(path);
|
|
42436
42721
|
const before = lstatSync19(path, { throwIfNoEntry: false }) ? new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(readNativeBytes(path, 1024 * 1024)) : null;
|
|
42437
|
-
if ((before === null ? "absent" :
|
|
42722
|
+
if ((before === null ? "absent" : sha4(before)) !== options.expectedSettingsSha256)
|
|
42438
42723
|
throw new Error("Claude settings preimage changed");
|
|
42439
42724
|
assertClaudeHookEventsReplacement(before, options.replacement, options.events);
|
|
42440
42725
|
const agents = bridge.agents;
|
|
@@ -42500,7 +42785,7 @@ function atomicWrite2(path, content) {
|
|
|
42500
42785
|
function planAgentSettingsWitnessUpgrade(options) {
|
|
42501
42786
|
const home = resolve15(options.home ?? homedir3()), dataDir2 = options.dataDir ?? getDataDirReadOnly();
|
|
42502
42787
|
const snapshot2 = readManagedSkillPolicySnapshot(dataDir2);
|
|
42503
|
-
if (!snapshot2 ||
|
|
42788
|
+
if (!snapshot2 || sha4(snapshot2.text) !== options.expectedPolicySha256)
|
|
42504
42789
|
throw new Error("Managed policy preimage changed");
|
|
42505
42790
|
const policy = snapshot2.value, aliases = policy.bridge?.rootAliases ?? [];
|
|
42506
42791
|
recheckRootAliases(aliases);
|
|
@@ -42509,7 +42794,7 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
42509
42794
|
throw new Error("Settings witness upgrade requires an existing reviewed native binding");
|
|
42510
42795
|
const configPath = canonicalAgentPath(join22(home, options.agent === "claude" ? ".claude/settings.json" : ".codex/config.toml"), aliases);
|
|
42511
42796
|
const settings = readOptional(configPath);
|
|
42512
|
-
if (settings === null ||
|
|
42797
|
+
if (settings === null || sha4(settings) !== options.expectedSettingsSha256)
|
|
42513
42798
|
throw new Error("Native settings preimage changed");
|
|
42514
42799
|
const sources = binding.sources.filter((source) => source.path === configPath && source.format === undefined && source.fields === undefined);
|
|
42515
42800
|
if (sources.length !== 1)
|
|
@@ -42517,15 +42802,40 @@ function planAgentSettingsWitnessUpgrade(options) {
|
|
|
42517
42802
|
const previous = sources[0];
|
|
42518
42803
|
if (typeof previous.sha256 !== "string")
|
|
42519
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
|
+
}
|
|
42520
42821
|
const next = options.agent === "claude" ? upgradeClaudeSettingsWitness(previous, options.reviewedPreimage) : upgradeCodexSettingsWitness(previous, options.reviewedPreimage);
|
|
42521
|
-
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 };
|
|
42522
42832
|
verifyAgentDiscovery(replacement);
|
|
42523
42833
|
const after = serializeManagedSkillPolicy({ ...policy, bridge: { ...policy.bridge, discovery: { ...policy.bridge.discovery, [options.agent]: replacement } } });
|
|
42524
|
-
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 })) } };
|
|
42525
42835
|
}
|
|
42526
42836
|
function applyAgentIntegration(plan) {
|
|
42527
42837
|
for (const source of plan.observedNativeSources ?? [])
|
|
42528
|
-
if (
|
|
42838
|
+
if (sha4(readNativeBytes(source.path, 1024 * 1024)) !== source.sha256)
|
|
42529
42839
|
throw new Error("Native identity source changed after planning");
|
|
42530
42840
|
if (plan.observedSettings && readOptional(plan.observedSettings.path) !== plan.observedSettings.before)
|
|
42531
42841
|
throw new Error("Native settings changed after witness planning");
|
|
@@ -42545,7 +42855,7 @@ function applyAgentIntegration(plan) {
|
|
|
42545
42855
|
const upgrade = plan.settingsWitnessUpgrade;
|
|
42546
42856
|
if (!plan.managedAgentChecks || !plan.observedPolicy?.before)
|
|
42547
42857
|
throw new Error("Invalid settings witness upgrade plan");
|
|
42548
|
-
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 });
|
|
42549
42859
|
if (JSON.stringify(verified.changes) !== JSON.stringify(plan.changes) || JSON.stringify(verified.settingsWitnessUpgrade) !== JSON.stringify(upgrade))
|
|
42550
42860
|
throw new Error("Settings witness upgrade plan changed");
|
|
42551
42861
|
provenDiscovery = verified.discoveryBefore[0];
|
|
@@ -42573,7 +42883,7 @@ function applyAgentIntegration(plan) {
|
|
|
42573
42883
|
chmodSync(backupRoot, 448);
|
|
42574
42884
|
for (const [index, change] of plan.changes.entries())
|
|
42575
42885
|
if (change.before !== null) {
|
|
42576
|
-
const backup = join22(backupRoot, `${index}-${
|
|
42886
|
+
const backup = join22(backupRoot, `${index}-${sha4(change.path).slice(0, 12)}.backup`);
|
|
42577
42887
|
writeFileSync4(backup, change.before, { mode: 384, flag: "wx" });
|
|
42578
42888
|
if (readFileSync14(backup, "utf8") !== change.before)
|
|
42579
42889
|
throw new Error("Native configuration preservation readback failed");
|
|
@@ -42592,7 +42902,7 @@ function applyAgentIntegration(plan) {
|
|
|
42592
42902
|
}
|
|
42593
42903
|
recheckRootAliases(aliases);
|
|
42594
42904
|
for (const source of plan.observedNativeSources ?? [])
|
|
42595
|
-
if (
|
|
42905
|
+
if (sha4(readNativeBytes(source.path, 1024 * 1024)) !== source.sha256)
|
|
42596
42906
|
throw new Error("Native identity source changed during application");
|
|
42597
42907
|
if (plan.observedSettings && readOptional(plan.observedSettings.path) !== plan.observedSettings.before)
|
|
42598
42908
|
throw new Error("Native settings changed during witness application");
|
|
@@ -42604,7 +42914,7 @@ function applyAgentIntegration(plan) {
|
|
|
42604
42914
|
}
|
|
42605
42915
|
for (const agent of plan.managedAgentChecks?.agents ?? [])
|
|
42606
42916
|
assertManagedAgentBridge(agent, { home: plan.managedAgentChecks.home, dataDir: plan.dataDir, projectDir: plan.managedAgentChecks.home });
|
|
42607
|
-
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 } : {} }) + `
|
|
42608
42918
|
`);
|
|
42609
42919
|
} catch (error) {
|
|
42610
42920
|
for (const change of written.reverse()) {
|
|
@@ -42683,8 +42993,8 @@ function archiveNativeSkills(inventory, options) {
|
|
|
42683
42993
|
const operationId = randomUUID3(), archiveRoot = join22(options.dataDir ?? getDataDir(), "migration", operationId, "native"), receiptPath = join22(archiveRoot, "receipt.json");
|
|
42684
42994
|
const entries = selected.map((entry, index) => ({
|
|
42685
42995
|
source: entry.vendor ? join22(entry.path, "SKILL.md") : entry.path,
|
|
42686
|
-
archive: join22(archiveRoot, `${index}-${
|
|
42687
|
-
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,
|
|
42688
42998
|
...entry.vendor ? { discoveryOnly: true } : {},
|
|
42689
42999
|
status: "planned"
|
|
42690
43000
|
}));
|
|
@@ -42695,7 +43005,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
42695
43005
|
const stat2 = lstatSync19(entry.archive);
|
|
42696
43006
|
if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
|
|
42697
43007
|
throw new Error("Archive type changed");
|
|
42698
|
-
if ((entry.discoveryOnly ?
|
|
43008
|
+
if ((entry.discoveryOnly ? sha4(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
|
|
42699
43009
|
throw new Error("Archive bytes changed");
|
|
42700
43010
|
};
|
|
42701
43011
|
assertSafePath(archiveRoot);
|
|
@@ -42815,7 +43125,7 @@ function assertManagedAgentBridgeWithDiscovery(agent, options = {}, provenDiscov
|
|
|
42815
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");
|
|
42816
43126
|
if (agent === "hermes") {
|
|
42817
43127
|
const supervisor = binding.supervisors?.hermes;
|
|
42818
|
-
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)))
|
|
42819
43129
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes supervisor binding changed; run skills hook install");
|
|
42820
43130
|
assertHermesProtection(home, config, command, profile, supervisor);
|
|
42821
43131
|
} else if (agent === "opencode") {
|
|
@@ -42913,13 +43223,13 @@ import {
|
|
|
42913
43223
|
statSync as statSync9,
|
|
42914
43224
|
writeFileSync as writeFileSync6
|
|
42915
43225
|
} from "fs";
|
|
42916
|
-
import { basename 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";
|
|
42917
43227
|
|
|
42918
43228
|
// src/lib/registry-data/index.ts
|
|
42919
43229
|
var SKILLS = [];
|
|
42920
43230
|
|
|
42921
43231
|
// src/lib/skill-hash.ts
|
|
42922
|
-
import { createHash as
|
|
43232
|
+
import { createHash as createHash19 } from "crypto";
|
|
42923
43233
|
import { existsSync as existsSync7, readdirSync as readdirSync9, readFileSync as readFileSync15, statSync as statSync7 } from "fs";
|
|
42924
43234
|
import { join as join23, sep as sep6 } from "path";
|
|
42925
43235
|
var CONTENT_HASH_ALGORITHM = "sha256";
|
|
@@ -43043,13 +43353,13 @@ function* bundleHashParts(files) {
|
|
|
43043
43353
|
yield new TextEncoder().encode("\x00");
|
|
43044
43354
|
}
|
|
43045
43355
|
function hashBundleFiles(files) {
|
|
43046
|
-
const hash2 =
|
|
43356
|
+
const hash2 = createHash19(CONTENT_HASH_ALGORITHM);
|
|
43047
43357
|
for (const part of bundleHashParts(files))
|
|
43048
43358
|
hash2.update(part);
|
|
43049
43359
|
return hash2.digest("hex");
|
|
43050
43360
|
}
|
|
43051
43361
|
async function hashBundleFilesCooperatively(files, check) {
|
|
43052
|
-
const hash2 =
|
|
43362
|
+
const hash2 = createHash19(CONTENT_HASH_ALGORITHM);
|
|
43053
43363
|
let bytesSinceYield = 0;
|
|
43054
43364
|
for (const part of bundleHashParts(files)) {
|
|
43055
43365
|
for (let offset = 0;offset < part.byteLength; offset += 64 * 1024) {
|
|
@@ -43307,7 +43617,7 @@ var MAX_RUNTIME_TIMEOUT_SECONDS = 900;
|
|
|
43307
43617
|
function add2(target, code, message) {
|
|
43308
43618
|
target.push({ code, message });
|
|
43309
43619
|
}
|
|
43310
|
-
function
|
|
43620
|
+
function isRecord2(value) {
|
|
43311
43621
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
43312
43622
|
}
|
|
43313
43623
|
function isNonEmptyString(value) {
|
|
@@ -43335,7 +43645,7 @@ function validatePortableManifestContract(manifest, options = {}) {
|
|
|
43335
43645
|
}
|
|
43336
43646
|
validateRuntimeContract(manifest, issues, options.strict === true);
|
|
43337
43647
|
const provenance = manifest.provenance;
|
|
43338
|
-
if (provenance && !
|
|
43648
|
+
if (provenance && !isRecord2(provenance)) {
|
|
43339
43649
|
add2(issues, "contract.provenance_invalid", "provenance must be an object");
|
|
43340
43650
|
} else {
|
|
43341
43651
|
const sourceCommit = provenance?.source_commit;
|
|
@@ -43368,7 +43678,7 @@ function validateRuntimeContract(manifest, issues, strict) {
|
|
|
43368
43678
|
}
|
|
43369
43679
|
return;
|
|
43370
43680
|
}
|
|
43371
|
-
if (!
|
|
43681
|
+
if (!isRecord2(runtime)) {
|
|
43372
43682
|
add2(issues, "contract.runtime_invalid", "runtime must be an object");
|
|
43373
43683
|
return;
|
|
43374
43684
|
}
|
|
@@ -43438,7 +43748,7 @@ import {
|
|
|
43438
43748
|
realpathSync as realpathSync8,
|
|
43439
43749
|
writeFileSync as writeFileSync5
|
|
43440
43750
|
} from "fs";
|
|
43441
|
-
import { basename as
|
|
43751
|
+
import { basename as basename8, dirname as dirname16, join as join24, relative as relative5 } from "path";
|
|
43442
43752
|
var ANY_SEGMENT_COPY_EXCLUDES = new Set([
|
|
43443
43753
|
".git",
|
|
43444
43754
|
".DS_Store",
|
|
@@ -43488,11 +43798,11 @@ function normalizeNewPortableSkillName(name) {
|
|
|
43488
43798
|
throw new Error(`Invalid skill name '${name}'. Include letters or numbers.`);
|
|
43489
43799
|
return normalized;
|
|
43490
43800
|
}
|
|
43491
|
-
function readPortableSkillManifest(skillPath, fallbackName =
|
|
43801
|
+
function readPortableSkillManifest(skillPath, fallbackName = basename8(skillPath)) {
|
|
43492
43802
|
return readManifest(skillPath, fallbackName, normalizePortableSkillName);
|
|
43493
43803
|
}
|
|
43494
43804
|
function readPortableSkillManifestForImport(skillPath) {
|
|
43495
|
-
return readManifest(skillPath,
|
|
43805
|
+
return readManifest(skillPath, basename8(skillPath), normalizeNewPortableSkillName);
|
|
43496
43806
|
}
|
|
43497
43807
|
function readManifest(skillPath, fallbackName, normalizeName) {
|
|
43498
43808
|
const skillJsonPath = join24(skillPath, "skill.json");
|
|
@@ -43655,7 +43965,7 @@ function readExistingSkillJson(skillPath) {
|
|
|
43655
43965
|
return {};
|
|
43656
43966
|
try {
|
|
43657
43967
|
const parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
43658
|
-
return
|
|
43968
|
+
return isRecord3(parsed) ? parsed : {};
|
|
43659
43969
|
} catch {
|
|
43660
43970
|
return {};
|
|
43661
43971
|
}
|
|
@@ -43711,7 +44021,7 @@ function ensurePackageJson(skillPath, manifest) {
|
|
|
43711
44021
|
}
|
|
43712
44022
|
const existing = readJsonObject(pkgPath);
|
|
43713
44023
|
const bin = {};
|
|
43714
|
-
if (
|
|
44024
|
+
if (isRecord3(existing.bin)) {
|
|
43715
44025
|
for (const [name, value] of Object.entries(existing.bin)) {
|
|
43716
44026
|
if (typeof value === "string" && value.trim())
|
|
43717
44027
|
bin[normalizePortableSkillName(name)] = value.replace(/^\.\//, "");
|
|
@@ -43722,7 +44032,7 @@ function ensurePackageJson(skillPath, manifest) {
|
|
|
43722
44032
|
bin[manifest.name] = binEntry.replace(/^\.\//, "");
|
|
43723
44033
|
}
|
|
43724
44034
|
bin[commandName] = entry;
|
|
43725
|
-
const scripts =
|
|
44035
|
+
const scripts = isRecord3(existing.scripts) ? { ...existing.scripts } : {};
|
|
43726
44036
|
if (!stringValue(scripts.dev))
|
|
43727
44037
|
scripts.dev = `bun run ${entry}`;
|
|
43728
44038
|
writeFileSync5(pkgPath, `${JSON.stringify({
|
|
@@ -43795,7 +44105,7 @@ function copySkillDirectory(source, destination) {
|
|
|
43795
44105
|
cpSync(resolvedSource, destination, {
|
|
43796
44106
|
recursive: true,
|
|
43797
44107
|
filter: (src) => {
|
|
43798
|
-
const rel =
|
|
44108
|
+
const rel = relative5(resolvedSource, src);
|
|
43799
44109
|
if (!rel)
|
|
43800
44110
|
return true;
|
|
43801
44111
|
const segments = rel.split(/[\\/]/);
|
|
@@ -43943,7 +44253,7 @@ function parseManifestCommands(value) {
|
|
|
43943
44253
|
if (!Array.isArray(raw))
|
|
43944
44254
|
return;
|
|
43945
44255
|
const commands = raw.map((item) => {
|
|
43946
|
-
if (!
|
|
44256
|
+
if (!isRecord3(item))
|
|
43947
44257
|
return null;
|
|
43948
44258
|
const name = stringValue(item.name);
|
|
43949
44259
|
if (!name)
|
|
@@ -43960,7 +44270,7 @@ function parseManifestCommands(value) {
|
|
|
43960
44270
|
}
|
|
43961
44271
|
function parseManifestRuntime(value) {
|
|
43962
44272
|
const raw = value?.runtime;
|
|
43963
|
-
if (!
|
|
44273
|
+
if (!isRecord3(raw))
|
|
43964
44274
|
return;
|
|
43965
44275
|
const runtimeName = stringValue(raw.runtime);
|
|
43966
44276
|
if (!runtimeName)
|
|
@@ -43986,7 +44296,7 @@ function parseManifestRuntime(value) {
|
|
|
43986
44296
|
}
|
|
43987
44297
|
function parseManifestProvenance(value) {
|
|
43988
44298
|
const raw = value?.provenance;
|
|
43989
|
-
if (!
|
|
44299
|
+
if (!isRecord3(raw))
|
|
43990
44300
|
return;
|
|
43991
44301
|
const parsed = {};
|
|
43992
44302
|
if (stringValue(raw.source_commit))
|
|
@@ -44002,7 +44312,7 @@ function parseManifestInputs(value) {
|
|
|
44002
44312
|
if (!Array.isArray(raw))
|
|
44003
44313
|
return;
|
|
44004
44314
|
const inputs = raw.map((item) => {
|
|
44005
|
-
if (!
|
|
44315
|
+
if (!isRecord3(item))
|
|
44006
44316
|
return null;
|
|
44007
44317
|
const name = stringValue(item.name);
|
|
44008
44318
|
const type = stringValue(item.type);
|
|
@@ -44020,7 +44330,7 @@ function parseManifestInputs(value) {
|
|
|
44020
44330
|
function inferPackageCommands(pkg, fallbackName) {
|
|
44021
44331
|
if (!pkg)
|
|
44022
44332
|
return;
|
|
44023
|
-
if (
|
|
44333
|
+
if (isRecord3(pkg.bin)) {
|
|
44024
44334
|
const commands = Object.entries(pkg.bin).filter((entry) => typeof entry[1] === "string" && entry[1].trim().length > 0).map(([name, entry]) => ({
|
|
44025
44335
|
name: normalizePortableSkillName(name),
|
|
44026
44336
|
entry: entry.replace(/^\.\//, ""),
|
|
@@ -44029,7 +44339,7 @@ function inferPackageCommands(pkg, fallbackName) {
|
|
|
44029
44339
|
if (commands.length)
|
|
44030
44340
|
return commands;
|
|
44031
44341
|
}
|
|
44032
|
-
const scripts =
|
|
44342
|
+
const scripts = isRecord3(pkg.scripts) ? pkg.scripts : undefined;
|
|
44033
44343
|
const dev = stringValue(scripts?.dev);
|
|
44034
44344
|
const match = dev?.match(/(?:bun\s+run\s+|bun\s+)([^ ]+)/);
|
|
44035
44345
|
if (match?.[1]) {
|
|
@@ -44045,20 +44355,20 @@ function inferRuntimeFromCommands(commands) {
|
|
|
44045
44355
|
}
|
|
44046
44356
|
function readJsonObject(path) {
|
|
44047
44357
|
const parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
44048
|
-
if (!
|
|
44049
|
-
throw new Error(`${
|
|
44358
|
+
if (!isRecord3(parsed))
|
|
44359
|
+
throw new Error(`${basename8(path)} must contain a JSON object`);
|
|
44050
44360
|
return parsed;
|
|
44051
44361
|
}
|
|
44052
44362
|
function hasPackageDependencies(pkgPath) {
|
|
44053
44363
|
try {
|
|
44054
44364
|
const pkg = readJsonObject(pkgPath);
|
|
44055
|
-
const deps =
|
|
44365
|
+
const deps = isRecord3(pkg.dependencies) ? Object.keys(pkg.dependencies) : [];
|
|
44056
44366
|
return deps.length > 0;
|
|
44057
44367
|
} catch {
|
|
44058
44368
|
return false;
|
|
44059
44369
|
}
|
|
44060
44370
|
}
|
|
44061
|
-
function
|
|
44371
|
+
function isRecord3(value) {
|
|
44062
44372
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44063
44373
|
}
|
|
44064
44374
|
function stringField(value, key) {
|
|
@@ -44084,7 +44394,7 @@ function escapeJsString(value) {
|
|
|
44084
44394
|
// src/lib/authoring-path.ts
|
|
44085
44395
|
import { lstatSync as lstatSync21, realpathSync as realpathSync9 } from "fs";
|
|
44086
44396
|
import { homedir as homedir4 } from "os";
|
|
44087
|
-
import { basename as
|
|
44397
|
+
import { basename as basename9, dirname as dirname17, join as join25, resolve as resolve16, sep as sep7 } from "path";
|
|
44088
44398
|
var NATIVE_DISCOVERY_ROOTS = NATIVE_SKILL_ROOTS.map(([, path]) => path.split("/"));
|
|
44089
44399
|
function pathParts(path) {
|
|
44090
44400
|
return resolve16(path).split(sep7).filter(Boolean);
|
|
@@ -44104,7 +44414,7 @@ function physicalPath(path) {
|
|
|
44104
44414
|
let cursor = resolve16(path);
|
|
44105
44415
|
const suffix = [];
|
|
44106
44416
|
while (!lstatSync21(cursor, { throwIfNoEntry: false })) {
|
|
44107
|
-
suffix.unshift(
|
|
44417
|
+
suffix.unshift(basename9(cursor));
|
|
44108
44418
|
const parent = dirname17(cursor);
|
|
44109
44419
|
if (parent === cursor)
|
|
44110
44420
|
return resolve16(path);
|
|
@@ -44273,7 +44583,7 @@ function scaffoldPortableSkill(name, options = {}) {
|
|
|
44273
44583
|
return { name: skillName, path: skillPath, manifest, created: true };
|
|
44274
44584
|
}
|
|
44275
44585
|
function portPortableSkillDirectory(sourceDir, options = {}) {
|
|
44276
|
-
const absoluteSource =
|
|
44586
|
+
const absoluteSource = normalize4(sourceDir);
|
|
44277
44587
|
if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
|
|
44278
44588
|
throw new Error(`Import directory not found: ${sourceDir}`);
|
|
44279
44589
|
}
|
|
@@ -44323,7 +44633,7 @@ function physicalImportPath(path) {
|
|
|
44323
44633
|
let ancestor = resolve17(path);
|
|
44324
44634
|
const suffix = [];
|
|
44325
44635
|
while (!existsSync9(ancestor)) {
|
|
44326
|
-
suffix.unshift(
|
|
44636
|
+
suffix.unshift(basename10(ancestor));
|
|
44327
44637
|
ancestor = dirname18(ancestor);
|
|
44328
44638
|
}
|
|
44329
44639
|
return join26(realpathSync10(ancestor), ...suffix);
|
|
@@ -44332,7 +44642,7 @@ function assertDisjointImportPaths(source, destination) {
|
|
|
44332
44642
|
const sourcePath = realpathSync10(source);
|
|
44333
44643
|
const destinationPath = physicalImportPath(destination);
|
|
44334
44644
|
const contains2 = (parent, child) => {
|
|
44335
|
-
const path =
|
|
44645
|
+
const path = relative6(parent, child);
|
|
44336
44646
|
return path === "" || !isAbsolute18(path) && path !== ".." && !path.startsWith(`..${sep8}`);
|
|
44337
44647
|
};
|
|
44338
44648
|
if (contains2(sourcePath, destinationPath) || contains2(destinationPath, sourcePath)) {
|
|
@@ -44340,7 +44650,7 @@ function assertDisjointImportPaths(source, destination) {
|
|
|
44340
44650
|
}
|
|
44341
44651
|
}
|
|
44342
44652
|
function portPortableSkill(sourcePath, options = {}) {
|
|
44343
|
-
const absoluteSource =
|
|
44653
|
+
const absoluteSource = normalize4(sourcePath);
|
|
44344
44654
|
if (!existsSync9(absoluteSource) || !statSync9(absoluteSource).isDirectory()) {
|
|
44345
44655
|
throw new Error(`Skill source directory not found: ${sourcePath}`);
|
|
44346
44656
|
}
|
|
@@ -44348,8 +44658,8 @@ function portPortableSkill(sourcePath, options = {}) {
|
|
|
44348
44658
|
const explicitName = options.name != null;
|
|
44349
44659
|
const skillName = normalizeNewPortableSkillName(options.name ?? inferred.name);
|
|
44350
44660
|
if (isOfficialSkillName(skillName) && !options.allowShadow) {
|
|
44351
|
-
const sourceSlug = safeNormalizeName(
|
|
44352
|
-
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${
|
|
44661
|
+
const sourceSlug = safeNormalizeName(basename10(absoluteSource));
|
|
44662
|
+
const via = explicitName ? `Name '${skillName}' matches a bundled official skill.` : `Inferred name '${skillName}'${sourceSlug && sourceSlug !== skillName ? ` (from source folder '${basename10(absoluteSource)}')` : ""} matches a bundled official skill.`;
|
|
44353
44663
|
throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
|
|
44354
44664
|
}
|
|
44355
44665
|
const readOnlyDestination = join26(resolvePortableSkillsRoot(options, false), skillName);
|
|
@@ -44616,7 +44926,7 @@ function safeIsDirectory(path) {
|
|
|
44616
44926
|
function isSafeRelativePath2(value) {
|
|
44617
44927
|
if (!value.trim() || isAbsolute18(value))
|
|
44618
44928
|
return false;
|
|
44619
|
-
const normalized =
|
|
44929
|
+
const normalized = normalize4(value).replace(/\\/g, "/");
|
|
44620
44930
|
return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
|
|
44621
44931
|
}
|
|
44622
44932
|
function add3(target, code, message) {
|
|
@@ -44869,7 +45179,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
44869
45179
|
return { action, path: skillMdPath };
|
|
44870
45180
|
const parentDir = dirname19(dir);
|
|
44871
45181
|
mkdirSync8(parentDir, { recursive: true });
|
|
44872
|
-
const transactionDir = mkdtempSync2(join27(parentDir, `.hasna-skills-write-${
|
|
45182
|
+
const transactionDir = mkdtempSync2(join27(parentDir, `.hasna-skills-write-${basename11(dir)}-`));
|
|
44873
45183
|
const candidateDir = join27(transactionDir, "candidate");
|
|
44874
45184
|
const backupDir = join27(transactionDir, "backup");
|
|
44875
45185
|
const candidateSkillMdPath = join27(candidateDir, "SKILL.md");
|
|
@@ -46267,7 +46577,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
46267
46577
|
selection: selection2,
|
|
46268
46578
|
target: "local",
|
|
46269
46579
|
runtime: runtimeName,
|
|
46270
|
-
inputDigest: `sha256:${
|
|
46580
|
+
inputDigest: `sha256:${createHash20("sha256").update(input).digest("hex")}`,
|
|
46271
46581
|
runDirectory,
|
|
46272
46582
|
...executionGrant ? { executionGrant } : {},
|
|
46273
46583
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
@@ -46325,7 +46635,7 @@ async function subprocess(command, cwd, env, input, timeoutMs) {
|
|
|
46325
46635
|
// src/lib/remote-run-contract.ts
|
|
46326
46636
|
var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
|
|
46327
46637
|
function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
|
|
46328
|
-
const record3 =
|
|
46638
|
+
const record3 = isRecord4(payload) ? payload : {};
|
|
46329
46639
|
return {
|
|
46330
46640
|
contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
46331
46641
|
...pickString(record3, "id"),
|
|
@@ -46347,7 +46657,7 @@ function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
|
|
|
46347
46657
|
...hasOwn(record3, "details") ? { details: record3.details } : {}
|
|
46348
46658
|
};
|
|
46349
46659
|
}
|
|
46350
|
-
function
|
|
46660
|
+
function isRecord4(value) {
|
|
46351
46661
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
46352
46662
|
}
|
|
46353
46663
|
function hasOwn(record3, key) {
|
|
@@ -55557,7 +55867,7 @@ var import_node_http_handler2 = __toESM(require_dist_cjs6(), 1);
|
|
|
55557
55867
|
|
|
55558
55868
|
// node_modules/@aws-sdk/checksums/dist-cjs/submodules/sha/index.js
|
|
55559
55869
|
var { toUint8Array: toUint8Array2, concatBytes } = require_serde();
|
|
55560
|
-
var { createHmac: createHmac2, createHash:
|
|
55870
|
+
var { createHmac: createHmac2, createHash: createHash22 } = __require("crypto");
|
|
55561
55871
|
var { Sha256: Sha2562, Sha256Js, Sha256Node } = require_checksum();
|
|
55562
55872
|
var BLOCK2 = 64;
|
|
55563
55873
|
var DIGEST_LENGTH = 20;
|
|
@@ -55726,7 +56036,7 @@ class Sha1Js {
|
|
|
55726
56036
|
}
|
|
55727
56037
|
var hasNativeCrypto = (() => {
|
|
55728
56038
|
try {
|
|
55729
|
-
|
|
56039
|
+
createHash22("sha1");
|
|
55730
56040
|
return true;
|
|
55731
56041
|
} catch {
|
|
55732
56042
|
return false;
|
|
@@ -55766,7 +56076,7 @@ function buildNativeClass() {
|
|
|
55766
56076
|
this.finished = false;
|
|
55767
56077
|
}
|
|
55768
56078
|
createHash() {
|
|
55769
|
-
return this.secret ? createHmac2("sha1", toBuffer(this.secret)) :
|
|
56079
|
+
return this.secret ? createHmac2("sha1", toBuffer(this.secret)) : createHash22("sha1");
|
|
55770
56080
|
}
|
|
55771
56081
|
};
|
|
55772
56082
|
}
|
|
@@ -56634,9 +56944,9 @@ import { mkdirSync as mkdirSync11, readFileSync as readFileSync23, readdirSync a
|
|
|
56634
56944
|
import { dirname as dirname23, join as join36 } from "path";
|
|
56635
56945
|
|
|
56636
56946
|
// src/server/auth.ts
|
|
56637
|
-
import { createHash as
|
|
56947
|
+
import { createHash as createHash23 } from "crypto";
|
|
56638
56948
|
function hashApiKey(token) {
|
|
56639
|
-
return
|
|
56949
|
+
return createHash23("sha256").update(token).digest("hex");
|
|
56640
56950
|
}
|
|
56641
56951
|
function bearerToken(request2) {
|
|
56642
56952
|
const header = request2.headers.get("authorization") || "";
|
|
@@ -56958,7 +57268,7 @@ function validOperatorScopeEnrollmentInput(input) {
|
|
|
56958
57268
|
}
|
|
56959
57269
|
|
|
56960
57270
|
// src/lib/revision.ts
|
|
56961
|
-
import { createHash as
|
|
57271
|
+
import { createHash as createHash24 } from "crypto";
|
|
56962
57272
|
var REVISION_ID_PATTERN = /^[0-9a-f]{64}$/;
|
|
56963
57273
|
function revisionIdOf(content) {
|
|
56964
57274
|
const canonicalContent = {
|
|
@@ -56979,8 +57289,8 @@ function revisionIdOf(content) {
|
|
|
56979
57289
|
canonicalContent.archiveReason = content.archiveReason ?? null;
|
|
56980
57290
|
canonicalContent.replacementSlug = content.replacementSlug ?? null;
|
|
56981
57291
|
}
|
|
56982
|
-
const
|
|
56983
|
-
return
|
|
57292
|
+
const canonical6 = JSON.stringify(canonicalContent);
|
|
57293
|
+
return createHash24("sha256").update(canonical6).digest("hex");
|
|
56984
57294
|
}
|
|
56985
57295
|
function revisionIdOfRecord(record3) {
|
|
56986
57296
|
return revisionIdOf(record3);
|
|
@@ -58064,7 +58374,7 @@ function nextMonthPrefix(monthPrefix) {
|
|
|
58064
58374
|
}
|
|
58065
58375
|
|
|
58066
58376
|
// src/server/skills-api.ts
|
|
58067
|
-
import { createHash as
|
|
58377
|
+
import { createHash as createHash25 } from "crypto";
|
|
58068
58378
|
var SLUG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
|
|
58069
58379
|
var SHA256_HEX2 = /^[0-9a-f]{64}$/;
|
|
58070
58380
|
var MAX_SLUG_LENGTH = 128;
|
|
@@ -58254,7 +58564,7 @@ async function parsePublishRequest(request2, config) {
|
|
|
58254
58564
|
if (bundleBytes.byteLength === 0) {
|
|
58255
58565
|
throw new SkillRequestError(400, "BUNDLE_EMPTY", "the uploaded bundle is empty");
|
|
58256
58566
|
}
|
|
58257
|
-
const sha2562 =
|
|
58567
|
+
const sha2562 = createHash25("sha256").update(bundleBytes).digest("hex");
|
|
58258
58568
|
const claimed = optionalString(manifest.bundleSha256);
|
|
58259
58569
|
if (claimed)
|
|
58260
58570
|
assertSha2562(claimed);
|
|
@@ -58369,7 +58679,7 @@ async function readPublishedBundle(store, artifactStorage, principal, slug) {
|
|
|
58369
58679
|
if (!bytes) {
|
|
58370
58680
|
throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
|
|
58371
58681
|
}
|
|
58372
|
-
const actual =
|
|
58682
|
+
const actual = createHash25("sha256").update(bytes).digest("hex");
|
|
58373
58683
|
if (actual !== record3.bundleSha256) {
|
|
58374
58684
|
throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}' hashes to ${actual} but was published as ${record3.bundleSha256}`);
|
|
58375
58685
|
}
|
|
@@ -58517,7 +58827,7 @@ async function readSkillVersionBundle(store, artifactStorage, principal, slug, v
|
|
|
58517
58827
|
const bytes = await artifactStorage.readBundle(bundle2);
|
|
58518
58828
|
if (!bytes)
|
|
58519
58829
|
throw new SkillRequestError(503, "BUNDLE_BACKEND_UNAVAILABLE", "bundle storage backend unavailable");
|
|
58520
|
-
const actual =
|
|
58830
|
+
const actual = createHash25("sha256").update(bytes).digest("hex");
|
|
58521
58831
|
if (actual !== found.bundleSha256) {
|
|
58522
58832
|
throw new SkillRequestError(500, "BUNDLE_DIGEST_DRIFT", `stored bundle for '${slug}@${version2}' hashes to ${actual} but was published as ${found.bundleSha256}`);
|
|
58523
58833
|
}
|
|
@@ -59220,7 +59530,7 @@ class RuntimeExecutionStore {
|
|
|
59220
59530
|
}
|
|
59221
59531
|
|
|
59222
59532
|
// src/sdk/execution/admission.ts
|
|
59223
|
-
import { createHash as
|
|
59533
|
+
import { createHash as createHash27 } from "crypto";
|
|
59224
59534
|
|
|
59225
59535
|
// src/sdk/execution/image-profile.ts
|
|
59226
59536
|
class ImageProfileResolutionError extends Error {
|
|
@@ -59832,11 +60142,11 @@ function ownedAdmission(admission) {
|
|
|
59832
60142
|
};
|
|
59833
60143
|
}
|
|
59834
60144
|
function digestInput(input) {
|
|
59835
|
-
return
|
|
60145
|
+
return createHash27("sha256").update(canonicalJson2(input)).digest("hex");
|
|
59836
60146
|
}
|
|
59837
60147
|
|
|
59838
60148
|
// src/sdk/execution/dispatchers/ecs.ts
|
|
59839
|
-
import { createHash as
|
|
60149
|
+
import { createHash as createHash28 } from "crypto";
|
|
59840
60150
|
|
|
59841
60151
|
// src/sdk/execution/state-machine.ts
|
|
59842
60152
|
var LEGAL_TRANSITIONS = {
|
|
@@ -63236,13 +63546,13 @@ function observedTask(states, taskArn) {
|
|
|
63236
63546
|
return state2.lastStatus === "STOPPED" || LIVE_TASK_STATUSES.has(state2.lastStatus) ? state2 : undefined;
|
|
63237
63547
|
}
|
|
63238
63548
|
function clientTokenFor(runId3, attemptId) {
|
|
63239
|
-
return
|
|
63549
|
+
return createHash28("sha256").update(`${runId3}\x00${attemptId}`).digest("hex").slice(0, CLIENT_TOKEN_BYTES * 2);
|
|
63240
63550
|
}
|
|
63241
63551
|
function startedByFor(runId3, attemptNumber) {
|
|
63242
63552
|
return `skills-exec/${runId3}/a${attemptNumber}`;
|
|
63243
63553
|
}
|
|
63244
63554
|
function requestDigestFor(admission, attemptId) {
|
|
63245
|
-
return
|
|
63555
|
+
return createHash28("sha256").update(canonicalJson2({ admission, attemptId })).digest("hex");
|
|
63246
63556
|
}
|
|
63247
63557
|
|
|
63248
63558
|
class EcsDispatcher {
|
|
@@ -63538,10 +63848,10 @@ function validText(value) {
|
|
|
63538
63848
|
}
|
|
63539
63849
|
|
|
63540
63850
|
// src/server/runtime-policy.ts
|
|
63541
|
-
import { createHash as
|
|
63851
|
+
import { createHash as createHash30, createHmac as createHmac3, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
63542
63852
|
|
|
63543
63853
|
// src/server/runtime-pure-contract.ts
|
|
63544
|
-
import { createHash as
|
|
63854
|
+
import { createHash as createHash29 } from "crypto";
|
|
63545
63855
|
var PURE_DESCRIPTOR = Object.freeze({
|
|
63546
63856
|
id: "regex-test.v1",
|
|
63547
63857
|
runtime: "bun",
|
|
@@ -63565,7 +63875,7 @@ var PURE_LIMITS = Object.freeze({
|
|
|
63565
63875
|
maxArtifactsBytes: 0,
|
|
63566
63876
|
maxConcurrency: 1
|
|
63567
63877
|
});
|
|
63568
|
-
var hash2 = (bytes) =>
|
|
63878
|
+
var hash2 = (bytes) => createHash29("sha256").update(bytes).digest("hex");
|
|
63569
63879
|
var object6 = (v2) => {
|
|
63570
63880
|
if (!v2 || typeof v2 !== "object" || Array.isArray(v2))
|
|
63571
63881
|
throw Error("Pure contract requires an object");
|
|
@@ -63794,7 +64104,7 @@ function verifyRuntimeToken(token, key, admission, attempt, now = Date.now()) {
|
|
|
63794
64104
|
const actual = Buffer.from(token);
|
|
63795
64105
|
return actual.length === expected.length && timingSafeEqual2(actual, expected);
|
|
63796
64106
|
}
|
|
63797
|
-
var hashBytes = (bytes) =>
|
|
64107
|
+
var hashBytes = (bytes) => createHash30("sha256").update(bytes).digest("hex");
|
|
63798
64108
|
|
|
63799
64109
|
// src/server/runtime-api.ts
|
|
63800
64110
|
async function createRuntimeService(options) {
|
|
@@ -65982,7 +66292,7 @@ async function readJson(request2, limitBytes) {
|
|
|
65982
66292
|
if (!text2.trim())
|
|
65983
66293
|
return {};
|
|
65984
66294
|
const parsed = JSON.parse(text2);
|
|
65985
|
-
return
|
|
66295
|
+
return isRecord5(parsed) ? parsed : {};
|
|
65986
66296
|
}
|
|
65987
66297
|
function pathSegments(pathname) {
|
|
65988
66298
|
return pathname.split("/").filter(Boolean).map(decodeSegment);
|
|
@@ -66003,7 +66313,7 @@ function json4(payload, init = {}) {
|
|
|
66003
66313
|
headers: { "Cache-Control": "no-store", ...init.headers }
|
|
66004
66314
|
});
|
|
66005
66315
|
}
|
|
66006
|
-
function
|
|
66316
|
+
function isRecord5(value) {
|
|
66007
66317
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
66008
66318
|
}
|
|
66009
66319
|
function clampInt(value, fallback, max) {
|
|
@@ -70166,7 +70476,7 @@ var localRunExecutor = {
|
|
|
70166
70476
|
// src/sdk/storage.ts
|
|
70167
70477
|
var artifactStorageSeam = ArtifactStorage;
|
|
70168
70478
|
// src/sdk/outputs.ts
|
|
70169
|
-
import { createHash as
|
|
70479
|
+
import { createHash as createHash31 } from "crypto";
|
|
70170
70480
|
class DatabaseOnlyObjectStore {
|
|
70171
70481
|
usesS3 = false;
|
|
70172
70482
|
async materialize(run, artifact, body4) {
|
|
@@ -70213,7 +70523,7 @@ function createGovernedArtifactWriter(options) {
|
|
|
70213
70523
|
const stamped = {
|
|
70214
70524
|
...meta,
|
|
70215
70525
|
byteSize: outputBytes,
|
|
70216
|
-
sha256:
|
|
70526
|
+
sha256: createHash31("sha256").update(persistedBytes).digest("hex"),
|
|
70217
70527
|
visibility: options.visibility ?? config.defaultVisibility,
|
|
70218
70528
|
...config.artifactTtlSeconds !== undefined ? { expiresAt: expiresAtFor(createdAt, config.artifactTtlSeconds) } : {}
|
|
70219
70529
|
};
|
|
@@ -73684,15 +73994,15 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
|
|
|
73684
73994
|
} catch (_err) {}
|
|
73685
73995
|
}
|
|
73686
73996
|
const input = payload.value;
|
|
73687
|
-
const
|
|
73688
|
-
const isValidDate =
|
|
73997
|
+
const isDate2 = input instanceof Date;
|
|
73998
|
+
const isValidDate = isDate2 && !Number.isNaN(input.getTime());
|
|
73689
73999
|
if (isValidDate)
|
|
73690
74000
|
return payload;
|
|
73691
74001
|
payload.issues.push({
|
|
73692
74002
|
expected: "date",
|
|
73693
74003
|
code: "invalid_type",
|
|
73694
74004
|
input,
|
|
73695
|
-
...
|
|
74005
|
+
...isDate2 ? { received: "Invalid Date" } : {},
|
|
73696
74006
|
inst
|
|
73697
74007
|
});
|
|
73698
74008
|
return payload;
|
|
@@ -88980,7 +89290,7 @@ function date4(params) {
|
|
|
88980
89290
|
return _coercedDate(ZodDate2, params);
|
|
88981
89291
|
}
|
|
88982
89292
|
// src/lib/canonical-json.ts
|
|
88983
|
-
import { createHash as
|
|
89293
|
+
import { createHash as createHash32 } from "crypto";
|
|
88984
89294
|
function canonicalJson3(value, maximumBytes = 2 * 1024 * 1024) {
|
|
88985
89295
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
88986
89296
|
}
|
|
@@ -89024,7 +89334,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
89024
89334
|
return visit3(value, 0);
|
|
89025
89335
|
}
|
|
89026
89336
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
89027
|
-
return
|
|
89337
|
+
return createHash32("sha256").update(canonicalJson3(value, maximumBytes)).digest("hex");
|
|
89028
89338
|
}
|
|
89029
89339
|
|
|
89030
89340
|
// src/lib/remote-recurring-contract.ts
|
|
@@ -89890,7 +90200,7 @@ function creditCheckoutFailure(value, status, key) {
|
|
|
89890
90200
|
|
|
89891
90201
|
// src/lib/remote-profile.ts
|
|
89892
90202
|
function customerNamePatch(input2, field2) {
|
|
89893
|
-
if (!
|
|
90203
|
+
if (!isRecord6(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field2))
|
|
89894
90204
|
throw new Error("Provide only the requested name field.");
|
|
89895
90205
|
const value = input2[field2];
|
|
89896
90206
|
if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
|
|
@@ -89898,22 +90208,22 @@ function customerNamePatch(input2, field2) {
|
|
|
89898
90208
|
}
|
|
89899
90209
|
return { [field2]: value.trim() };
|
|
89900
90210
|
}
|
|
89901
|
-
function
|
|
90211
|
+
function isRecord6(value) {
|
|
89902
90212
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
89903
90213
|
}
|
|
89904
90214
|
function string4(value) {
|
|
89905
90215
|
return typeof value === "string" && value.length > 0;
|
|
89906
90216
|
}
|
|
89907
90217
|
function parseUpdatedProfile(value) {
|
|
89908
|
-
const user =
|
|
89909
|
-
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)) {
|
|
89910
90220
|
throw new Error("The server returned an invalid account profile.");
|
|
89911
90221
|
}
|
|
89912
90222
|
return { user: { id: user.id, email: user.email, displayName: user.displayName, role: user.role } };
|
|
89913
90223
|
}
|
|
89914
90224
|
function parseUpdatedWorkspace(value) {
|
|
89915
|
-
const organization2 =
|
|
89916
|
-
if (!
|
|
90225
|
+
const organization2 = isRecord6(value) && value.organization;
|
|
90226
|
+
if (!isRecord6(organization2) || !string4(organization2.id) || !string4(organization2.slug) || !string4(organization2.name)) {
|
|
89917
90227
|
throw new Error("The server returned an invalid workspace.");
|
|
89918
90228
|
}
|
|
89919
90229
|
return { organization: { id: organization2.id, slug: organization2.slug, name: organization2.name } };
|
|
@@ -91138,7 +91448,7 @@ async function requestInvitationEmail(origin, action, input2) {
|
|
|
91138
91448
|
}
|
|
91139
91449
|
|
|
91140
91450
|
// src/lib/remote-private-publications.ts
|
|
91141
|
-
import { createHash as
|
|
91451
|
+
import { createHash as createHash33 } from "crypto";
|
|
91142
91452
|
var PRIVATE_PUBLICATION_MAX_BYTES = 16 * 1024 * 1024;
|
|
91143
91453
|
var failures2 = {
|
|
91144
91454
|
INVALID_REQUEST: [400, "The publication request is invalid."],
|
|
@@ -91185,7 +91495,7 @@ var hash4 = (v2) => typeof v2 === "string" && /^[a-f0-9]{64}$/.test(v2);
|
|
|
91185
91495
|
var record9 = (v2) => !!v2 && typeof v2 === "object" && !Array.isArray(v2);
|
|
91186
91496
|
var exact = (v2, keys3) => record9(v2) && Object.keys(v2).sort().join(",") === keys3.sort().join(",");
|
|
91187
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));
|
|
91188
|
-
var publicationSha256 = (bytes) =>
|
|
91498
|
+
var publicationSha256 = (bytes) => createHash33("sha256").update(bytes).digest("hex");
|
|
91189
91499
|
function checkedPublicationDeclaration(value) {
|
|
91190
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)
|
|
91191
91501
|
return bad();
|
|
@@ -91484,7 +91794,7 @@ async function requestAuthApi(instance, path2, options) {
|
|
|
91484
91794
|
const text3 = await res.text();
|
|
91485
91795
|
const body4 = text3 ? parseJsonBody(text3) : {};
|
|
91486
91796
|
if (!res.ok) {
|
|
91487
|
-
const record10 =
|
|
91797
|
+
const record10 = isRecord7(body4) ? body4 : {};
|
|
91488
91798
|
const detail = typeof record10.detail === "string" ? record10.detail : undefined;
|
|
91489
91799
|
const error61 = typeof record10.error === "string" ? record10.error : undefined;
|
|
91490
91800
|
const code = typeof record10.code === "string" ? record10.code : undefined;
|
|
@@ -91512,7 +91822,7 @@ function condenseErrorBody(text3) {
|
|
|
91512
91822
|
return collapsed;
|
|
91513
91823
|
return `${collapsed.slice(0, MAX_ERROR_DETAIL_LENGTH - 1).trimEnd()}\u2026`;
|
|
91514
91824
|
}
|
|
91515
|
-
function
|
|
91825
|
+
function isRecord7(value) {
|
|
91516
91826
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
91517
91827
|
}
|
|
91518
91828
|
|
|
@@ -92020,16 +92330,16 @@ function resultSnapshot(input2, requestId) {
|
|
|
92020
92330
|
const value = snapshot2(input2, SKILL_OPERATION_LIMITS.resultBytes).value;
|
|
92021
92331
|
if (!record10(value) || value.contractVersion !== 1 || value.requestId !== requestId)
|
|
92022
92332
|
throw Error();
|
|
92023
|
-
const
|
|
92333
|
+
const fields2 = ["contractVersion", "requestId", "status"];
|
|
92024
92334
|
if (value.status === "succeeded")
|
|
92025
|
-
|
|
92335
|
+
fields2.push("output");
|
|
92026
92336
|
else if (value.status === "refused") {
|
|
92027
|
-
|
|
92337
|
+
fields2.push("code");
|
|
92028
92338
|
if (!refusalCodes.has(value.code))
|
|
92029
92339
|
throw Error();
|
|
92030
92340
|
} else if (!["not-executed", "pending", "unknown"].includes(value.status))
|
|
92031
92341
|
throw Error();
|
|
92032
|
-
if (!exact2(value,
|
|
92342
|
+
if (!exact2(value, fields2))
|
|
92033
92343
|
throw Error();
|
|
92034
92344
|
return value;
|
|
92035
92345
|
} catch {
|